installjammer

Check-in [28cb56af89]
aplsimple | Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:populating the repo
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 28cb56af895414bec41519b47f97b5d73ec903263b69355eb8ae1194e438c764
User & Date: apl 2024-10-05 16:38:28.899
Context
2024-10-05
17:12
ADDED tests/alited.mpi check-in: b66dcd30c1 user: apl tags: trunk
16:38
populating the repo check-in: 28cb56af89 user: apl tags: trunk
15:52
initial empty check-in check-in: 313eabe0cd user: aplsimple tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Added ANNOUNCE.txt.






























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
[29 October 2010]

ANNOUNCE: InstallJammer Multiplatform Installer, version 1.2.15

The InstallJammer Team is pleased to announce the release of
InstallJammer 1.2.15!

This release contains minor bug fixes and enhancements.

~ What is it?

InstallJammer is a free, open source, multiplatform
GUI installer and builder designed to be completely
cross-platform and function on Windows and most all
version of UNIX with eventual support for Mac OS X.

InstallJammer Features:

* A full-featured install builder.
* Installs are packaged in single binary executables for
  each platform making web distribution easy.
* Support for multiple install themes.
* Default install themes that resemble popular, commercial
  installers.
* A high level of configurability.
* Built-in support for Windows and Linux conventions.
* Automatic creation of an uninstaller.
* Easily extended to new platforms.


~ What's New in 1.2.15

This release contains minor bug fixes and enhancements.
Please see the Release Notes in the documentation for
a full list of changes.  The complete ChangeLog is
also included with each release.

Release Notes:
http://www.installjammer.com/docs/ReleaseNotes.html


~ Availability:

Home page:
http://www.installjammer.com/

Downloads are available at:
http://www.installjammer.com/download/

Windows Download
http://downloads.installjammer.com/installjammer/1.2/InstallJammer-1.2.15-Setup.exe

Linux Download
http://downloads.installjammer.com/installjammer/1.2/InstallJammer-1.2.15-Linux-x86-Install

All Other Platform Downloads
http://downloads.installjammer.com/installjammer/1.2/installjammer-1.2.15.tar.gz


Feedback and bug reports are greatly appreciated.

-
The InstallJammer Team
Added Binaries/AIX-ppc/installkit.

cannot compute difference between binary files

Added Binaries/FreeBSD-4-x86/installkit.

cannot compute difference between binary files

Added Binaries/FreeBSD-5-x86/installkit.

cannot compute difference between binary files

Added Binaries/FreeBSD-6-x86/Tktable2.9/README.txt.






















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Conceptually based on Tk3 table widget by Roland King (rols@lehman.com)
 *
 * see ChangeLog file for details
 *
 * current maintainer: jeff at hobbs org
 *
 * Copyright 1997-2002, Jeffrey Hobbs (jeff@hobbs.org)
 */

		*************************************
		  The Tk Table Widget Version 2.0+
		*************************************

INTRODUCTION

TkTable is a table/matrix widget extension to tk/tcl.
The basic features of the widget are:

 * multi-line cells
 * support for embedded windows (one per cell)
 * row & column spanning
 * variable width columns / height rows (interactively resizable)
 * row and column titles
 * multiple data sources ((Tcl array || Tcl command) &| internal caching)
 * supports standard Tk reliefs, fonts, colors, etc.
 * x/y scrollbar support
 * 'tag' styles per row, column or cell to change visual appearance
 * in-cell editing - returns value back to data source
 * support for disabled (read-only) tables or cells (via tags)
 * multiple selection modes, with "active" cell
 * multiple drawing modes to get optimal performance for larger tables
 * optional 'flashes' when things update
 * cell validation support
 * Works everywhere Tk does (including Windows and Mac!)
 * Unicode support (Tk8.1+)

FINDING THE WIDGET

0. The newest version is most likely found at:
	http://tktable.sourceforge.net/
	http://www.purl.org/net/hobbs/tcl/capp/

BUILDING AND INSTALLING THE WIDGET

1. Uncompress and unpack the distribution

   ON UNIX:
	gzip -cd Tktable<version>.tar.gz | tar xf -

   ON WINDOWS:
	use something like WinZip to unpack the archive.

   ON MACINTOSH:
	use StuffIt Expander to unstuff the archive.
    
   This will create a subdirectory tkTable<version> with all the files in it.

2. Configure

   ON UNIX:
        cd Tktable<version>
	./configure

   tkTable uses information left in tkConfig.sh when you built tk.  This
   file will be found in $exec_prefix/lib/.  You might set the --prefix and
   --exec-prefix options of configure if you don't want the default
   (/usr/local).  If building on multiple unix platforms, the following is
   recommended to isolate build conflicts:
	mkdir <builddir>/<platform>
	cd !$
	/path/to/Tktable<version>/configure

   ON WINDOWS:

   Version 2.8 added support for building in the cygwin environment on
   Windows based on TEA (http://www.tcl.tk/doc/tea/).  You can retrieve
   cygwin from:
	http://sources.redhat.com/cygwin/

   Inside the cygwin environment, you build the same as on Unix.

   Otherwise, hack makefile.vc until it works and compile.  It has problems
   executing wish from a path with a space in it, but the DLL builds just
   fine.  A DLL should be available where you found this archive.

   ON MACINTOSH:
   
   Hack the CodeWarrior XML project mac_tkTable.mcp.xml until it works and
   compile.  The access path to the Tcl/Tk source tree will probably need
   adjusting.  A DLL should be available where you found this archive.

3. Make and Install

   ON UNIX or WINDOWS (with cygwin):
	make
	make test (OPTIONAL)
	make install

   ON WINDOWS (makefile.vc):
	nmake -f makefile.vc
	nmake -f makefile.vc test (OPTIONAL)
	nmake -f makefile.vc install

   ON MACINTOSH:
	Place Tktable.shlb in the Tool Command Language folder

   tkTable is built to comply to the latest tcl package conventions.
   There is also a specific "make static" for those who need it.

4. Use it

   Start a regular wish interpreter, 'load' the library, and use the table.
   Or use the "tablewish" interpreter that has the 'table' command built in.
   There are a few test scripts in the demos directory which you can source.

5. Read the documentation

   There is a Unix manpage and HTML translation provided in the doc/
   subdirectory.  These describe the table widget's features and commands
   in depth.  If something is confusing, just to try it out.


THINGS TO WATCH OUT FOR

Packing
  The table tries not to allocate huge chunks of screen real estate if
  you ask it for a lot of rows and columns.  You can always stretch out
  the frame or explicitly tell it how big it can be.  If you want to
  stretch the table, remember to pack it with fill both and expand on,
  or with grid, give it -sticky news and configure the grid row and column
  for some weighting.

Array   
  The array elements for the table are of the form array(2,3) etc.  Make
  sure there are no spaces around the ','.  Negative indices are allowed.

Editing
  If you can't edit, remember that the focus model in tk is explicit, so
  you need to click on the table or give it the focus command.  Just
  having a selected cell is not the same thing as being able to edit.
  You also need the editing cursor.  If you can't get the cursor, make
  sure that you actually have a variable assigned to the table, and that
  the "state" of the cell is not disabled.

COMMENTS, BUGS, etc.

* Please can you send comments and bug reports to the current maintainer
  and their best will be done to address them.  A mailing list for
  tktable discussion is tktable-users@lists.sourceforge.net.

* If you find a bug, a short piece of Tcl that exercises it would be very
  useful, or even better, compile with debugging and specify where it
  crashed in that short piece of Tcl.  Use the SourceForge site to check
  for known bugs or submit new ones.
Added Binaries/FreeBSD-6-x86/Tktable2.9/libTktable2.9.so.

cannot compute difference between binary files

Added Binaries/FreeBSD-6-x86/Tktable2.9/license.txt.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
		   * COPYRIGHT AND LICENSE TERMS *

(This file blatantly stolen from Tcl/Tk license and adapted - thus assume
it falls under similar license terms).

This software is copyrighted by Jeffrey Hobbs <jeff at hobbs org>.  The
following terms apply to all files associated with the software unless
explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute, and
license this software and its documentation for any purpose, provided that
existing copyright notices are retained in all copies and that this notice
is included verbatim in any distributions.  No written agreement, license,
or royalty fee is required for any of the authorized uses.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS
PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government
is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
of the Rights in Technical Data and Computer Software Clause as DFARS
252.227-7013 and FAR 52.227-19.

SPECIAL NOTES:

This software also falls under the bourbon_ware clause:

    Should you find this software useful in your daily work, you should
    feel obliged to take the author out for a drink if the opportunity
    presents itself.  The user may feel exempt from this clause if they
    are under 21 or think the author has already partaken of too many
    drinks.
Added Binaries/FreeBSD-6-x86/Tktable2.9/pkgIndex.tcl.




>
>
1
2
if {[catch {package require Tcl 8.2}]} return
package ifneeded Tktable 2.9  [list load [file join $dir libTktable2.9.so] Tktable]
Added Binaries/FreeBSD-6-x86/Tktable2.9/tkTable.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
# table.tcl --
#
# Version align with tkTable 2.7, jeff at hobbs org
# This file defines the default bindings for Tk table widgets
# and provides procedures that help in implementing those bindings.
#
# RCS: @(#) $Id: tkTable.tcl,v 1.14 2005/07/12 23:26:28 hobbs Exp $

#--------------------------------------------------------------------------
# ::tk::table::Priv elements used in this file:
#
# x && y -		Coords in widget
# afterId -		Token returned by "after" for autoscanning.
# tablePrev -		The last element to be selected or deselected
#			during a selection operation.
# mouseMoved -		Boolean to indicate whether mouse moved while
#			the button was pressed.
# borderInfo -		Boolean to know if the user clicked on a border
# borderB1 -		Boolean that set whether B1 can be used for the
#			interactiving resizing
#--------------------------------------------------------------------------

namespace eval ::tk::table {
    # Ensure that a namespace is created for us
    variable Priv
    array set Priv [list x 0 y 0 afterId {} mouseMoved 0 \
	    borderInfo {} borderB1 1]
}

# ::tk::table::ClipboardKeysyms --
# This procedure is invoked to identify the keys that correspond to
# the "copy", "cut", and "paste" functions for the clipboard.
#
# Arguments:
# copy -	Name of the key (keysym name plus modifiers, if any,
#		such as "Meta-y") used for the copy operation.
# cut -		Name of the key used for the cut operation.
# paste -	Name of the key used for the paste operation.

proc ::tk::table::ClipboardKeysyms {copy cut paste} {
    bind Table <$copy>	{tk_tableCopy %W}
    bind Table <$cut>	{tk_tableCut %W}
    bind Table <$paste>	{tk_tablePaste %W}
}
::tk::table::ClipboardKeysyms <Copy> <Cut> <Paste>

##
## Interactive cell resizing, affected by -resizeborders option
##
bind Table <3>		{
    ## You might want to check for cell returned if you want to
    ## restrict the resizing of certain cells
    %W border mark %x %y
}
bind Table <B3-Motion>	{ %W border dragto %x %y }

## Button events

bind Table <1> { ::tk::table::Button1 %W %x %y }
bind Table <B1-Motion> { ::tk::table::B1Motion %W %x %y }

bind Table <ButtonRelease-1> {
    if {$::tk::table::Priv(borderInfo) == "" && [winfo exists %W]} {
	::tk::table::CancelRepeat
	%W activate @%x,%y
    }
}
bind Table <Double-1> {
    # empty
}

bind Table <Shift-1>	{::tk::table::BeginExtend %W [%W index @%x,%y]}
bind Table <Control-1>	{::tk::table::BeginToggle %W [%W index @%x,%y]}
bind Table <B1-Enter>	{::tk::table::CancelRepeat}
bind Table <B1-Leave>	{
    if {$::tk::table::Priv(borderInfo) == ""} {
	array set ::tk::table::Priv {x %x y %y}
	::tk::table::AutoScan %W
    }
}
bind Table <2> {
    %W scan mark %x %y
    array set ::tk::table::Priv {x %x y %y}
    set ::tk::table::Priv(mouseMoved) 0
}
bind Table <B2-Motion> {
    if {(%x != $::tk::table::Priv(x)) || (%y != $::tk::table::Priv(y))} {
	set ::tk::table::Priv(mouseMoved) 1
    }
    if {$::tk::table::Priv(mouseMoved)} { %W scan dragto %x %y }
}
bind Table <ButtonRelease-2> {
    if {!$::tk::table::Priv(mouseMoved)} { tk_tablePaste %W [%W index @%x,%y] }
}

## Key events

# This forces a cell commit if an active cell exists
bind Table <<Table_Commit>> {
    catch {%W activate active}
}
# Remove this if you don't want cell commit to occur on every Leave for
# the table (via mouse) or FocusOut (loss of focus by table).
event add <<Table_Commit>> <Leave> <FocusOut>

bind Table <Shift-Up>		{::tk::table::ExtendSelect %W -1  0}
bind Table <Shift-Down>		{::tk::table::ExtendSelect %W  1  0}
bind Table <Shift-Left>		{::tk::table::ExtendSelect %W  0 -1}
bind Table <Shift-Right>	{::tk::table::ExtendSelect %W  0  1}
bind Table <Prior>		{%W yview scroll -1 pages; %W activate topleft}
bind Table <Next>		{%W yview scroll  1 pages; %W activate topleft}
bind Table <Control-Prior>	{%W xview scroll -1 pages}
bind Table <Control-Next>	{%W xview scroll  1 pages}
bind Table <Home>		{%W see origin}
bind Table <End>		{%W see end}
bind Table <Control-Home> {
    %W selection clear all
    %W activate origin
    %W selection set active
    %W see active
}
bind Table <Control-End> {
    %W selection clear all
    %W activate end
    %W selection set active
    %W see active
}
bind Table <Shift-Control-Home>	{::tk::table::DataExtend %W origin}
bind Table <Shift-Control-End>	{::tk::table::DataExtend %W end}
bind Table <Select>		{::tk::table::BeginSelect %W [%W index active]}
bind Table <Shift-Select>	{::tk::table::BeginExtend %W [%W index active]}
bind Table <Control-slash>	{::tk::table::SelectAll %W}
bind Table <Control-backslash> {
    if {[string match browse [%W cget -selectmode]]} {%W selection clear all}
}
bind Table <Up>			{::tk::table::MoveCell %W -1  0}
bind Table <Down>		{::tk::table::MoveCell %W  1  0}
bind Table <Left>		{::tk::table::MoveCell %W  0 -1}
bind Table <Right>		{::tk::table::MoveCell %W  0  1}
bind Table <KeyPress>		{::tk::table::Insert %W %A}
bind Table <BackSpace>		{::tk::table::BackSpace %W}
bind Table <Delete>		{%W delete active insert}
bind Table <Escape>		{%W reread}

#bind Table <Return>		{::tk::table::MoveCell %W 1 0}
bind Table <Return>		{::tk::table::Insert %W "\n"}

bind Table <Control-Left>	{%W icursor [expr {[%W icursor]-1}]}
bind Table <Control-Right>	{%W icursor [expr {[%W icursor]+1}]}
bind Table <Control-e>		{%W icursor end}
bind Table <Control-a>		{%W icursor 0}
bind Table <Control-k>		{%W delete active insert end}
bind Table <Control-equal>	{::tk::table::ChangeWidth %W active  1}
bind Table <Control-minus>	{::tk::table::ChangeWidth %W active -1}

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# which is wrong.  Ditto for Tab.

bind Table <Alt-KeyPress>	{# nothing}
bind Table <Meta-KeyPress>	{# nothing}
bind Table <Control-KeyPress>	{# nothing}
bind Table <Any-Tab>		{# nothing}
if {[string match "macintosh" $::tcl_platform(platform)]} {
    bind Table <Command-KeyPress> {# nothing}
}

# ::tk::table::GetSelection --
#   This tries to obtain the default selection.  On Unix, we first try
#   and get a UTF8_STRING, a type supported by modern Unix apps for
#   passing Unicode data safely.  We fall back on the default STRING
#   type otherwise.  On Windows, only the STRING type is necessary.
# Arguments:
#   w	The widget for which the selection will be retrieved.
#	Important for the -displayof property.
#   sel	The source of the selection (PRIMARY or CLIPBOARD)
# Results:
#   Returns the selection, or an error if none could be found
#
if {[string compare $::tcl_platform(platform) "unix"]} {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
} else {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel \
		-type UTF8_STRING} txt] \
		&& [catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
}

# ::tk::table::CancelRepeat --
# A copy of tkCancelRepeat, just in case it's not available or changes.
# This procedure is invoked to cancel an auto-repeat action described
# by ::tk::table::Priv(afterId).  It's used by several widgets to auto-scroll
# the widget when the mouse is dragged out of the widget with a
# button pressed.
#
# Arguments:
# None.

proc ::tk::table::CancelRepeat {} {
    variable Priv
    after cancel $Priv(afterId)
    set Priv(afterId) {}
}

# ::tk::table::Insert --
#
#   Insert into the active cell
#
# Arguments:
#   w	- the table widget
#   s	- the string to insert
# Results:
#   Returns nothing
#
proc ::tk::table::Insert {w s} {
    if {[string compare $s {}]} {
	$w insert active insert $s
    }
}

# ::tk::table::BackSpace --
#
#   BackSpace in the current cell
#
# Arguments:
#   w	- the table widget
# Results:
#   Returns nothing
#
proc ::tk::table::BackSpace {w} {
    set cur [$w icursor]
    if {[string compare {} $cur] && $cur} {
	$w delete active [expr {$cur-1}]
    }
}

# ::tk::table::Button1 --
#
# This procedure is called to handle selecting with mouse button 1.
# It will distinguish whether to start selection or mark a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::Button1 {w x y} {
    variable Priv
    #
    # $Priv(borderInfo) is null if the user did not click on a border
    #
    if {$Priv(borderB1) == 1} {
	set Priv(borderInfo) [$w border mark $x $y]
	# account for what resizeborders are set [Bug 876320] (ferenc)
	set rbd [$w cget -resizeborders]
	if {$rbd == "none" || ![llength $Priv(borderInfo)]
	    || ($rbd == "col" && [lindex $Priv(borderInfo) 1] == "")
	    || ($rbd == "row" && [lindex $Priv(borderInfo) 0] == "")} {
	    set Priv(borderInfo) ""
	}
    } else {
	set Priv(borderInfo) ""
    }
    if {$Priv(borderInfo) == ""} {
	#
	# Only do this when a border wasn't selected
	#
	if {[winfo exists $w]} {
	    ::tk::table::BeginSelect $w [$w index @$x,$y]
	    focus $w
	}
	array set Priv [list x $x y $y]
	set Priv(mouseMoved) 0
    }
}

# ::tk::table::B1Motion --
#
# This procedure is called to start processing mouse motion events while
# button 1 moves while pressed.  It will distinguish whether to change
# the selection or move a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::B1Motion {w x y} {
    variable Priv

    # If we already had motion, or we moved more than 1 pixel,
    # then we start the Motion routine
    if {$Priv(borderInfo) != ""} {
	#
	# If the motion is on a border, drag it and skip the rest
	# of this binding.
	#
	$w border dragto $x $y
    } else {
	#
	# If we already had motion, or we moved more than 1 pixel,
	# then we start the Motion routine
	#
	if {
	    $::tk::table::Priv(mouseMoved)
	    || abs($x-$::tk::table::Priv(x)) > 1
	    || abs($y-$::tk::table::Priv(y)) > 1
	} {
	    set ::tk::table::Priv(mouseMoved) 1
	}
	if {$::tk::table::Priv(mouseMoved)} {
	    ::tk::table::Motion $w [$w index @$x,$y]
	}
    }
}

# ::tk::table::BeginSelect --
#
# This procedure is typically invoked on button-1 presses. It begins
# the process of making a selection in the table. Its exact behavior
# depends on the selection mode currently in effect for the table;
# see the Motif documentation for details.
#
# Arguments:
# w	- The table widget.
# el	- The element for the selection operation (typically the
#	one under the pointer).  Must be in row,col form.

proc ::tk::table::BeginSelect {w el} {
    variable Priv
    if {[scan $el %d,%d r c] != 2} return
    switch [$w cget -selectmode] {
	multiple {
	    if {[$w tag includes title $el]} {
		## in the title area
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			set inc topleft
			set el2 end
		    } else {
			set inc [$w index topleft row],$c
			set el2 [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    set inc $r,[$w index topleft col]
		    set el2 $r,[$w index end col]
		}
	    } else {
		set inc $el
		set el2 $el
	    }
	    if {[$w selection includes $inc]} {
		$w selection clear $el $el2
	    } else {
		$w selection set $el $el2
	    }
	}
	extended {
	    $w selection clear all
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection set $el end
		    } else {
			$w selection set $el [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    $w selection set $el $r,[$w index end col]
		}
	    } else {
		$w selection set $el
	    }
	    $w selection anchor $el
	    set Priv(tablePrev) $el
	}
	default {
	    if {![$w tag includes title $el]} {
		$w selection clear all
		$w selection set $el
		set Priv(tablePrev) $el
	    }
	    $w selection anchor $el
	}
    }
}

# ::tk::table::Motion --
#
# This procedure is called to process mouse motion events while
# button 1 is down. It may move or extend the selection, depending
# on the table's selection mode.
#
# Arguments:
# w	- The table widget.
# el	- The element under the pointer (must be in row,col form).

proc ::tk::table::Motion {w el} {
    variable Priv
    if {![info exists Priv(tablePrev)]} {
	set Priv(tablePrev) $el
	return
    }
    if {[string match $Priv(tablePrev) $el]} return
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set $el
	    set Priv(tablePrev) $el
	}
	extended {
	    # avoid tables that have no anchor index yet.
	    if {[catch {$w index anchor}]} { return }
	    scan $Priv(tablePrev) %d,%d r c
	    scan $el %d,%d elr elc
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection clear anchor end
		    } else {
			$w selection clear anchor [$w index end row],$c
		    }
		    $w selection set anchor [$w index end row],$elc
		} else {
		    ## We're in a row header
		    $w selection clear anchor $r,[$w index end col]
		    $w selection set anchor $elr,[$w index end col]
		}
	    } else {
		$w selection clear anchor $Priv(tablePrev)
		$w selection set anchor $el
	    }
	    set Priv(tablePrev) $el
	}
    }
}

# ::tk::table::BeginExtend --
#
# This procedure is typically invoked on shift-button-1 presses. It
# begins the process of extending a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginExtend {w el} {
    # avoid tables that have no anchor index yet.
    if {[catch {$w index anchor}]} { return }
    if {[string match extended [$w cget -selectmode]] &&
	[$w selection includes anchor]} {
	::tk::table::Motion $w $el
    }
}

# ::tk::table::BeginToggle --
#
# This procedure is typically invoked on control-button-1 presses. It
# begins the process of toggling a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginToggle {w el} {
    if {[string match extended [$w cget -selectmode]]} {
	variable Priv
	set Priv(tablePrev) $el
	$w selection anchor $el
	if {[$w tag includes title $el]} {
	    scan $el %d,%d r c
	    if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		## We're in a column header
		if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
		    ## We're in the topleft title area
		    set end end
		} else {
		    set end [$w index end row],$c
		}
	    } else {
		## We're in a row header
		set end $r,[$w index end col]
	    }
	} else {
	    ## We're in a non-title cell
	    set end $el
	}
	if {[$w selection includes  $end]} {
	    $w selection clear $el $end
	} else {
	    $w selection set   $el $end
        }
    }
}

# ::tk::table::AutoScan --
# This procedure is invoked when the mouse leaves an table window
# with button 1 down. It scrolls the window up, down, left, or
# right, depending on where the mouse left the window, and reschedules
# itself as an "after" command so that the window continues to scroll until
# the mouse moves back into the window or the mouse button is released.
#
# Arguments:
# w - The table window.

proc ::tk::table::AutoScan {w} {
    if {![winfo exists $w]} return
    variable Priv
    set x $Priv(x)
    set y $Priv(y)
    if {$y >= [winfo height $w]} {
	$w yview scroll 1 units
    } elseif {$y < 0} {
	$w yview scroll -1 units
    } elseif {$x >= [winfo width $w]} {
	$w xview scroll 1 units
    } elseif {$x < 0} {
	$w xview scroll -1 units
    } else {
	return
    }
    ::tk::table::Motion $w [$w index @$x,$y]
    set Priv(afterId) [after 50 ::tk::table::AutoScan $w]
}

# ::tk::table::MoveCell --
#
# Moves the location cursor (active element) by the specified number
# of cells and changes the selection if we're in browse or extended
# selection mode.  If the new cell is "hidden", we skip to the next
# visible cell if possible, otherwise just abort.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::MoveCell {w x y} {
    if {[catch {$w index active row} r]} return
    set c [$w index active col]
    set cell [$w index [incr r $x],[incr c $y]]
    while {[string compare [set true [$w hidden $cell]] {}]} {
	# The cell is in some way hidden
	if {[string compare $true [$w index active]]} {
	    # The span cell wasn't the previous cell, so go to that
	    set cell $true
	    break
	}
	if {$x > 0} {incr r} elseif {$x < 0} {incr r -1}
	if {$y > 0} {incr c} elseif {$y < 0} {incr c -1}
	if {[string compare $cell [$w index $r,$c]]} {
	    set cell [$w index $r,$c]
	} else {
	    # We couldn't find a non-hidden cell, just don't move
	    return
	}
    }
    $w activate $cell
    $w see active
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set active
	}
	extended {
	    variable Priv
	    $w selection clear all
	    $w selection set active
	    $w selection anchor active
	    set Priv(tablePrev) [$w index active]
	}
    }
}

# ::tk::table::ExtendSelect --
#
# Does nothing unless we're in extended selection mode; in this
# case it moves the location cursor (active element) by the specified
# number of cells, and extends the selection to that point.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::ExtendSelect {w x y} {
    if {[string compare extended [$w cget -selectmode]] ||
	[catch {$w index active row} r]} return
    set c [$w index active col]
    $w activate [incr r $x],[incr c $y]
    $w see active
    ::tk::table::Motion $w [$w index active]
}

# ::tk::table::DataExtend
#
# This procedure is called for key-presses such as Shift-KEndData.
# If the selection mode isnt multiple or extend then it does nothing.
# Otherwise it moves the active element to el and, if we're in
# extended mode, extends the selection to that point.
#
# Arguments:
# w - The table widget.
# el - An integer cell number.

proc ::tk::table::DataExtend {w el} {
    set mode [$w cget -selectmode]
    if {[string match extended $mode]} {
	$w activate $el
	$w see $el
	if {[$w selection includes anchor]} {::tk::table::Motion $w $el}
    } elseif {[string match multiple $mode]} {
	$w activate $el
	$w see $el
    }
}

# ::tk::table::SelectAll
#
# This procedure is invoked to handle the "select all" operation.
# For single and browse mode, it just selects the active element.
# Otherwise it selects everything in the widget.
#
# Arguments:
# w - The table widget.

proc ::tk::table::SelectAll {w} {
    if {[regexp {^(single|browse)$} [$w cget -selectmode]]} {
	$w selection clear all
	catch {$w selection set active}
    } elseif {[$w cget -selecttitles]} {
	$w selection set [$w cget -roworigin],[$w cget -colorigin] end
    } else {
	$w selection set origin end
    }
}

# ::tk::table::ChangeWidth --
#
# Adjust the widget of the specified cell by $a.
#
# Arguments:
# w - The table widget.
# i - cell index
# a - amount to adjust by

proc ::tk::table::ChangeWidth {w i a} {
    set tmp [$w index $i col]
    if {[set width [$w width $tmp]] >= 0} {
	$w width $tmp [incr width $a]
    } else {
	$w width $tmp [incr width [expr {-$a}]]
    }
}

# tk_tableCopy --
#
# This procedure copies the selection from a table widget into the
# clipboard.
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCopy w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {clipboard append -displayof $w [::tk::table::GetSelection $w]}
    }
}

# tk_tableCut --
#
# This procedure copies the selection from a table widget into the
# clipboard, then deletes the selection (if it exists in the given
# widget).
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCut w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {
	    clipboard append -displayof $w [::tk::table::GetSelection $w]
	    $w cursel {}
	    $w selection clear all
	}
    }
}

# tk_tablePaste --
#
# This procedure pastes the contents of the clipboard to the specified
# cell (active by default) in a table widget.
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePaste {w {cell {}}} {
    if {[string compare {} $cell]} {
	if {[catch {::tk::table::GetSelection $w} data]} return
    } else {
	if {[catch {::tk::table::GetSelection $w CLIPBOARD} data]} {
	    return
	}
	set cell active
    }
    tk_tablePasteHandler $w [$w index $cell] $data
    if {[$w cget -state] == "normal"} {focus $w}
}

# tk_tablePasteHandler --
#
# This procedure handles how data is pasted into the table widget.
# This handles data in the default table selection form.
#
# NOTE: this allows pasting into all cells except title cells,
#       even those with -state disabled
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePasteHandler {w cell data} {
    #
    # Don't allow pasting into the title cells
    #
    if {[$w tag includes title $cell]} {
        return
    }

    set rows	[expr {[$w cget -rows]-[$w cget -roworigin]}]
    set cols	[expr {[$w cget -cols]-[$w cget -colorigin]}]
    set r	[$w index $cell row]
    set c	[$w index $cell col]
    set rsep	[$w cget -rowseparator]
    set csep	[$w cget -colseparator]
    ## Assume separate rows are split by row separator if specified
    ## If you were to want multi-character row separators, you would need:
    # regsub -all $rsep $data <newline> data
    # set data [join $data <newline>]
    if {[string compare {} $rsep]} { set data [split $data $rsep] }
    set row	$r
    foreach line $data {
	if {$row > $rows} break
	set col	$c
	## Assume separate cols are split by col separator if specified
	## Unless a -separator was specified
	if {[string compare {} $csep]} { set line [split $line $csep] }
	## If you were to want multi-character col separators, you would need:
	# regsub -all $csep $line <newline> line
	# set line [join $line <newline>]
	foreach item $line {
	    if {$col > $cols} break
	    $w set $row,$col $item
	    incr col
	}
	incr row
    }
}

# tk::table::Sort --
#
# This procedure handles how data is sorted in the table widget.
# This isn't currently used by tktable, but can be called by the user.
# It's behavior may change in the future.
#
# Arguments:
# w -		Name of a table widget.
# start -	start cell of rectangle to sort
# end -		end cell of rectangle to sort
# col -		column within rectangle to sort on
# args -	passed to lsort proc (ie: -integer -decreasing)

proc ::tk::table::Sort {w start end col args} {
    set start [$w index $start]
    set end   [$w index $end]
    scan $start %d,%d sr sc
    scan $end   %d,%d er ec
    if {($col < $sc) || ($col > $ec)} {
	return -code error "$col is not within sort range $sc to $ec"
    }
    set col [expr {$col - $sc}]

    set data {}
    for {set i $sr} {$i <= $er} {incr i} {
	lappend data [$w get $i,$sc $i,$ec]
    }

    set i $sr
    foreach row [eval [list lsort -index $col] $args [list $data]] {
	$w set row $i,$sc $row
	incr i
    }
}
Added Binaries/FreeBSD-6-x86/craplzma0.1/libcraplzma0.1.so.

cannot compute difference between binary files

Added Binaries/FreeBSD-6-x86/craplzma0.1/pkgIndex.tcl.










>
>
>
>
>
1
2
3
4
5
#
# Tcl package index file
#
package ifneeded miniarc::crap::lzma 0.1 \
    [list load [file join $dir libcraplzma0.1.so] craplzma]
Added Binaries/FreeBSD-6-x86/installkit.

cannot compute difference between binary files

Added Binaries/FreeBSD-6-x86/tkdnd1.0/License.txt.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
This software (tkdnd) is copyrighted by:
    George Petasis,
    Software and Knowledge Engineering Laboratory,
    Institute of Informatics and Telecommunications,
    National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and 
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

The following terms apply to all files associated
with the software unless explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
Added Binaries/FreeBSD-6-x86/tkdnd1.0/Readme.txt.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
                  
	    tkdnd: Tk Drag & Drop extension
		     (Version 1.0.0)

This directory holds a collection of files that add native drag & drop
capabilities to the tk toolkit. It is designed for tk versions >= 8.3.3,
but with simple modifications can be applied to any tk version greater than
8.1.

Remember that this software is in development. Please report any bugs or
feature requests directly to the author (petasis@iit.demokritos.gr) or by
posting on the comp.lang.tcl newsgroup. In the latter case, please use
"tkdnd" in the title of the posting.

This software (tkdnd) is copyrighted by:
    George Petasis, National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

and is under the same license that covers tcl. Free to use for anything :-)

For any questions and suggestions contact me at

  petasis@iit.demokritos.gr

or post a question at comp.lang.tcl (preferable)
Added Binaries/FreeBSD-6-x86/tkdnd1.0/libtkdnd1.0.so.

cannot compute difference between binary files

Added Binaries/FreeBSD-6-x86/tkdnd1.0/pkgIndex.tcl.






















>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
namespace eval ::dnd {
    proc _load {dir} {
	set version 1.0
	load [file join $dir libtkdnd1.0.so] tkdnd
	source [file join $dir tkdnd.tcl]
	package provide tkdnd 1.0
	rename ::dnd::_load {}
    }
}

package ifneeded tkdnd 1.0  [list ::dnd::_load $dir]
Added Binaries/FreeBSD-6-x86/tkdnd1.0/tkdnd.tcl.
















































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#
# tkdnd.tcl --
# 
#    This file implements some utility procedures that are used by the tkDND
#    package.
#
# This software is copyrighted by:
# George Petasis, National Centre for Scientific Research "Demokritos",
# Aghia Paraskevi, Athens, Greece.
# e-mail: petasis@iit.demokritos.gr
#
# The following terms apply to all files associated
# with the software unless explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
# and license this software and its documentation for any purpose, provided
# that existing copyright notices are retained in all copies and that this
# notice is included verbatim in any distributions. No written agreement,
# license, or royalty fee is required for any of the authorized uses.
# Modifications to this software may be copyrighted by their authors
# and need not follow the licensing terms described here, provided that
# the new terms are clearly indicated on the first page of each file where
# they apply.
# 
# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# 
# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
# MODIFICATIONS.
#

namespace eval ::dnd {
    variable AskSelectedAction
    
    # This procedure is used just to ensure that the object given as its
    # argument can be accessed as a binary object. Many thanks to Paul Duffin
    # for the idea :-)
    proc ConvertToBinary {object} {
	binary scan $object {}
	return $object
    }

    # This procedure handles the special case where we want items into a canvas
    # widget to be drop targets. It emulates this case as follows:
    #
    #  The tkDND extension is able to deliver events only to real windows
    #  (that means tk widgets). This procedure can be the binding script of all
    #  dnd events we are interested in being received by the canvas items.
    #  When this function is called, it tries to find the item that the mouse
    #  is over (if any). Then it examines its bindings, and if it finds the
    #  dnd related event that is processing it delivers this event to the
    #  particular item. Fianlly, it tries to emulate <DragEnter>/<DragLeave>
    #  on every canvas item...
    proc CanvasDeliverEvent {
	event actions action button source_codes curr_code data descriptions
	mods type source_types win X x Y y
    } {
	# This function will find the topmost item that the mouse is over, and
	# Deliver the event specified by the "event" arg to this item...
	global CanvasDeliverEventStatus
	switch $event {
	    <DragEnter>  -
	    <<DragEnter>> {set CanvasDeliverEventStatus(item) {}}
	    default {}
	}

	# Translate mouse coordinates to canvas coordinates...
	set cx [$win canvasx $x]
	set cy [$win canvasy $y]
	set cx_1 [expr {$cx+1}]
	set cy_1 [expr {$cy+1}]
	# Find all tags that are under the mouse...
	set tags [$win find overlapping $cx $cy $cx_1 $cy_1]
	# ... and select the topmost...
	set length [llength $tags]

	# If no tags under the mouse, return...
	if {!$length} {
	    #puts -->$CanvasDeliverEventStatus(item)
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (1) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    set CanvasDeliverEventStatus(item) {}
	    update
	    if {[string equal $event <<Drag>>]} {
		return -code break
	    }
	    return $action
	}
	if {$length == 1} {
	    set id $tags
	} else {
	    set id [$win find closest $cx $cy]
	}

	# Now in "id" we have the tag of the item below the mouse...
	# Has this item a binding?
	foreach tag [concat $id [$win gettags $id]] {
	    set binding [$win bind $tag $event]
	    if {[string length $binding]} {break}
	}
	
	# Is this tag the same as the last one? If is different, we
	# have to send a leave event to the previous item and an enter
	# event to this one...
	if {$CanvasDeliverEventStatus(item) != $id} {
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (2) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    # Send <<DndEnter>>...
	    set _id $id
	    set _binding {}
	    foreach _tag [concat $_id [$win gettags $_id]] {
		set _binding [$win bind $_tag <<DragEnter>>]
		if {[string length $_binding]} {break}
	    }
	    # puts "Sending <DragEnter> to $tag ($_binding)"
	    set script {}
	    foreach element $_binding {
		switch $element {
		    %% {lappend script %}       
		    %A {lappend script $action}
		    %a {lappend script $actions}
		    %b {lappend script $button}
		    %C {lappend script $source_codes}
		    %c {lappend script $curr_code}
		    %D {lappend script $data}
		    %d {lappend script $descriptions}
		    %m {lappend script $mods}
		    %T {lappend script $type}
		    %t {lappend script $source_types}
		    %W {lappend script $win}
		    %X {lappend script $X}
		    %x {lappend script $x}
		    %Y {lappend script $Y}
		    %y {lappend script $y}
		    %I {lappend script $_id}
		    default {lappend script $element}
		}
	    }
	    if {[llength $script]} {uplevel 1 $script}
	    set CanvasDeliverEventStatus(item) $id
	}

	set script {}
	foreach element $binding {
	    switch $element {
		%% {lappend script %}       
		%A {lappend script $action}
		%a {lappend script $actions}
		%b {lappend script $button}
		%C {lappend script $source_codes}
		%c {lappend script $curr_code}
		%D {lappend script $data}
		%d {lappend script $descriptions}
		%m {lappend script $mods}
		%T {lappend script $type}
		%t {lappend script $source_types}
		%W {lappend script $win}
		%X {lappend script $X}
		%x {lappend script $x}
		%Y {lappend script $Y}
		%y {lappend script $y}
		%I {lappend script $id}
		default {lappend script $element}
	    }
	}
	if {[llength $script]} {
	    return [uplevel 1 $script]
	}
	set CanvasDeliverEventStatus(item) {}
	update
	if {[string equal $event <<Drag>>]} {
	    return -code break
	}
	return $action
    }

    # ChooseAskAction --
    #   This procedure displays a dialog with the help of which the user can
    #   select one of the supported actions...
    proc ChooseAskAction {window x y actions descriptions args} {
	variable AskSelectedAction
	set title {Please Select Action:}
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} {
		set title $descr
		break
	    }
	}

	set menu $window.__tk_dnd[pwd]__action_ask__Drop_window_[pid]
	catch {destroy $menu}
	menu $menu -title $title -tearoff 0 -disabledforeground darkgreen
	$menu add command -font {helvetica 12 bold} \
		-label $title -command "destroy $menu" -state disabled
	$menu add separator

	set items 0
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} continue
	    $menu add command -label $descr -command \
		    "set ::dnd::AskSelectedAction $action; destroy $menu"
	    incr items
	}
	if {!$items} {
	    # The drag source accepts the ask action, but has no defined
	    # action list? Add copy action at least...
	    $menu add command -label Copy -command \
		    "set ::dnd::AskSelectedAction copy; destroy $menu"
	}
	
	$menu add separator
	$menu add command -label {Cancel Drop} -command \
		"set ::dnd::AskSelectedAction none; destroy $menu"

	set AskSelectedAction none
	tk_popup $menu $x $y
	update
	bind $menu <Unmap> {after idle {catch {destroy %W}}}
	tkwait window $menu
	
	return $AskSelectedAction
    }
};# namespace eval ::dnd

# EOF
Added Binaries/FreeBSD-7-x86/Tktable2.9/README.txt.






















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Conceptually based on Tk3 table widget by Roland King (rols@lehman.com)
 *
 * see ChangeLog file for details
 *
 * current maintainer: jeff at hobbs org
 *
 * Copyright 1997-2002, Jeffrey Hobbs (jeff@hobbs.org)
 */

		*************************************
		  The Tk Table Widget Version 2.0+
		*************************************

INTRODUCTION

TkTable is a table/matrix widget extension to tk/tcl.
The basic features of the widget are:

 * multi-line cells
 * support for embedded windows (one per cell)
 * row & column spanning
 * variable width columns / height rows (interactively resizable)
 * row and column titles
 * multiple data sources ((Tcl array || Tcl command) &| internal caching)
 * supports standard Tk reliefs, fonts, colors, etc.
 * x/y scrollbar support
 * 'tag' styles per row, column or cell to change visual appearance
 * in-cell editing - returns value back to data source
 * support for disabled (read-only) tables or cells (via tags)
 * multiple selection modes, with "active" cell
 * multiple drawing modes to get optimal performance for larger tables
 * optional 'flashes' when things update
 * cell validation support
 * Works everywhere Tk does (including Windows and Mac!)
 * Unicode support (Tk8.1+)

FINDING THE WIDGET

0. The newest version is most likely found at:
	http://tktable.sourceforge.net/
	http://www.purl.org/net/hobbs/tcl/capp/

BUILDING AND INSTALLING THE WIDGET

1. Uncompress and unpack the distribution

   ON UNIX:
	gzip -cd Tktable<version>.tar.gz | tar xf -

   ON WINDOWS:
	use something like WinZip to unpack the archive.

   ON MACINTOSH:
	use StuffIt Expander to unstuff the archive.
    
   This will create a subdirectory tkTable<version> with all the files in it.

2. Configure

   ON UNIX:
        cd Tktable<version>
	./configure

   tkTable uses information left in tkConfig.sh when you built tk.  This
   file will be found in $exec_prefix/lib/.  You might set the --prefix and
   --exec-prefix options of configure if you don't want the default
   (/usr/local).  If building on multiple unix platforms, the following is
   recommended to isolate build conflicts:
	mkdir <builddir>/<platform>
	cd !$
	/path/to/Tktable<version>/configure

   ON WINDOWS:

   Version 2.8 added support for building in the cygwin environment on
   Windows based on TEA (http://www.tcl.tk/doc/tea/).  You can retrieve
   cygwin from:
	http://sources.redhat.com/cygwin/

   Inside the cygwin environment, you build the same as on Unix.

   Otherwise, hack makefile.vc until it works and compile.  It has problems
   executing wish from a path with a space in it, but the DLL builds just
   fine.  A DLL should be available where you found this archive.

   ON MACINTOSH:
   
   Hack the CodeWarrior XML project mac_tkTable.mcp.xml until it works and
   compile.  The access path to the Tcl/Tk source tree will probably need
   adjusting.  A DLL should be available where you found this archive.

3. Make and Install

   ON UNIX or WINDOWS (with cygwin):
	make
	make test (OPTIONAL)
	make install

   ON WINDOWS (makefile.vc):
	nmake -f makefile.vc
	nmake -f makefile.vc test (OPTIONAL)
	nmake -f makefile.vc install

   ON MACINTOSH:
	Place Tktable.shlb in the Tool Command Language folder

   tkTable is built to comply to the latest tcl package conventions.
   There is also a specific "make static" for those who need it.

4. Use it

   Start a regular wish interpreter, 'load' the library, and use the table.
   Or use the "tablewish" interpreter that has the 'table' command built in.
   There are a few test scripts in the demos directory which you can source.

5. Read the documentation

   There is a Unix manpage and HTML translation provided in the doc/
   subdirectory.  These describe the table widget's features and commands
   in depth.  If something is confusing, just to try it out.


THINGS TO WATCH OUT FOR

Packing
  The table tries not to allocate huge chunks of screen real estate if
  you ask it for a lot of rows and columns.  You can always stretch out
  the frame or explicitly tell it how big it can be.  If you want to
  stretch the table, remember to pack it with fill both and expand on,
  or with grid, give it -sticky news and configure the grid row and column
  for some weighting.

Array   
  The array elements for the table are of the form array(2,3) etc.  Make
  sure there are no spaces around the ','.  Negative indices are allowed.

Editing
  If you can't edit, remember that the focus model in tk is explicit, so
  you need to click on the table or give it the focus command.  Just
  having a selected cell is not the same thing as being able to edit.
  You also need the editing cursor.  If you can't get the cursor, make
  sure that you actually have a variable assigned to the table, and that
  the "state" of the cell is not disabled.

COMMENTS, BUGS, etc.

* Please can you send comments and bug reports to the current maintainer
  and their best will be done to address them.  A mailing list for
  tktable discussion is tktable-users@lists.sourceforge.net.

* If you find a bug, a short piece of Tcl that exercises it would be very
  useful, or even better, compile with debugging and specify where it
  crashed in that short piece of Tcl.  Use the SourceForge site to check
  for known bugs or submit new ones.
Added Binaries/FreeBSD-7-x86/Tktable2.9/libTktable2.9.so.

cannot compute difference between binary files

Added Binaries/FreeBSD-7-x86/Tktable2.9/license.txt.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
		   * COPYRIGHT AND LICENSE TERMS *

(This file blatantly stolen from Tcl/Tk license and adapted - thus assume
it falls under similar license terms).

This software is copyrighted by Jeffrey Hobbs <jeff at hobbs org>.  The
following terms apply to all files associated with the software unless
explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute, and
license this software and its documentation for any purpose, provided that
existing copyright notices are retained in all copies and that this notice
is included verbatim in any distributions.  No written agreement, license,
or royalty fee is required for any of the authorized uses.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS
PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government
is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
of the Rights in Technical Data and Computer Software Clause as DFARS
252.227-7013 and FAR 52.227-19.

SPECIAL NOTES:

This software also falls under the bourbon_ware clause:

    Should you find this software useful in your daily work, you should
    feel obliged to take the author out for a drink if the opportunity
    presents itself.  The user may feel exempt from this clause if they
    are under 21 or think the author has already partaken of too many
    drinks.
Added Binaries/FreeBSD-7-x86/Tktable2.9/pkgIndex.tcl.






>
>
>
1
2
3
if {[catch {package require Tcl 8.2}]} return
package ifneeded Tktable 2.9 \
    [list load [file join $dir libTktable2.9.so] Tktable]
Added Binaries/FreeBSD-7-x86/Tktable2.9/tkTable.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
# table.tcl --
#
# Version align with tkTable 2.7, jeff at hobbs org
# This file defines the default bindings for Tk table widgets
# and provides procedures that help in implementing those bindings.
#
# RCS: @(#) $Id: tkTable.tcl,v 1.14 2005/07/12 23:26:28 hobbs Exp $

#--------------------------------------------------------------------------
# ::tk::table::Priv elements used in this file:
#
# x && y -		Coords in widget
# afterId -		Token returned by "after" for autoscanning.
# tablePrev -		The last element to be selected or deselected
#			during a selection operation.
# mouseMoved -		Boolean to indicate whether mouse moved while
#			the button was pressed.
# borderInfo -		Boolean to know if the user clicked on a border
# borderB1 -		Boolean that set whether B1 can be used for the
#			interactiving resizing
#--------------------------------------------------------------------------

namespace eval ::tk::table {
    # Ensure that a namespace is created for us
    variable Priv
    array set Priv [list x 0 y 0 afterId {} mouseMoved 0 \
	    borderInfo {} borderB1 1]
}

# ::tk::table::ClipboardKeysyms --
# This procedure is invoked to identify the keys that correspond to
# the "copy", "cut", and "paste" functions for the clipboard.
#
# Arguments:
# copy -	Name of the key (keysym name plus modifiers, if any,
#		such as "Meta-y") used for the copy operation.
# cut -		Name of the key used for the cut operation.
# paste -	Name of the key used for the paste operation.

proc ::tk::table::ClipboardKeysyms {copy cut paste} {
    bind Table <$copy>	{tk_tableCopy %W}
    bind Table <$cut>	{tk_tableCut %W}
    bind Table <$paste>	{tk_tablePaste %W}
}
::tk::table::ClipboardKeysyms <Copy> <Cut> <Paste>

##
## Interactive cell resizing, affected by -resizeborders option
##
bind Table <3>		{
    ## You might want to check for cell returned if you want to
    ## restrict the resizing of certain cells
    %W border mark %x %y
}
bind Table <B3-Motion>	{ %W border dragto %x %y }

## Button events

bind Table <1> { ::tk::table::Button1 %W %x %y }
bind Table <B1-Motion> { ::tk::table::B1Motion %W %x %y }

bind Table <ButtonRelease-1> {
    if {$::tk::table::Priv(borderInfo) == "" && [winfo exists %W]} {
	::tk::table::CancelRepeat
	%W activate @%x,%y
    }
}
bind Table <Double-1> {
    # empty
}

bind Table <Shift-1>	{::tk::table::BeginExtend %W [%W index @%x,%y]}
bind Table <Control-1>	{::tk::table::BeginToggle %W [%W index @%x,%y]}
bind Table <B1-Enter>	{::tk::table::CancelRepeat}
bind Table <B1-Leave>	{
    if {$::tk::table::Priv(borderInfo) == ""} {
	array set ::tk::table::Priv {x %x y %y}
	::tk::table::AutoScan %W
    }
}
bind Table <2> {
    %W scan mark %x %y
    array set ::tk::table::Priv {x %x y %y}
    set ::tk::table::Priv(mouseMoved) 0
}
bind Table <B2-Motion> {
    if {(%x != $::tk::table::Priv(x)) || (%y != $::tk::table::Priv(y))} {
	set ::tk::table::Priv(mouseMoved) 1
    }
    if {$::tk::table::Priv(mouseMoved)} { %W scan dragto %x %y }
}
bind Table <ButtonRelease-2> {
    if {!$::tk::table::Priv(mouseMoved)} { tk_tablePaste %W [%W index @%x,%y] }
}

## Key events

# This forces a cell commit if an active cell exists
bind Table <<Table_Commit>> {
    catch {%W activate active}
}
# Remove this if you don't want cell commit to occur on every Leave for
# the table (via mouse) or FocusOut (loss of focus by table).
event add <<Table_Commit>> <Leave> <FocusOut>

bind Table <Shift-Up>		{::tk::table::ExtendSelect %W -1  0}
bind Table <Shift-Down>		{::tk::table::ExtendSelect %W  1  0}
bind Table <Shift-Left>		{::tk::table::ExtendSelect %W  0 -1}
bind Table <Shift-Right>	{::tk::table::ExtendSelect %W  0  1}
bind Table <Prior>		{%W yview scroll -1 pages; %W activate topleft}
bind Table <Next>		{%W yview scroll  1 pages; %W activate topleft}
bind Table <Control-Prior>	{%W xview scroll -1 pages}
bind Table <Control-Next>	{%W xview scroll  1 pages}
bind Table <Home>		{%W see origin}
bind Table <End>		{%W see end}
bind Table <Control-Home> {
    %W selection clear all
    %W activate origin
    %W selection set active
    %W see active
}
bind Table <Control-End> {
    %W selection clear all
    %W activate end
    %W selection set active
    %W see active
}
bind Table <Shift-Control-Home>	{::tk::table::DataExtend %W origin}
bind Table <Shift-Control-End>	{::tk::table::DataExtend %W end}
bind Table <Select>		{::tk::table::BeginSelect %W [%W index active]}
bind Table <Shift-Select>	{::tk::table::BeginExtend %W [%W index active]}
bind Table <Control-slash>	{::tk::table::SelectAll %W}
bind Table <Control-backslash> {
    if {[string match browse [%W cget -selectmode]]} {%W selection clear all}
}
bind Table <Up>			{::tk::table::MoveCell %W -1  0}
bind Table <Down>		{::tk::table::MoveCell %W  1  0}
bind Table <Left>		{::tk::table::MoveCell %W  0 -1}
bind Table <Right>		{::tk::table::MoveCell %W  0  1}
bind Table <KeyPress>		{::tk::table::Insert %W %A}
bind Table <BackSpace>		{::tk::table::BackSpace %W}
bind Table <Delete>		{%W delete active insert}
bind Table <Escape>		{%W reread}

#bind Table <Return>		{::tk::table::MoveCell %W 1 0}
bind Table <Return>		{::tk::table::Insert %W "\n"}

bind Table <Control-Left>	{%W icursor [expr {[%W icursor]-1}]}
bind Table <Control-Right>	{%W icursor [expr {[%W icursor]+1}]}
bind Table <Control-e>		{%W icursor end}
bind Table <Control-a>		{%W icursor 0}
bind Table <Control-k>		{%W delete active insert end}
bind Table <Control-equal>	{::tk::table::ChangeWidth %W active  1}
bind Table <Control-minus>	{::tk::table::ChangeWidth %W active -1}

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# which is wrong.  Ditto for Tab.

bind Table <Alt-KeyPress>	{# nothing}
bind Table <Meta-KeyPress>	{# nothing}
bind Table <Control-KeyPress>	{# nothing}
bind Table <Any-Tab>		{# nothing}
if {[string match "macintosh" $::tcl_platform(platform)]} {
    bind Table <Command-KeyPress> {# nothing}
}

# ::tk::table::GetSelection --
#   This tries to obtain the default selection.  On Unix, we first try
#   and get a UTF8_STRING, a type supported by modern Unix apps for
#   passing Unicode data safely.  We fall back on the default STRING
#   type otherwise.  On Windows, only the STRING type is necessary.
# Arguments:
#   w	The widget for which the selection will be retrieved.
#	Important for the -displayof property.
#   sel	The source of the selection (PRIMARY or CLIPBOARD)
# Results:
#   Returns the selection, or an error if none could be found
#
if {[string compare $::tcl_platform(platform) "unix"]} {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
} else {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel \
		-type UTF8_STRING} txt] \
		&& [catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
}

# ::tk::table::CancelRepeat --
# A copy of tkCancelRepeat, just in case it's not available or changes.
# This procedure is invoked to cancel an auto-repeat action described
# by ::tk::table::Priv(afterId).  It's used by several widgets to auto-scroll
# the widget when the mouse is dragged out of the widget with a
# button pressed.
#
# Arguments:
# None.

proc ::tk::table::CancelRepeat {} {
    variable Priv
    after cancel $Priv(afterId)
    set Priv(afterId) {}
}

# ::tk::table::Insert --
#
#   Insert into the active cell
#
# Arguments:
#   w	- the table widget
#   s	- the string to insert
# Results:
#   Returns nothing
#
proc ::tk::table::Insert {w s} {
    if {[string compare $s {}]} {
	$w insert active insert $s
    }
}

# ::tk::table::BackSpace --
#
#   BackSpace in the current cell
#
# Arguments:
#   w	- the table widget
# Results:
#   Returns nothing
#
proc ::tk::table::BackSpace {w} {
    set cur [$w icursor]
    if {[string compare {} $cur] && $cur} {
	$w delete active [expr {$cur-1}]
    }
}

# ::tk::table::Button1 --
#
# This procedure is called to handle selecting with mouse button 1.
# It will distinguish whether to start selection or mark a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::Button1 {w x y} {
    variable Priv
    #
    # $Priv(borderInfo) is null if the user did not click on a border
    #
    if {$Priv(borderB1) == 1} {
	set Priv(borderInfo) [$w border mark $x $y]
	# account for what resizeborders are set [Bug 876320] (ferenc)
	set rbd [$w cget -resizeborders]
	if {$rbd == "none" || ![llength $Priv(borderInfo)]
	    || ($rbd == "col" && [lindex $Priv(borderInfo) 1] == "")
	    || ($rbd == "row" && [lindex $Priv(borderInfo) 0] == "")} {
	    set Priv(borderInfo) ""
	}
    } else {
	set Priv(borderInfo) ""
    }
    if {$Priv(borderInfo) == ""} {
	#
	# Only do this when a border wasn't selected
	#
	if {[winfo exists $w]} {
	    ::tk::table::BeginSelect $w [$w index @$x,$y]
	    focus $w
	}
	array set Priv [list x $x y $y]
	set Priv(mouseMoved) 0
    }
}

# ::tk::table::B1Motion --
#
# This procedure is called to start processing mouse motion events while
# button 1 moves while pressed.  It will distinguish whether to change
# the selection or move a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::B1Motion {w x y} {
    variable Priv

    # If we already had motion, or we moved more than 1 pixel,
    # then we start the Motion routine
    if {$Priv(borderInfo) != ""} {
	#
	# If the motion is on a border, drag it and skip the rest
	# of this binding.
	#
	$w border dragto $x $y
    } else {
	#
	# If we already had motion, or we moved more than 1 pixel,
	# then we start the Motion routine
	#
	if {
	    $::tk::table::Priv(mouseMoved)
	    || abs($x-$::tk::table::Priv(x)) > 1
	    || abs($y-$::tk::table::Priv(y)) > 1
	} {
	    set ::tk::table::Priv(mouseMoved) 1
	}
	if {$::tk::table::Priv(mouseMoved)} {
	    ::tk::table::Motion $w [$w index @$x,$y]
	}
    }
}

# ::tk::table::BeginSelect --
#
# This procedure is typically invoked on button-1 presses. It begins
# the process of making a selection in the table. Its exact behavior
# depends on the selection mode currently in effect for the table;
# see the Motif documentation for details.
#
# Arguments:
# w	- The table widget.
# el	- The element for the selection operation (typically the
#	one under the pointer).  Must be in row,col form.

proc ::tk::table::BeginSelect {w el} {
    variable Priv
    if {[scan $el %d,%d r c] != 2} return
    switch [$w cget -selectmode] {
	multiple {
	    if {[$w tag includes title $el]} {
		## in the title area
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			set inc topleft
			set el2 end
		    } else {
			set inc [$w index topleft row],$c
			set el2 [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    set inc $r,[$w index topleft col]
		    set el2 $r,[$w index end col]
		}
	    } else {
		set inc $el
		set el2 $el
	    }
	    if {[$w selection includes $inc]} {
		$w selection clear $el $el2
	    } else {
		$w selection set $el $el2
	    }
	}
	extended {
	    $w selection clear all
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection set $el end
		    } else {
			$w selection set $el [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    $w selection set $el $r,[$w index end col]
		}
	    } else {
		$w selection set $el
	    }
	    $w selection anchor $el
	    set Priv(tablePrev) $el
	}
	default {
	    if {![$w tag includes title $el]} {
		$w selection clear all
		$w selection set $el
		set Priv(tablePrev) $el
	    }
	    $w selection anchor $el
	}
    }
}

# ::tk::table::Motion --
#
# This procedure is called to process mouse motion events while
# button 1 is down. It may move or extend the selection, depending
# on the table's selection mode.
#
# Arguments:
# w	- The table widget.
# el	- The element under the pointer (must be in row,col form).

proc ::tk::table::Motion {w el} {
    variable Priv
    if {![info exists Priv(tablePrev)]} {
	set Priv(tablePrev) $el
	return
    }
    if {[string match $Priv(tablePrev) $el]} return
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set $el
	    set Priv(tablePrev) $el
	}
	extended {
	    # avoid tables that have no anchor index yet.
	    if {[catch {$w index anchor}]} { return }
	    scan $Priv(tablePrev) %d,%d r c
	    scan $el %d,%d elr elc
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection clear anchor end
		    } else {
			$w selection clear anchor [$w index end row],$c
		    }
		    $w selection set anchor [$w index end row],$elc
		} else {
		    ## We're in a row header
		    $w selection clear anchor $r,[$w index end col]
		    $w selection set anchor $elr,[$w index end col]
		}
	    } else {
		$w selection clear anchor $Priv(tablePrev)
		$w selection set anchor $el
	    }
	    set Priv(tablePrev) $el
	}
    }
}

# ::tk::table::BeginExtend --
#
# This procedure is typically invoked on shift-button-1 presses. It
# begins the process of extending a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginExtend {w el} {
    # avoid tables that have no anchor index yet.
    if {[catch {$w index anchor}]} { return }
    if {[string match extended [$w cget -selectmode]] &&
	[$w selection includes anchor]} {
	::tk::table::Motion $w $el
    }
}

# ::tk::table::BeginToggle --
#
# This procedure is typically invoked on control-button-1 presses. It
# begins the process of toggling a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginToggle {w el} {
    if {[string match extended [$w cget -selectmode]]} {
	variable Priv
	set Priv(tablePrev) $el
	$w selection anchor $el
	if {[$w tag includes title $el]} {
	    scan $el %d,%d r c
	    if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		## We're in a column header
		if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
		    ## We're in the topleft title area
		    set end end
		} else {
		    set end [$w index end row],$c
		}
	    } else {
		## We're in a row header
		set end $r,[$w index end col]
	    }
	} else {
	    ## We're in a non-title cell
	    set end $el
	}
	if {[$w selection includes  $end]} {
	    $w selection clear $el $end
	} else {
	    $w selection set   $el $end
        }
    }
}

# ::tk::table::AutoScan --
# This procedure is invoked when the mouse leaves an table window
# with button 1 down. It scrolls the window up, down, left, or
# right, depending on where the mouse left the window, and reschedules
# itself as an "after" command so that the window continues to scroll until
# the mouse moves back into the window or the mouse button is released.
#
# Arguments:
# w - The table window.

proc ::tk::table::AutoScan {w} {
    if {![winfo exists $w]} return
    variable Priv
    set x $Priv(x)
    set y $Priv(y)
    if {$y >= [winfo height $w]} {
	$w yview scroll 1 units
    } elseif {$y < 0} {
	$w yview scroll -1 units
    } elseif {$x >= [winfo width $w]} {
	$w xview scroll 1 units
    } elseif {$x < 0} {
	$w xview scroll -1 units
    } else {
	return
    }
    ::tk::table::Motion $w [$w index @$x,$y]
    set Priv(afterId) [after 50 ::tk::table::AutoScan $w]
}

# ::tk::table::MoveCell --
#
# Moves the location cursor (active element) by the specified number
# of cells and changes the selection if we're in browse or extended
# selection mode.  If the new cell is "hidden", we skip to the next
# visible cell if possible, otherwise just abort.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::MoveCell {w x y} {
    if {[catch {$w index active row} r]} return
    set c [$w index active col]
    set cell [$w index [incr r $x],[incr c $y]]
    while {[string compare [set true [$w hidden $cell]] {}]} {
	# The cell is in some way hidden
	if {[string compare $true [$w index active]]} {
	    # The span cell wasn't the previous cell, so go to that
	    set cell $true
	    break
	}
	if {$x > 0} {incr r} elseif {$x < 0} {incr r -1}
	if {$y > 0} {incr c} elseif {$y < 0} {incr c -1}
	if {[string compare $cell [$w index $r,$c]]} {
	    set cell [$w index $r,$c]
	} else {
	    # We couldn't find a non-hidden cell, just don't move
	    return
	}
    }
    $w activate $cell
    $w see active
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set active
	}
	extended {
	    variable Priv
	    $w selection clear all
	    $w selection set active
	    $w selection anchor active
	    set Priv(tablePrev) [$w index active]
	}
    }
}

# ::tk::table::ExtendSelect --
#
# Does nothing unless we're in extended selection mode; in this
# case it moves the location cursor (active element) by the specified
# number of cells, and extends the selection to that point.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::ExtendSelect {w x y} {
    if {[string compare extended [$w cget -selectmode]] ||
	[catch {$w index active row} r]} return
    set c [$w index active col]
    $w activate [incr r $x],[incr c $y]
    $w see active
    ::tk::table::Motion $w [$w index active]
}

# ::tk::table::DataExtend
#
# This procedure is called for key-presses such as Shift-KEndData.
# If the selection mode isnt multiple or extend then it does nothing.
# Otherwise it moves the active element to el and, if we're in
# extended mode, extends the selection to that point.
#
# Arguments:
# w - The table widget.
# el - An integer cell number.

proc ::tk::table::DataExtend {w el} {
    set mode [$w cget -selectmode]
    if {[string match extended $mode]} {
	$w activate $el
	$w see $el
	if {[$w selection includes anchor]} {::tk::table::Motion $w $el}
    } elseif {[string match multiple $mode]} {
	$w activate $el
	$w see $el
    }
}

# ::tk::table::SelectAll
#
# This procedure is invoked to handle the "select all" operation.
# For single and browse mode, it just selects the active element.
# Otherwise it selects everything in the widget.
#
# Arguments:
# w - The table widget.

proc ::tk::table::SelectAll {w} {
    if {[regexp {^(single|browse)$} [$w cget -selectmode]]} {
	$w selection clear all
	catch {$w selection set active}
    } elseif {[$w cget -selecttitles]} {
	$w selection set [$w cget -roworigin],[$w cget -colorigin] end
    } else {
	$w selection set origin end
    }
}

# ::tk::table::ChangeWidth --
#
# Adjust the widget of the specified cell by $a.
#
# Arguments:
# w - The table widget.
# i - cell index
# a - amount to adjust by

proc ::tk::table::ChangeWidth {w i a} {
    set tmp [$w index $i col]
    if {[set width [$w width $tmp]] >= 0} {
	$w width $tmp [incr width $a]
    } else {
	$w width $tmp [incr width [expr {-$a}]]
    }
}

# tk_tableCopy --
#
# This procedure copies the selection from a table widget into the
# clipboard.
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCopy w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {clipboard append -displayof $w [::tk::table::GetSelection $w]}
    }
}

# tk_tableCut --
#
# This procedure copies the selection from a table widget into the
# clipboard, then deletes the selection (if it exists in the given
# widget).
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCut w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {
	    clipboard append -displayof $w [::tk::table::GetSelection $w]
	    $w cursel {}
	    $w selection clear all
	}
    }
}

# tk_tablePaste --
#
# This procedure pastes the contents of the clipboard to the specified
# cell (active by default) in a table widget.
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePaste {w {cell {}}} {
    if {[string compare {} $cell]} {
	if {[catch {::tk::table::GetSelection $w} data]} return
    } else {
	if {[catch {::tk::table::GetSelection $w CLIPBOARD} data]} {
	    return
	}
	set cell active
    }
    tk_tablePasteHandler $w [$w index $cell] $data
    if {[$w cget -state] == "normal"} {focus $w}
}

# tk_tablePasteHandler --
#
# This procedure handles how data is pasted into the table widget.
# This handles data in the default table selection form.
#
# NOTE: this allows pasting into all cells except title cells,
#       even those with -state disabled
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePasteHandler {w cell data} {
    #
    # Don't allow pasting into the title cells
    #
    if {[$w tag includes title $cell]} {
        return
    }

    set rows	[expr {[$w cget -rows]-[$w cget -roworigin]}]
    set cols	[expr {[$w cget -cols]-[$w cget -colorigin]}]
    set r	[$w index $cell row]
    set c	[$w index $cell col]
    set rsep	[$w cget -rowseparator]
    set csep	[$w cget -colseparator]
    ## Assume separate rows are split by row separator if specified
    ## If you were to want multi-character row separators, you would need:
    # regsub -all $rsep $data <newline> data
    # set data [join $data <newline>]
    if {[string compare {} $rsep]} { set data [split $data $rsep] }
    set row	$r
    foreach line $data {
	if {$row > $rows} break
	set col	$c
	## Assume separate cols are split by col separator if specified
	## Unless a -separator was specified
	if {[string compare {} $csep]} { set line [split $line $csep] }
	## If you were to want multi-character col separators, you would need:
	# regsub -all $csep $line <newline> line
	# set line [join $line <newline>]
	foreach item $line {
	    if {$col > $cols} break
	    $w set $row,$col $item
	    incr col
	}
	incr row
    }
}

# tk::table::Sort --
#
# This procedure handles how data is sorted in the table widget.
# This isn't currently used by tktable, but can be called by the user.
# It's behavior may change in the future.
#
# Arguments:
# w -		Name of a table widget.
# start -	start cell of rectangle to sort
# end -		end cell of rectangle to sort
# col -		column within rectangle to sort on
# args -	passed to lsort proc (ie: -integer -decreasing)

proc ::tk::table::Sort {w start end col args} {
    set start [$w index $start]
    set end   [$w index $end]
    scan $start %d,%d sr sc
    scan $end   %d,%d er ec
    if {($col < $sc) || ($col > $ec)} {
	return -code error "$col is not within sort range $sc to $ec"
    }
    set col [expr {$col - $sc}]

    set data {}
    for {set i $sr} {$i <= $er} {incr i} {
	lappend data [$w get $i,$sc $i,$ec]
    }

    set i $sr
    foreach row [eval [list lsort -index $col] $args [list $data]] {
	$w set row $i,$sc $row
	incr i
    }
}
Added Binaries/FreeBSD-7-x86/craplzma0.1/libcraplzma0.1.so.

cannot compute difference between binary files

Added Binaries/FreeBSD-7-x86/craplzma0.1/pkgIndex.tcl.










>
>
>
>
>
1
2
3
4
5
#
# Tcl package index file
#
package ifneeded miniarc::crap::lzma 0.1 \
    [list load [file join $dir libcraplzma0.1.so] craplzma]
Added Binaries/FreeBSD-7-x86/installkit.

cannot compute difference between binary files

Added Binaries/FreeBSD-7-x86/tkdnd1.0/License.txt.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
This software (tkdnd) is copyrighted by:
    George Petasis,
    Software and Knowledge Engineering Laboratory,
    Institute of Informatics and Telecommunications,
    National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and 
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

The following terms apply to all files associated
with the software unless explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
Added Binaries/FreeBSD-7-x86/tkdnd1.0/Readme.txt.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
                  
	    tkdnd: Tk Drag & Drop extension
		     (Version 1.0.0)

This directory holds a collection of files that add native drag & drop
capabilities to the tk toolkit. It is designed for tk versions >= 8.3.3,
but with simple modifications can be applied to any tk version greater than
8.1.

Remember that this software is in development. Please report any bugs or
feature requests directly to the author (petasis@iit.demokritos.gr) or by
posting on the comp.lang.tcl newsgroup. In the latter case, please use
"tkdnd" in the title of the posting.

This software (tkdnd) is copyrighted by:
    George Petasis, National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

and is under the same license that covers tcl. Free to use for anything :-)

For any questions and suggestions contact me at

  petasis@iit.demokritos.gr

or post a question at comp.lang.tcl (preferable)
Added Binaries/FreeBSD-7-x86/tkdnd1.0/libtkdnd1.0.so.

cannot compute difference between binary files

Added Binaries/FreeBSD-7-x86/tkdnd1.0/pkgIndex.tcl.
























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
namespace eval ::dnd {
    proc _load {dir} {
	set version 1.0
	load [file join $dir libtkdnd1.0.so] tkdnd
	source [file join $dir tkdnd.tcl]
	package provide tkdnd 1.0
	rename ::dnd::_load {}
    }
}

package ifneeded tkdnd 1.0 \
	[list ::dnd::_load $dir]
Added Binaries/FreeBSD-7-x86/tkdnd1.0/tkdnd.tcl.
















































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#
# tkdnd.tcl --
# 
#    This file implements some utility procedures that are used by the tkDND
#    package.
#
# This software is copyrighted by:
# George Petasis, National Centre for Scientific Research "Demokritos",
# Aghia Paraskevi, Athens, Greece.
# e-mail: petasis@iit.demokritos.gr
#
# The following terms apply to all files associated
# with the software unless explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
# and license this software and its documentation for any purpose, provided
# that existing copyright notices are retained in all copies and that this
# notice is included verbatim in any distributions. No written agreement,
# license, or royalty fee is required for any of the authorized uses.
# Modifications to this software may be copyrighted by their authors
# and need not follow the licensing terms described here, provided that
# the new terms are clearly indicated on the first page of each file where
# they apply.
# 
# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# 
# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
# MODIFICATIONS.
#

namespace eval ::dnd {
    variable AskSelectedAction
    
    # This procedure is used just to ensure that the object given as its
    # argument can be accessed as a binary object. Many thanks to Paul Duffin
    # for the idea :-)
    proc ConvertToBinary {object} {
	binary scan $object {}
	return $object
    }

    # This procedure handles the special case where we want items into a canvas
    # widget to be drop targets. It emulates this case as follows:
    #
    #  The tkDND extension is able to deliver events only to real windows
    #  (that means tk widgets). This procedure can be the binding script of all
    #  dnd events we are interested in being received by the canvas items.
    #  When this function is called, it tries to find the item that the mouse
    #  is over (if any). Then it examines its bindings, and if it finds the
    #  dnd related event that is processing it delivers this event to the
    #  particular item. Fianlly, it tries to emulate <DragEnter>/<DragLeave>
    #  on every canvas item...
    proc CanvasDeliverEvent {
	event actions action button source_codes curr_code data descriptions
	mods type source_types win X x Y y
    } {
	# This function will find the topmost item that the mouse is over, and
	# Deliver the event specified by the "event" arg to this item...
	global CanvasDeliverEventStatus
	switch $event {
	    <DragEnter>  -
	    <<DragEnter>> {set CanvasDeliverEventStatus(item) {}}
	    default {}
	}

	# Translate mouse coordinates to canvas coordinates...
	set cx [$win canvasx $x]
	set cy [$win canvasy $y]
	set cx_1 [expr {$cx+1}]
	set cy_1 [expr {$cy+1}]
	# Find all tags that are under the mouse...
	set tags [$win find overlapping $cx $cy $cx_1 $cy_1]
	# ... and select the topmost...
	set length [llength $tags]

	# If no tags under the mouse, return...
	if {!$length} {
	    #puts -->$CanvasDeliverEventStatus(item)
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (1) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    set CanvasDeliverEventStatus(item) {}
	    update
	    if {[string equal $event <<Drag>>]} {
		return -code break
	    }
	    return $action
	}
	if {$length == 1} {
	    set id $tags
	} else {
	    set id [$win find closest $cx $cy]
	}

	# Now in "id" we have the tag of the item below the mouse...
	# Has this item a binding?
	foreach tag [concat $id [$win gettags $id]] {
	    set binding [$win bind $tag $event]
	    if {[string length $binding]} {break}
	}
	
	# Is this tag the same as the last one? If is different, we
	# have to send a leave event to the previous item and an enter
	# event to this one...
	if {$CanvasDeliverEventStatus(item) != $id} {
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (2) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    # Send <<DndEnter>>...
	    set _id $id
	    set _binding {}
	    foreach _tag [concat $_id [$win gettags $_id]] {
		set _binding [$win bind $_tag <<DragEnter>>]
		if {[string length $_binding]} {break}
	    }
	    # puts "Sending <DragEnter> to $tag ($_binding)"
	    set script {}
	    foreach element $_binding {
		switch $element {
		    %% {lappend script %}       
		    %A {lappend script $action}
		    %a {lappend script $actions}
		    %b {lappend script $button}
		    %C {lappend script $source_codes}
		    %c {lappend script $curr_code}
		    %D {lappend script $data}
		    %d {lappend script $descriptions}
		    %m {lappend script $mods}
		    %T {lappend script $type}
		    %t {lappend script $source_types}
		    %W {lappend script $win}
		    %X {lappend script $X}
		    %x {lappend script $x}
		    %Y {lappend script $Y}
		    %y {lappend script $y}
		    %I {lappend script $_id}
		    default {lappend script $element}
		}
	    }
	    if {[llength $script]} {uplevel 1 $script}
	    set CanvasDeliverEventStatus(item) $id
	}

	set script {}
	foreach element $binding {
	    switch $element {
		%% {lappend script %}       
		%A {lappend script $action}
		%a {lappend script $actions}
		%b {lappend script $button}
		%C {lappend script $source_codes}
		%c {lappend script $curr_code}
		%D {lappend script $data}
		%d {lappend script $descriptions}
		%m {lappend script $mods}
		%T {lappend script $type}
		%t {lappend script $source_types}
		%W {lappend script $win}
		%X {lappend script $X}
		%x {lappend script $x}
		%Y {lappend script $Y}
		%y {lappend script $y}
		%I {lappend script $id}
		default {lappend script $element}
	    }
	}
	if {[llength $script]} {
	    return [uplevel 1 $script]
	}
	set CanvasDeliverEventStatus(item) {}
	update
	if {[string equal $event <<Drag>>]} {
	    return -code break
	}
	return $action
    }

    # ChooseAskAction --
    #   This procedure displays a dialog with the help of which the user can
    #   select one of the supported actions...
    proc ChooseAskAction {window x y actions descriptions args} {
	variable AskSelectedAction
	set title {Please Select Action:}
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} {
		set title $descr
		break
	    }
	}

	set menu $window.__tk_dnd[pwd]__action_ask__Drop_window_[pid]
	catch {destroy $menu}
	menu $menu -title $title -tearoff 0 -disabledforeground darkgreen
	$menu add command -font {helvetica 12 bold} \
		-label $title -command "destroy $menu" -state disabled
	$menu add separator

	set items 0
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} continue
	    $menu add command -label $descr -command \
		    "set ::dnd::AskSelectedAction $action; destroy $menu"
	    incr items
	}
	if {!$items} {
	    # The drag source accepts the ask action, but has no defined
	    # action list? Add copy action at least...
	    $menu add command -label Copy -command \
		    "set ::dnd::AskSelectedAction copy; destroy $menu"
	}
	
	$menu add separator
	$menu add command -label {Cancel Drop} -command \
		"set ::dnd::AskSelectedAction none; destroy $menu"

	set AskSelectedAction none
	tk_popup $menu $x $y
	update
	bind $menu <Unmap> {after idle {catch {destroy %W}}}
	tkwait window $menu
	
	return $AskSelectedAction
    }
};# namespace eval ::dnd

# EOF
Added Binaries/HPUX-hppa/installkit.

cannot compute difference between binary files

Added Binaries/Linux-x86/Tktable2.9/README.txt.






















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Conceptually based on Tk3 table widget by Roland King (rols@lehman.com)
 *
 * see ChangeLog file for details
 *
 * current maintainer: jeff at hobbs org
 *
 * Copyright 1997-2002, Jeffrey Hobbs (jeff@hobbs.org)
 */

		*************************************
		  The Tk Table Widget Version 2.0+
		*************************************

INTRODUCTION

TkTable is a table/matrix widget extension to tk/tcl.
The basic features of the widget are:

 * multi-line cells
 * support for embedded windows (one per cell)
 * row & column spanning
 * variable width columns / height rows (interactively resizable)
 * row and column titles
 * multiple data sources ((Tcl array || Tcl command) &| internal caching)
 * supports standard Tk reliefs, fonts, colors, etc.
 * x/y scrollbar support
 * 'tag' styles per row, column or cell to change visual appearance
 * in-cell editing - returns value back to data source
 * support for disabled (read-only) tables or cells (via tags)
 * multiple selection modes, with "active" cell
 * multiple drawing modes to get optimal performance for larger tables
 * optional 'flashes' when things update
 * cell validation support
 * Works everywhere Tk does (including Windows and Mac!)
 * Unicode support (Tk8.1+)

FINDING THE WIDGET

0. The newest version is most likely found at:
	http://tktable.sourceforge.net/
	http://www.purl.org/net/hobbs/tcl/capp/

BUILDING AND INSTALLING THE WIDGET

1. Uncompress and unpack the distribution

   ON UNIX:
	gzip -cd Tktable<version>.tar.gz | tar xf -

   ON WINDOWS:
	use something like WinZip to unpack the archive.

   ON MACINTOSH:
	use StuffIt Expander to unstuff the archive.
    
   This will create a subdirectory tkTable<version> with all the files in it.

2. Configure

   ON UNIX:
        cd Tktable<version>
	./configure

   tkTable uses information left in tkConfig.sh when you built tk.  This
   file will be found in $exec_prefix/lib/.  You might set the --prefix and
   --exec-prefix options of configure if you don't want the default
   (/usr/local).  If building on multiple unix platforms, the following is
   recommended to isolate build conflicts:
	mkdir <builddir>/<platform>
	cd !$
	/path/to/Tktable<version>/configure

   ON WINDOWS:

   Version 2.8 added support for building in the cygwin environment on
   Windows based on TEA (http://www.tcl.tk/doc/tea/).  You can retrieve
   cygwin from:
	http://sources.redhat.com/cygwin/

   Inside the cygwin environment, you build the same as on Unix.

   Otherwise, hack makefile.vc until it works and compile.  It has problems
   executing wish from a path with a space in it, but the DLL builds just
   fine.  A DLL should be available where you found this archive.

   ON MACINTOSH:
   
   Hack the CodeWarrior XML project mac_tkTable.mcp.xml until it works and
   compile.  The access path to the Tcl/Tk source tree will probably need
   adjusting.  A DLL should be available where you found this archive.

3. Make and Install

   ON UNIX or WINDOWS (with cygwin):
	make
	make test (OPTIONAL)
	make install

   ON WINDOWS (makefile.vc):
	nmake -f makefile.vc
	nmake -f makefile.vc test (OPTIONAL)
	nmake -f makefile.vc install

   ON MACINTOSH:
	Place Tktable.shlb in the Tool Command Language folder

   tkTable is built to comply to the latest tcl package conventions.
   There is also a specific "make static" for those who need it.

4. Use it

   Start a regular wish interpreter, 'load' the library, and use the table.
   Or use the "tablewish" interpreter that has the 'table' command built in.
   There are a few test scripts in the demos directory which you can source.

5. Read the documentation

   There is a Unix manpage and HTML translation provided in the doc/
   subdirectory.  These describe the table widget's features and commands
   in depth.  If something is confusing, just to try it out.


THINGS TO WATCH OUT FOR

Packing
  The table tries not to allocate huge chunks of screen real estate if
  you ask it for a lot of rows and columns.  You can always stretch out
  the frame or explicitly tell it how big it can be.  If you want to
  stretch the table, remember to pack it with fill both and expand on,
  or with grid, give it -sticky news and configure the grid row and column
  for some weighting.

Array   
  The array elements for the table are of the form array(2,3) etc.  Make
  sure there are no spaces around the ','.  Negative indices are allowed.

Editing
  If you can't edit, remember that the focus model in tk is explicit, so
  you need to click on the table or give it the focus command.  Just
  having a selected cell is not the same thing as being able to edit.
  You also need the editing cursor.  If you can't get the cursor, make
  sure that you actually have a variable assigned to the table, and that
  the "state" of the cell is not disabled.

COMMENTS, BUGS, etc.

* Please can you send comments and bug reports to the current maintainer
  and their best will be done to address them.  A mailing list for
  tktable discussion is tktable-users@lists.sourceforge.net.

* If you find a bug, a short piece of Tcl that exercises it would be very
  useful, or even better, compile with debugging and specify where it
  crashed in that short piece of Tcl.  Use the SourceForge site to check
  for known bugs or submit new ones.
Added Binaries/Linux-x86/Tktable2.9/libTktable2.9.so.

cannot compute difference between binary files

Added Binaries/Linux-x86/Tktable2.9/license.txt.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
		   * COPYRIGHT AND LICENSE TERMS *

(This file blatantly stolen from Tcl/Tk license and adapted - thus assume
it falls under similar license terms).

This software is copyrighted by Jeffrey Hobbs <jeff at hobbs org>.  The
following terms apply to all files associated with the software unless
explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute, and
license this software and its documentation for any purpose, provided that
existing copyright notices are retained in all copies and that this notice
is included verbatim in any distributions.  No written agreement, license,
or royalty fee is required for any of the authorized uses.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS
PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government
is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
of the Rights in Technical Data and Computer Software Clause as DFARS
252.227-7013 and FAR 52.227-19.

SPECIAL NOTES:

This software also falls under the bourbon_ware clause:

    Should you find this software useful in your daily work, you should
    feel obliged to take the author out for a drink if the opportunity
    presents itself.  The user may feel exempt from this clause if they
    are under 21 or think the author has already partaken of too many
    drinks.
Added Binaries/Linux-x86/Tktable2.9/pkgIndex.tcl.




>
>
1
2
if {[catch {package require Tcl 8.2}]} return
package ifneeded Tktable 2.9  [list load [file join $dir libTktable2.9.so] Tktable]
Added Binaries/Linux-x86/Tktable2.9/tkTable.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
# table.tcl --
#
# Version align with tkTable 2.7, jeff at hobbs org
# This file defines the default bindings for Tk table widgets
# and provides procedures that help in implementing those bindings.
#
# RCS: @(#) $Id: tkTable.tcl,v 1.14 2005/07/12 23:26:28 hobbs Exp $

#--------------------------------------------------------------------------
# ::tk::table::Priv elements used in this file:
#
# x && y -		Coords in widget
# afterId -		Token returned by "after" for autoscanning.
# tablePrev -		The last element to be selected or deselected
#			during a selection operation.
# mouseMoved -		Boolean to indicate whether mouse moved while
#			the button was pressed.
# borderInfo -		Boolean to know if the user clicked on a border
# borderB1 -		Boolean that set whether B1 can be used for the
#			interactiving resizing
#--------------------------------------------------------------------------

namespace eval ::tk::table {
    # Ensure that a namespace is created for us
    variable Priv
    array set Priv [list x 0 y 0 afterId {} mouseMoved 0 \
	    borderInfo {} borderB1 1]
}

# ::tk::table::ClipboardKeysyms --
# This procedure is invoked to identify the keys that correspond to
# the "copy", "cut", and "paste" functions for the clipboard.
#
# Arguments:
# copy -	Name of the key (keysym name plus modifiers, if any,
#		such as "Meta-y") used for the copy operation.
# cut -		Name of the key used for the cut operation.
# paste -	Name of the key used for the paste operation.

proc ::tk::table::ClipboardKeysyms {copy cut paste} {
    bind Table <$copy>	{tk_tableCopy %W}
    bind Table <$cut>	{tk_tableCut %W}
    bind Table <$paste>	{tk_tablePaste %W}
}
::tk::table::ClipboardKeysyms <Copy> <Cut> <Paste>

##
## Interactive cell resizing, affected by -resizeborders option
##
bind Table <3>		{
    ## You might want to check for cell returned if you want to
    ## restrict the resizing of certain cells
    %W border mark %x %y
}
bind Table <B3-Motion>	{ %W border dragto %x %y }

## Button events

bind Table <1> { ::tk::table::Button1 %W %x %y }
bind Table <B1-Motion> { ::tk::table::B1Motion %W %x %y }

bind Table <ButtonRelease-1> {
    if {$::tk::table::Priv(borderInfo) == "" && [winfo exists %W]} {
	::tk::table::CancelRepeat
	%W activate @%x,%y
    }
}
bind Table <Double-1> {
    # empty
}

bind Table <Shift-1>	{::tk::table::BeginExtend %W [%W index @%x,%y]}
bind Table <Control-1>	{::tk::table::BeginToggle %W [%W index @%x,%y]}
bind Table <B1-Enter>	{::tk::table::CancelRepeat}
bind Table <B1-Leave>	{
    if {$::tk::table::Priv(borderInfo) == ""} {
	array set ::tk::table::Priv {x %x y %y}
	::tk::table::AutoScan %W
    }
}
bind Table <2> {
    %W scan mark %x %y
    array set ::tk::table::Priv {x %x y %y}
    set ::tk::table::Priv(mouseMoved) 0
}
bind Table <B2-Motion> {
    if {(%x != $::tk::table::Priv(x)) || (%y != $::tk::table::Priv(y))} {
	set ::tk::table::Priv(mouseMoved) 1
    }
    if {$::tk::table::Priv(mouseMoved)} { %W scan dragto %x %y }
}
bind Table <ButtonRelease-2> {
    if {!$::tk::table::Priv(mouseMoved)} { tk_tablePaste %W [%W index @%x,%y] }
}

## Key events

# This forces a cell commit if an active cell exists
bind Table <<Table_Commit>> {
    catch {%W activate active}
}
# Remove this if you don't want cell commit to occur on every Leave for
# the table (via mouse) or FocusOut (loss of focus by table).
event add <<Table_Commit>> <Leave> <FocusOut>

bind Table <Shift-Up>		{::tk::table::ExtendSelect %W -1  0}
bind Table <Shift-Down>		{::tk::table::ExtendSelect %W  1  0}
bind Table <Shift-Left>		{::tk::table::ExtendSelect %W  0 -1}
bind Table <Shift-Right>	{::tk::table::ExtendSelect %W  0  1}
bind Table <Prior>		{%W yview scroll -1 pages; %W activate topleft}
bind Table <Next>		{%W yview scroll  1 pages; %W activate topleft}
bind Table <Control-Prior>	{%W xview scroll -1 pages}
bind Table <Control-Next>	{%W xview scroll  1 pages}
bind Table <Home>		{%W see origin}
bind Table <End>		{%W see end}
bind Table <Control-Home> {
    %W selection clear all
    %W activate origin
    %W selection set active
    %W see active
}
bind Table <Control-End> {
    %W selection clear all
    %W activate end
    %W selection set active
    %W see active
}
bind Table <Shift-Control-Home>	{::tk::table::DataExtend %W origin}
bind Table <Shift-Control-End>	{::tk::table::DataExtend %W end}
bind Table <Select>		{::tk::table::BeginSelect %W [%W index active]}
bind Table <Shift-Select>	{::tk::table::BeginExtend %W [%W index active]}
bind Table <Control-slash>	{::tk::table::SelectAll %W}
bind Table <Control-backslash> {
    if {[string match browse [%W cget -selectmode]]} {%W selection clear all}
}
bind Table <Up>			{::tk::table::MoveCell %W -1  0}
bind Table <Down>		{::tk::table::MoveCell %W  1  0}
bind Table <Left>		{::tk::table::MoveCell %W  0 -1}
bind Table <Right>		{::tk::table::MoveCell %W  0  1}
bind Table <KeyPress>		{::tk::table::Insert %W %A}
bind Table <BackSpace>		{::tk::table::BackSpace %W}
bind Table <Delete>		{%W delete active insert}
bind Table <Escape>		{%W reread}

#bind Table <Return>		{::tk::table::MoveCell %W 1 0}
bind Table <Return>		{::tk::table::Insert %W "\n"}

bind Table <Control-Left>	{%W icursor [expr {[%W icursor]-1}]}
bind Table <Control-Right>	{%W icursor [expr {[%W icursor]+1}]}
bind Table <Control-e>		{%W icursor end}
bind Table <Control-a>		{%W icursor 0}
bind Table <Control-k>		{%W delete active insert end}
bind Table <Control-equal>	{::tk::table::ChangeWidth %W active  1}
bind Table <Control-minus>	{::tk::table::ChangeWidth %W active -1}

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# which is wrong.  Ditto for Tab.

bind Table <Alt-KeyPress>	{# nothing}
bind Table <Meta-KeyPress>	{# nothing}
bind Table <Control-KeyPress>	{# nothing}
bind Table <Any-Tab>		{# nothing}
if {[string match "macintosh" $::tcl_platform(platform)]} {
    bind Table <Command-KeyPress> {# nothing}
}

# ::tk::table::GetSelection --
#   This tries to obtain the default selection.  On Unix, we first try
#   and get a UTF8_STRING, a type supported by modern Unix apps for
#   passing Unicode data safely.  We fall back on the default STRING
#   type otherwise.  On Windows, only the STRING type is necessary.
# Arguments:
#   w	The widget for which the selection will be retrieved.
#	Important for the -displayof property.
#   sel	The source of the selection (PRIMARY or CLIPBOARD)
# Results:
#   Returns the selection, or an error if none could be found
#
if {[string compare $::tcl_platform(platform) "unix"]} {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
} else {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel \
		-type UTF8_STRING} txt] \
		&& [catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
}

# ::tk::table::CancelRepeat --
# A copy of tkCancelRepeat, just in case it's not available or changes.
# This procedure is invoked to cancel an auto-repeat action described
# by ::tk::table::Priv(afterId).  It's used by several widgets to auto-scroll
# the widget when the mouse is dragged out of the widget with a
# button pressed.
#
# Arguments:
# None.

proc ::tk::table::CancelRepeat {} {
    variable Priv
    after cancel $Priv(afterId)
    set Priv(afterId) {}
}

# ::tk::table::Insert --
#
#   Insert into the active cell
#
# Arguments:
#   w	- the table widget
#   s	- the string to insert
# Results:
#   Returns nothing
#
proc ::tk::table::Insert {w s} {
    if {[string compare $s {}]} {
	$w insert active insert $s
    }
}

# ::tk::table::BackSpace --
#
#   BackSpace in the current cell
#
# Arguments:
#   w	- the table widget
# Results:
#   Returns nothing
#
proc ::tk::table::BackSpace {w} {
    set cur [$w icursor]
    if {[string compare {} $cur] && $cur} {
	$w delete active [expr {$cur-1}]
    }
}

# ::tk::table::Button1 --
#
# This procedure is called to handle selecting with mouse button 1.
# It will distinguish whether to start selection or mark a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::Button1 {w x y} {
    variable Priv
    #
    # $Priv(borderInfo) is null if the user did not click on a border
    #
    if {$Priv(borderB1) == 1} {
	set Priv(borderInfo) [$w border mark $x $y]
	# account for what resizeborders are set [Bug 876320] (ferenc)
	set rbd [$w cget -resizeborders]
	if {$rbd == "none" || ![llength $Priv(borderInfo)]
	    || ($rbd == "col" && [lindex $Priv(borderInfo) 1] == "")
	    || ($rbd == "row" && [lindex $Priv(borderInfo) 0] == "")} {
	    set Priv(borderInfo) ""
	}
    } else {
	set Priv(borderInfo) ""
    }
    if {$Priv(borderInfo) == ""} {
	#
	# Only do this when a border wasn't selected
	#
	if {[winfo exists $w]} {
	    ::tk::table::BeginSelect $w [$w index @$x,$y]
	    focus $w
	}
	array set Priv [list x $x y $y]
	set Priv(mouseMoved) 0
    }
}

# ::tk::table::B1Motion --
#
# This procedure is called to start processing mouse motion events while
# button 1 moves while pressed.  It will distinguish whether to change
# the selection or move a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::B1Motion {w x y} {
    variable Priv

    # If we already had motion, or we moved more than 1 pixel,
    # then we start the Motion routine
    if {$Priv(borderInfo) != ""} {
	#
	# If the motion is on a border, drag it and skip the rest
	# of this binding.
	#
	$w border dragto $x $y
    } else {
	#
	# If we already had motion, or we moved more than 1 pixel,
	# then we start the Motion routine
	#
	if {
	    $::tk::table::Priv(mouseMoved)
	    || abs($x-$::tk::table::Priv(x)) > 1
	    || abs($y-$::tk::table::Priv(y)) > 1
	} {
	    set ::tk::table::Priv(mouseMoved) 1
	}
	if {$::tk::table::Priv(mouseMoved)} {
	    ::tk::table::Motion $w [$w index @$x,$y]
	}
    }
}

# ::tk::table::BeginSelect --
#
# This procedure is typically invoked on button-1 presses. It begins
# the process of making a selection in the table. Its exact behavior
# depends on the selection mode currently in effect for the table;
# see the Motif documentation for details.
#
# Arguments:
# w	- The table widget.
# el	- The element for the selection operation (typically the
#	one under the pointer).  Must be in row,col form.

proc ::tk::table::BeginSelect {w el} {
    variable Priv
    if {[scan $el %d,%d r c] != 2} return
    switch [$w cget -selectmode] {
	multiple {
	    if {[$w tag includes title $el]} {
		## in the title area
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			set inc topleft
			set el2 end
		    } else {
			set inc [$w index topleft row],$c
			set el2 [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    set inc $r,[$w index topleft col]
		    set el2 $r,[$w index end col]
		}
	    } else {
		set inc $el
		set el2 $el
	    }
	    if {[$w selection includes $inc]} {
		$w selection clear $el $el2
	    } else {
		$w selection set $el $el2
	    }
	}
	extended {
	    $w selection clear all
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection set $el end
		    } else {
			$w selection set $el [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    $w selection set $el $r,[$w index end col]
		}
	    } else {
		$w selection set $el
	    }
	    $w selection anchor $el
	    set Priv(tablePrev) $el
	}
	default {
	    if {![$w tag includes title $el]} {
		$w selection clear all
		$w selection set $el
		set Priv(tablePrev) $el
	    }
	    $w selection anchor $el
	}
    }
}

# ::tk::table::Motion --
#
# This procedure is called to process mouse motion events while
# button 1 is down. It may move or extend the selection, depending
# on the table's selection mode.
#
# Arguments:
# w	- The table widget.
# el	- The element under the pointer (must be in row,col form).

proc ::tk::table::Motion {w el} {
    variable Priv
    if {![info exists Priv(tablePrev)]} {
	set Priv(tablePrev) $el
	return
    }
    if {[string match $Priv(tablePrev) $el]} return
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set $el
	    set Priv(tablePrev) $el
	}
	extended {
	    # avoid tables that have no anchor index yet.
	    if {[catch {$w index anchor}]} { return }
	    scan $Priv(tablePrev) %d,%d r c
	    scan $el %d,%d elr elc
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection clear anchor end
		    } else {
			$w selection clear anchor [$w index end row],$c
		    }
		    $w selection set anchor [$w index end row],$elc
		} else {
		    ## We're in a row header
		    $w selection clear anchor $r,[$w index end col]
		    $w selection set anchor $elr,[$w index end col]
		}
	    } else {
		$w selection clear anchor $Priv(tablePrev)
		$w selection set anchor $el
	    }
	    set Priv(tablePrev) $el
	}
    }
}

# ::tk::table::BeginExtend --
#
# This procedure is typically invoked on shift-button-1 presses. It
# begins the process of extending a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginExtend {w el} {
    # avoid tables that have no anchor index yet.
    if {[catch {$w index anchor}]} { return }
    if {[string match extended [$w cget -selectmode]] &&
	[$w selection includes anchor]} {
	::tk::table::Motion $w $el
    }
}

# ::tk::table::BeginToggle --
#
# This procedure is typically invoked on control-button-1 presses. It
# begins the process of toggling a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginToggle {w el} {
    if {[string match extended [$w cget -selectmode]]} {
	variable Priv
	set Priv(tablePrev) $el
	$w selection anchor $el
	if {[$w tag includes title $el]} {
	    scan $el %d,%d r c
	    if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		## We're in a column header
		if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
		    ## We're in the topleft title area
		    set end end
		} else {
		    set end [$w index end row],$c
		}
	    } else {
		## We're in a row header
		set end $r,[$w index end col]
	    }
	} else {
	    ## We're in a non-title cell
	    set end $el
	}
	if {[$w selection includes  $end]} {
	    $w selection clear $el $end
	} else {
	    $w selection set   $el $end
        }
    }
}

# ::tk::table::AutoScan --
# This procedure is invoked when the mouse leaves an table window
# with button 1 down. It scrolls the window up, down, left, or
# right, depending on where the mouse left the window, and reschedules
# itself as an "after" command so that the window continues to scroll until
# the mouse moves back into the window or the mouse button is released.
#
# Arguments:
# w - The table window.

proc ::tk::table::AutoScan {w} {
    if {![winfo exists $w]} return
    variable Priv
    set x $Priv(x)
    set y $Priv(y)
    if {$y >= [winfo height $w]} {
	$w yview scroll 1 units
    } elseif {$y < 0} {
	$w yview scroll -1 units
    } elseif {$x >= [winfo width $w]} {
	$w xview scroll 1 units
    } elseif {$x < 0} {
	$w xview scroll -1 units
    } else {
	return
    }
    ::tk::table::Motion $w [$w index @$x,$y]
    set Priv(afterId) [after 50 ::tk::table::AutoScan $w]
}

# ::tk::table::MoveCell --
#
# Moves the location cursor (active element) by the specified number
# of cells and changes the selection if we're in browse or extended
# selection mode.  If the new cell is "hidden", we skip to the next
# visible cell if possible, otherwise just abort.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::MoveCell {w x y} {
    if {[catch {$w index active row} r]} return
    set c [$w index active col]
    set cell [$w index [incr r $x],[incr c $y]]
    while {[string compare [set true [$w hidden $cell]] {}]} {
	# The cell is in some way hidden
	if {[string compare $true [$w index active]]} {
	    # The span cell wasn't the previous cell, so go to that
	    set cell $true
	    break
	}
	if {$x > 0} {incr r} elseif {$x < 0} {incr r -1}
	if {$y > 0} {incr c} elseif {$y < 0} {incr c -1}
	if {[string compare $cell [$w index $r,$c]]} {
	    set cell [$w index $r,$c]
	} else {
	    # We couldn't find a non-hidden cell, just don't move
	    return
	}
    }
    $w activate $cell
    $w see active
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set active
	}
	extended {
	    variable Priv
	    $w selection clear all
	    $w selection set active
	    $w selection anchor active
	    set Priv(tablePrev) [$w index active]
	}
    }
}

# ::tk::table::ExtendSelect --
#
# Does nothing unless we're in extended selection mode; in this
# case it moves the location cursor (active element) by the specified
# number of cells, and extends the selection to that point.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::ExtendSelect {w x y} {
    if {[string compare extended [$w cget -selectmode]] ||
	[catch {$w index active row} r]} return
    set c [$w index active col]
    $w activate [incr r $x],[incr c $y]
    $w see active
    ::tk::table::Motion $w [$w index active]
}

# ::tk::table::DataExtend
#
# This procedure is called for key-presses such as Shift-KEndData.
# If the selection mode isnt multiple or extend then it does nothing.
# Otherwise it moves the active element to el and, if we're in
# extended mode, extends the selection to that point.
#
# Arguments:
# w - The table widget.
# el - An integer cell number.

proc ::tk::table::DataExtend {w el} {
    set mode [$w cget -selectmode]
    if {[string match extended $mode]} {
	$w activate $el
	$w see $el
	if {[$w selection includes anchor]} {::tk::table::Motion $w $el}
    } elseif {[string match multiple $mode]} {
	$w activate $el
	$w see $el
    }
}

# ::tk::table::SelectAll
#
# This procedure is invoked to handle the "select all" operation.
# For single and browse mode, it just selects the active element.
# Otherwise it selects everything in the widget.
#
# Arguments:
# w - The table widget.

proc ::tk::table::SelectAll {w} {
    if {[regexp {^(single|browse)$} [$w cget -selectmode]]} {
	$w selection clear all
	catch {$w selection set active}
    } elseif {[$w cget -selecttitles]} {
	$w selection set [$w cget -roworigin],[$w cget -colorigin] end
    } else {
	$w selection set origin end
    }
}

# ::tk::table::ChangeWidth --
#
# Adjust the widget of the specified cell by $a.
#
# Arguments:
# w - The table widget.
# i - cell index
# a - amount to adjust by

proc ::tk::table::ChangeWidth {w i a} {
    set tmp [$w index $i col]
    if {[set width [$w width $tmp]] >= 0} {
	$w width $tmp [incr width $a]
    } else {
	$w width $tmp [incr width [expr {-$a}]]
    }
}

# tk_tableCopy --
#
# This procedure copies the selection from a table widget into the
# clipboard.
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCopy w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {clipboard append -displayof $w [::tk::table::GetSelection $w]}
    }
}

# tk_tableCut --
#
# This procedure copies the selection from a table widget into the
# clipboard, then deletes the selection (if it exists in the given
# widget).
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCut w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {
	    clipboard append -displayof $w [::tk::table::GetSelection $w]
	    $w cursel {}
	    $w selection clear all
	}
    }
}

# tk_tablePaste --
#
# This procedure pastes the contents of the clipboard to the specified
# cell (active by default) in a table widget.
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePaste {w {cell {}}} {
    if {[string compare {} $cell]} {
	if {[catch {::tk::table::GetSelection $w} data]} return
    } else {
	if {[catch {::tk::table::GetSelection $w CLIPBOARD} data]} {
	    return
	}
	set cell active
    }
    tk_tablePasteHandler $w [$w index $cell] $data
    if {[$w cget -state] == "normal"} {focus $w}
}

# tk_tablePasteHandler --
#
# This procedure handles how data is pasted into the table widget.
# This handles data in the default table selection form.
#
# NOTE: this allows pasting into all cells except title cells,
#       even those with -state disabled
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePasteHandler {w cell data} {
    #
    # Don't allow pasting into the title cells
    #
    if {[$w tag includes title $cell]} {
        return
    }

    set rows	[expr {[$w cget -rows]-[$w cget -roworigin]}]
    set cols	[expr {[$w cget -cols]-[$w cget -colorigin]}]
    set r	[$w index $cell row]
    set c	[$w index $cell col]
    set rsep	[$w cget -rowseparator]
    set csep	[$w cget -colseparator]
    ## Assume separate rows are split by row separator if specified
    ## If you were to want multi-character row separators, you would need:
    # regsub -all $rsep $data <newline> data
    # set data [join $data <newline>]
    if {[string compare {} $rsep]} { set data [split $data $rsep] }
    set row	$r
    foreach line $data {
	if {$row > $rows} break
	set col	$c
	## Assume separate cols are split by col separator if specified
	## Unless a -separator was specified
	if {[string compare {} $csep]} { set line [split $line $csep] }
	## If you were to want multi-character col separators, you would need:
	# regsub -all $csep $line <newline> line
	# set line [join $line <newline>]
	foreach item $line {
	    if {$col > $cols} break
	    $w set $row,$col $item
	    incr col
	}
	incr row
    }
}

# tk::table::Sort --
#
# This procedure handles how data is sorted in the table widget.
# This isn't currently used by tktable, but can be called by the user.
# It's behavior may change in the future.
#
# Arguments:
# w -		Name of a table widget.
# start -	start cell of rectangle to sort
# end -		end cell of rectangle to sort
# col -		column within rectangle to sort on
# args -	passed to lsort proc (ie: -integer -decreasing)

proc ::tk::table::Sort {w start end col args} {
    set start [$w index $start]
    set end   [$w index $end]
    scan $start %d,%d sr sc
    scan $end   %d,%d er ec
    if {($col < $sc) || ($col > $ec)} {
	return -code error "$col is not within sort range $sc to $ec"
    }
    set col [expr {$col - $sc}]

    set data {}
    for {set i $sr} {$i <= $er} {incr i} {
	lappend data [$w get $i,$sc $i,$ec]
    }

    set i $sr
    foreach row [eval [list lsort -index $col] $args [list $data]] {
	$w set row $i,$sc $row
	incr i
    }
}
Added Binaries/Linux-x86/craplzma0.1/libcraplzma0.1.so.

cannot compute difference between binary files

Added Binaries/Linux-x86/craplzma0.1/pkgIndex.tcl.










>
>
>
>
>
1
2
3
4
5
#
# Tcl package index file
#
package ifneeded miniarc::crap::lzma 0.1 \
    [list load [file join $dir libcraplzma0.1.so] craplzma]
Added Binaries/Linux-x86/installkit.

cannot compute difference between binary files

Added Binaries/Linux-x86/installkitU.

cannot compute difference between binary files

Added Binaries/Linux-x86/tkdnd1.0/License.txt.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
This software (tkdnd) is copyrighted by:
    George Petasis,
    Software and Knowledge Engineering Laboratory,
    Institute of Informatics and Telecommunications,
    National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and 
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

The following terms apply to all files associated
with the software unless explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
Added Binaries/Linux-x86/tkdnd1.0/Readme.txt.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
                  
	    tkdnd: Tk Drag & Drop extension
		     (Version 1.0.0)

This directory holds a collection of files that add native drag & drop
capabilities to the tk toolkit. It is designed for tk versions >= 8.3.3,
but with simple modifications can be applied to any tk version greater than
8.1.

Remember that this software is in development. Please report any bugs or
feature requests directly to the author (petasis@iit.demokritos.gr) or by
posting on the comp.lang.tcl newsgroup. In the latter case, please use
"tkdnd" in the title of the posting.

This software (tkdnd) is copyrighted by:
    George Petasis, National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

and is under the same license that covers tcl. Free to use for anything :-)

For any questions and suggestions contact me at

  petasis@iit.demokritos.gr

or post a question at comp.lang.tcl (preferable)
Added Binaries/Linux-x86/tkdnd1.0/libtkdnd1.0.so.

cannot compute difference between binary files

Added Binaries/Linux-x86/tkdnd1.0/pkgIndex.tcl.






















>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
namespace eval ::dnd {
    proc _load {dir} {
	set version 1.0
	load [file join $dir libtkdnd1.0.so] tkdnd
	source [file join $dir tkdnd.tcl]
	package provide tkdnd 1.0
	rename ::dnd::_load {}
    }
}

package ifneeded tkdnd 1.0  [list ::dnd::_load $dir]
Added Binaries/Linux-x86/tkdnd1.0/tkdnd.tcl.
















































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#
# tkdnd.tcl --
# 
#    This file implements some utility procedures that are used by the tkDND
#    package.
#
# This software is copyrighted by:
# George Petasis, National Centre for Scientific Research "Demokritos",
# Aghia Paraskevi, Athens, Greece.
# e-mail: petasis@iit.demokritos.gr
#
# The following terms apply to all files associated
# with the software unless explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
# and license this software and its documentation for any purpose, provided
# that existing copyright notices are retained in all copies and that this
# notice is included verbatim in any distributions. No written agreement,
# license, or royalty fee is required for any of the authorized uses.
# Modifications to this software may be copyrighted by their authors
# and need not follow the licensing terms described here, provided that
# the new terms are clearly indicated on the first page of each file where
# they apply.
# 
# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# 
# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
# MODIFICATIONS.
#

namespace eval ::dnd {
    variable AskSelectedAction
    
    # This procedure is used just to ensure that the object given as its
    # argument can be accessed as a binary object. Many thanks to Paul Duffin
    # for the idea :-)
    proc ConvertToBinary {object} {
	binary scan $object {}
	return $object
    }

    # This procedure handles the special case where we want items into a canvas
    # widget to be drop targets. It emulates this case as follows:
    #
    #  The tkDND extension is able to deliver events only to real windows
    #  (that means tk widgets). This procedure can be the binding script of all
    #  dnd events we are interested in being received by the canvas items.
    #  When this function is called, it tries to find the item that the mouse
    #  is over (if any). Then it examines its bindings, and if it finds the
    #  dnd related event that is processing it delivers this event to the
    #  particular item. Fianlly, it tries to emulate <DragEnter>/<DragLeave>
    #  on every canvas item...
    proc CanvasDeliverEvent {
	event actions action button source_codes curr_code data descriptions
	mods type source_types win X x Y y
    } {
	# This function will find the topmost item that the mouse is over, and
	# Deliver the event specified by the "event" arg to this item...
	global CanvasDeliverEventStatus
	switch $event {
	    <DragEnter>  -
	    <<DragEnter>> {set CanvasDeliverEventStatus(item) {}}
	    default {}
	}

	# Translate mouse coordinates to canvas coordinates...
	set cx [$win canvasx $x]
	set cy [$win canvasy $y]
	set cx_1 [expr {$cx+1}]
	set cy_1 [expr {$cy+1}]
	# Find all tags that are under the mouse...
	set tags [$win find overlapping $cx $cy $cx_1 $cy_1]
	# ... and select the topmost...
	set length [llength $tags]

	# If no tags under the mouse, return...
	if {!$length} {
	    #puts -->$CanvasDeliverEventStatus(item)
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (1) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    set CanvasDeliverEventStatus(item) {}
	    update
	    if {[string equal $event <<Drag>>]} {
		return -code break
	    }
	    return $action
	}
	if {$length == 1} {
	    set id $tags
	} else {
	    set id [$win find closest $cx $cy]
	}

	# Now in "id" we have the tag of the item below the mouse...
	# Has this item a binding?
	foreach tag [concat $id [$win gettags $id]] {
	    set binding [$win bind $tag $event]
	    if {[string length $binding]} {break}
	}
	
	# Is this tag the same as the last one? If is different, we
	# have to send a leave event to the previous item and an enter
	# event to this one...
	if {$CanvasDeliverEventStatus(item) != $id} {
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (2) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    # Send <<DndEnter>>...
	    set _id $id
	    set _binding {}
	    foreach _tag [concat $_id [$win gettags $_id]] {
		set _binding [$win bind $_tag <<DragEnter>>]
		if {[string length $_binding]} {break}
	    }
	    # puts "Sending <DragEnter> to $tag ($_binding)"
	    set script {}
	    foreach element $_binding {
		switch $element {
		    %% {lappend script %}       
		    %A {lappend script $action}
		    %a {lappend script $actions}
		    %b {lappend script $button}
		    %C {lappend script $source_codes}
		    %c {lappend script $curr_code}
		    %D {lappend script $data}
		    %d {lappend script $descriptions}
		    %m {lappend script $mods}
		    %T {lappend script $type}
		    %t {lappend script $source_types}
		    %W {lappend script $win}
		    %X {lappend script $X}
		    %x {lappend script $x}
		    %Y {lappend script $Y}
		    %y {lappend script $y}
		    %I {lappend script $_id}
		    default {lappend script $element}
		}
	    }
	    if {[llength $script]} {uplevel 1 $script}
	    set CanvasDeliverEventStatus(item) $id
	}

	set script {}
	foreach element $binding {
	    switch $element {
		%% {lappend script %}       
		%A {lappend script $action}
		%a {lappend script $actions}
		%b {lappend script $button}
		%C {lappend script $source_codes}
		%c {lappend script $curr_code}
		%D {lappend script $data}
		%d {lappend script $descriptions}
		%m {lappend script $mods}
		%T {lappend script $type}
		%t {lappend script $source_types}
		%W {lappend script $win}
		%X {lappend script $X}
		%x {lappend script $x}
		%Y {lappend script $Y}
		%y {lappend script $y}
		%I {lappend script $id}
		default {lappend script $element}
	    }
	}
	if {[llength $script]} {
	    return [uplevel 1 $script]
	}
	set CanvasDeliverEventStatus(item) {}
	update
	if {[string equal $event <<Drag>>]} {
	    return -code break
	}
	return $action
    }

    # ChooseAskAction --
    #   This procedure displays a dialog with the help of which the user can
    #   select one of the supported actions...
    proc ChooseAskAction {window x y actions descriptions args} {
	variable AskSelectedAction
	set title {Please Select Action:}
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} {
		set title $descr
		break
	    }
	}

	set menu $window.__tk_dnd[pwd]__action_ask__Drop_window_[pid]
	catch {destroy $menu}
	menu $menu -title $title -tearoff 0 -disabledforeground darkgreen
	$menu add command -font {helvetica 12 bold} \
		-label $title -command "destroy $menu" -state disabled
	$menu add separator

	set items 0
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} continue
	    $menu add command -label $descr -command \
		    "set ::dnd::AskSelectedAction $action; destroy $menu"
	    incr items
	}
	if {!$items} {
	    # The drag source accepts the ask action, but has no defined
	    # action list? Add copy action at least...
	    $menu add command -label Copy -command \
		    "set ::dnd::AskSelectedAction copy; destroy $menu"
	}
	
	$menu add separator
	$menu add command -label {Cancel Drop} -command \
		"set ::dnd::AskSelectedAction none; destroy $menu"

	set AskSelectedAction none
	tk_popup $menu $x $y
	update
	bind $menu <Unmap> {after idle {catch {destroy %W}}}
	tkwait window $menu
	
	return $AskSelectedAction
    }
};# namespace eval ::dnd

# EOF
Added Binaries/Linux-x86_64/Tktable2.9/README.txt.






















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Conceptually based on Tk3 table widget by Roland King (rols@lehman.com)
 *
 * see ChangeLog file for details
 *
 * current maintainer: jeff at hobbs org
 *
 * Copyright 1997-2002, Jeffrey Hobbs (jeff@hobbs.org)
 */

		*************************************
		  The Tk Table Widget Version 2.0+
		*************************************

INTRODUCTION

TkTable is a table/matrix widget extension to tk/tcl.
The basic features of the widget are:

 * multi-line cells
 * support for embedded windows (one per cell)
 * row & column spanning
 * variable width columns / height rows (interactively resizable)
 * row and column titles
 * multiple data sources ((Tcl array || Tcl command) &| internal caching)
 * supports standard Tk reliefs, fonts, colors, etc.
 * x/y scrollbar support
 * 'tag' styles per row, column or cell to change visual appearance
 * in-cell editing - returns value back to data source
 * support for disabled (read-only) tables or cells (via tags)
 * multiple selection modes, with "active" cell
 * multiple drawing modes to get optimal performance for larger tables
 * optional 'flashes' when things update
 * cell validation support
 * Works everywhere Tk does (including Windows and Mac!)
 * Unicode support (Tk8.1+)

FINDING THE WIDGET

0. The newest version is most likely found at:
	http://tktable.sourceforge.net/
	http://www.purl.org/net/hobbs/tcl/capp/

BUILDING AND INSTALLING THE WIDGET

1. Uncompress and unpack the distribution

   ON UNIX:
	gzip -cd Tktable<version>.tar.gz | tar xf -

   ON WINDOWS:
	use something like WinZip to unpack the archive.

   ON MACINTOSH:
	use StuffIt Expander to unstuff the archive.
    
   This will create a subdirectory tkTable<version> with all the files in it.

2. Configure

   ON UNIX:
        cd Tktable<version>
	./configure

   tkTable uses information left in tkConfig.sh when you built tk.  This
   file will be found in $exec_prefix/lib/.  You might set the --prefix and
   --exec-prefix options of configure if you don't want the default
   (/usr/local).  If building on multiple unix platforms, the following is
   recommended to isolate build conflicts:
	mkdir <builddir>/<platform>
	cd !$
	/path/to/Tktable<version>/configure

   ON WINDOWS:

   Version 2.8 added support for building in the cygwin environment on
   Windows based on TEA (http://www.tcl.tk/doc/tea/).  You can retrieve
   cygwin from:
	http://sources.redhat.com/cygwin/

   Inside the cygwin environment, you build the same as on Unix.

   Otherwise, hack makefile.vc until it works and compile.  It has problems
   executing wish from a path with a space in it, but the DLL builds just
   fine.  A DLL should be available where you found this archive.

   ON MACINTOSH:
   
   Hack the CodeWarrior XML project mac_tkTable.mcp.xml until it works and
   compile.  The access path to the Tcl/Tk source tree will probably need
   adjusting.  A DLL should be available where you found this archive.

3. Make and Install

   ON UNIX or WINDOWS (with cygwin):
	make
	make test (OPTIONAL)
	make install

   ON WINDOWS (makefile.vc):
	nmake -f makefile.vc
	nmake -f makefile.vc test (OPTIONAL)
	nmake -f makefile.vc install

   ON MACINTOSH:
	Place Tktable.shlb in the Tool Command Language folder

   tkTable is built to comply to the latest tcl package conventions.
   There is also a specific "make static" for those who need it.

4. Use it

   Start a regular wish interpreter, 'load' the library, and use the table.
   Or use the "tablewish" interpreter that has the 'table' command built in.
   There are a few test scripts in the demos directory which you can source.

5. Read the documentation

   There is a Unix manpage and HTML translation provided in the doc/
   subdirectory.  These describe the table widget's features and commands
   in depth.  If something is confusing, just to try it out.


THINGS TO WATCH OUT FOR

Packing
  The table tries not to allocate huge chunks of screen real estate if
  you ask it for a lot of rows and columns.  You can always stretch out
  the frame or explicitly tell it how big it can be.  If you want to
  stretch the table, remember to pack it with fill both and expand on,
  or with grid, give it -sticky news and configure the grid row and column
  for some weighting.

Array   
  The array elements for the table are of the form array(2,3) etc.  Make
  sure there are no spaces around the ','.  Negative indices are allowed.

Editing
  If you can't edit, remember that the focus model in tk is explicit, so
  you need to click on the table or give it the focus command.  Just
  having a selected cell is not the same thing as being able to edit.
  You also need the editing cursor.  If you can't get the cursor, make
  sure that you actually have a variable assigned to the table, and that
  the "state" of the cell is not disabled.

COMMENTS, BUGS, etc.

* Please can you send comments and bug reports to the current maintainer
  and their best will be done to address them.  A mailing list for
  tktable discussion is tktable-users@lists.sourceforge.net.

* If you find a bug, a short piece of Tcl that exercises it would be very
  useful, or even better, compile with debugging and specify where it
  crashed in that short piece of Tcl.  Use the SourceForge site to check
  for known bugs or submit new ones.
Added Binaries/Linux-x86_64/Tktable2.9/libTktable2.9.so.

cannot compute difference between binary files

Added Binaries/Linux-x86_64/Tktable2.9/license.txt.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
		   * COPYRIGHT AND LICENSE TERMS *

(This file blatantly stolen from Tcl/Tk license and adapted - thus assume
it falls under similar license terms).

This software is copyrighted by Jeffrey Hobbs <jeff at hobbs org>.  The
following terms apply to all files associated with the software unless
explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute, and
license this software and its documentation for any purpose, provided that
existing copyright notices are retained in all copies and that this notice
is included verbatim in any distributions.  No written agreement, license,
or royalty fee is required for any of the authorized uses.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS
PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government
is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
of the Rights in Technical Data and Computer Software Clause as DFARS
252.227-7013 and FAR 52.227-19.

SPECIAL NOTES:

This software also falls under the bourbon_ware clause:

    Should you find this software useful in your daily work, you should
    feel obliged to take the author out for a drink if the opportunity
    presents itself.  The user may feel exempt from this clause if they
    are under 21 or think the author has already partaken of too many
    drinks.
Added Binaries/Linux-x86_64/Tktable2.9/pkgIndex.tcl.




>
>
1
2
if {[catch {package require Tcl 8.2}]} return
package ifneeded Tktable 2.9  [list load [file join $dir libTktable2.9.so] Tktable]
Added Binaries/Linux-x86_64/Tktable2.9/tkTable.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
# table.tcl --
#
# Version align with tkTable 2.7, jeff at hobbs org
# This file defines the default bindings for Tk table widgets
# and provides procedures that help in implementing those bindings.
#
# RCS: @(#) $Id: tkTable.tcl,v 1.14 2005/07/12 23:26:28 hobbs Exp $

#--------------------------------------------------------------------------
# ::tk::table::Priv elements used in this file:
#
# x && y -		Coords in widget
# afterId -		Token returned by "after" for autoscanning.
# tablePrev -		The last element to be selected or deselected
#			during a selection operation.
# mouseMoved -		Boolean to indicate whether mouse moved while
#			the button was pressed.
# borderInfo -		Boolean to know if the user clicked on a border
# borderB1 -		Boolean that set whether B1 can be used for the
#			interactiving resizing
#--------------------------------------------------------------------------

namespace eval ::tk::table {
    # Ensure that a namespace is created for us
    variable Priv
    array set Priv [list x 0 y 0 afterId {} mouseMoved 0 \
	    borderInfo {} borderB1 1]
}

# ::tk::table::ClipboardKeysyms --
# This procedure is invoked to identify the keys that correspond to
# the "copy", "cut", and "paste" functions for the clipboard.
#
# Arguments:
# copy -	Name of the key (keysym name plus modifiers, if any,
#		such as "Meta-y") used for the copy operation.
# cut -		Name of the key used for the cut operation.
# paste -	Name of the key used for the paste operation.

proc ::tk::table::ClipboardKeysyms {copy cut paste} {
    bind Table <$copy>	{tk_tableCopy %W}
    bind Table <$cut>	{tk_tableCut %W}
    bind Table <$paste>	{tk_tablePaste %W}
}
::tk::table::ClipboardKeysyms <Copy> <Cut> <Paste>

##
## Interactive cell resizing, affected by -resizeborders option
##
bind Table <3>		{
    ## You might want to check for cell returned if you want to
    ## restrict the resizing of certain cells
    %W border mark %x %y
}
bind Table <B3-Motion>	{ %W border dragto %x %y }

## Button events

bind Table <1> { ::tk::table::Button1 %W %x %y }
bind Table <B1-Motion> { ::tk::table::B1Motion %W %x %y }

bind Table <ButtonRelease-1> {
    if {$::tk::table::Priv(borderInfo) == "" && [winfo exists %W]} {
	::tk::table::CancelRepeat
	%W activate @%x,%y
    }
}
bind Table <Double-1> {
    # empty
}

bind Table <Shift-1>	{::tk::table::BeginExtend %W [%W index @%x,%y]}
bind Table <Control-1>	{::tk::table::BeginToggle %W [%W index @%x,%y]}
bind Table <B1-Enter>	{::tk::table::CancelRepeat}
bind Table <B1-Leave>	{
    if {$::tk::table::Priv(borderInfo) == ""} {
	array set ::tk::table::Priv {x %x y %y}
	::tk::table::AutoScan %W
    }
}
bind Table <2> {
    %W scan mark %x %y
    array set ::tk::table::Priv {x %x y %y}
    set ::tk::table::Priv(mouseMoved) 0
}
bind Table <B2-Motion> {
    if {(%x != $::tk::table::Priv(x)) || (%y != $::tk::table::Priv(y))} {
	set ::tk::table::Priv(mouseMoved) 1
    }
    if {$::tk::table::Priv(mouseMoved)} { %W scan dragto %x %y }
}
bind Table <ButtonRelease-2> {
    if {!$::tk::table::Priv(mouseMoved)} { tk_tablePaste %W [%W index @%x,%y] }
}

## Key events

# This forces a cell commit if an active cell exists
bind Table <<Table_Commit>> {
    catch {%W activate active}
}
# Remove this if you don't want cell commit to occur on every Leave for
# the table (via mouse) or FocusOut (loss of focus by table).
event add <<Table_Commit>> <Leave> <FocusOut>

bind Table <Shift-Up>		{::tk::table::ExtendSelect %W -1  0}
bind Table <Shift-Down>		{::tk::table::ExtendSelect %W  1  0}
bind Table <Shift-Left>		{::tk::table::ExtendSelect %W  0 -1}
bind Table <Shift-Right>	{::tk::table::ExtendSelect %W  0  1}
bind Table <Prior>		{%W yview scroll -1 pages; %W activate topleft}
bind Table <Next>		{%W yview scroll  1 pages; %W activate topleft}
bind Table <Control-Prior>	{%W xview scroll -1 pages}
bind Table <Control-Next>	{%W xview scroll  1 pages}
bind Table <Home>		{%W see origin}
bind Table <End>		{%W see end}
bind Table <Control-Home> {
    %W selection clear all
    %W activate origin
    %W selection set active
    %W see active
}
bind Table <Control-End> {
    %W selection clear all
    %W activate end
    %W selection set active
    %W see active
}
bind Table <Shift-Control-Home>	{::tk::table::DataExtend %W origin}
bind Table <Shift-Control-End>	{::tk::table::DataExtend %W end}
bind Table <Select>		{::tk::table::BeginSelect %W [%W index active]}
bind Table <Shift-Select>	{::tk::table::BeginExtend %W [%W index active]}
bind Table <Control-slash>	{::tk::table::SelectAll %W}
bind Table <Control-backslash> {
    if {[string match browse [%W cget -selectmode]]} {%W selection clear all}
}
bind Table <Up>			{::tk::table::MoveCell %W -1  0}
bind Table <Down>		{::tk::table::MoveCell %W  1  0}
bind Table <Left>		{::tk::table::MoveCell %W  0 -1}
bind Table <Right>		{::tk::table::MoveCell %W  0  1}
bind Table <KeyPress>		{::tk::table::Insert %W %A}
bind Table <BackSpace>		{::tk::table::BackSpace %W}
bind Table <Delete>		{%W delete active insert}
bind Table <Escape>		{%W reread}

#bind Table <Return>		{::tk::table::MoveCell %W 1 0}
bind Table <Return>		{::tk::table::Insert %W "\n"}

bind Table <Control-Left>	{%W icursor [expr {[%W icursor]-1}]}
bind Table <Control-Right>	{%W icursor [expr {[%W icursor]+1}]}
bind Table <Control-e>		{%W icursor end}
bind Table <Control-a>		{%W icursor 0}
bind Table <Control-k>		{%W delete active insert end}
bind Table <Control-equal>	{::tk::table::ChangeWidth %W active  1}
bind Table <Control-minus>	{::tk::table::ChangeWidth %W active -1}

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# which is wrong.  Ditto for Tab.

bind Table <Alt-KeyPress>	{# nothing}
bind Table <Meta-KeyPress>	{# nothing}
bind Table <Control-KeyPress>	{# nothing}
bind Table <Any-Tab>		{# nothing}
if {[string match "macintosh" $::tcl_platform(platform)]} {
    bind Table <Command-KeyPress> {# nothing}
}

# ::tk::table::GetSelection --
#   This tries to obtain the default selection.  On Unix, we first try
#   and get a UTF8_STRING, a type supported by modern Unix apps for
#   passing Unicode data safely.  We fall back on the default STRING
#   type otherwise.  On Windows, only the STRING type is necessary.
# Arguments:
#   w	The widget for which the selection will be retrieved.
#	Important for the -displayof property.
#   sel	The source of the selection (PRIMARY or CLIPBOARD)
# Results:
#   Returns the selection, or an error if none could be found
#
if {[string compare $::tcl_platform(platform) "unix"]} {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
} else {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel \
		-type UTF8_STRING} txt] \
		&& [catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
}

# ::tk::table::CancelRepeat --
# A copy of tkCancelRepeat, just in case it's not available or changes.
# This procedure is invoked to cancel an auto-repeat action described
# by ::tk::table::Priv(afterId).  It's used by several widgets to auto-scroll
# the widget when the mouse is dragged out of the widget with a
# button pressed.
#
# Arguments:
# None.

proc ::tk::table::CancelRepeat {} {
    variable Priv
    after cancel $Priv(afterId)
    set Priv(afterId) {}
}

# ::tk::table::Insert --
#
#   Insert into the active cell
#
# Arguments:
#   w	- the table widget
#   s	- the string to insert
# Results:
#   Returns nothing
#
proc ::tk::table::Insert {w s} {
    if {[string compare $s {}]} {
	$w insert active insert $s
    }
}

# ::tk::table::BackSpace --
#
#   BackSpace in the current cell
#
# Arguments:
#   w	- the table widget
# Results:
#   Returns nothing
#
proc ::tk::table::BackSpace {w} {
    set cur [$w icursor]
    if {[string compare {} $cur] && $cur} {
	$w delete active [expr {$cur-1}]
    }
}

# ::tk::table::Button1 --
#
# This procedure is called to handle selecting with mouse button 1.
# It will distinguish whether to start selection or mark a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::Button1 {w x y} {
    variable Priv
    #
    # $Priv(borderInfo) is null if the user did not click on a border
    #
    if {$Priv(borderB1) == 1} {
	set Priv(borderInfo) [$w border mark $x $y]
	# account for what resizeborders are set [Bug 876320] (ferenc)
	set rbd [$w cget -resizeborders]
	if {$rbd == "none" || ![llength $Priv(borderInfo)]
	    || ($rbd == "col" && [lindex $Priv(borderInfo) 1] == "")
	    || ($rbd == "row" && [lindex $Priv(borderInfo) 0] == "")} {
	    set Priv(borderInfo) ""
	}
    } else {
	set Priv(borderInfo) ""
    }
    if {$Priv(borderInfo) == ""} {
	#
	# Only do this when a border wasn't selected
	#
	if {[winfo exists $w]} {
	    ::tk::table::BeginSelect $w [$w index @$x,$y]
	    focus $w
	}
	array set Priv [list x $x y $y]
	set Priv(mouseMoved) 0
    }
}

# ::tk::table::B1Motion --
#
# This procedure is called to start processing mouse motion events while
# button 1 moves while pressed.  It will distinguish whether to change
# the selection or move a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::B1Motion {w x y} {
    variable Priv

    # If we already had motion, or we moved more than 1 pixel,
    # then we start the Motion routine
    if {$Priv(borderInfo) != ""} {
	#
	# If the motion is on a border, drag it and skip the rest
	# of this binding.
	#
	$w border dragto $x $y
    } else {
	#
	# If we already had motion, or we moved more than 1 pixel,
	# then we start the Motion routine
	#
	if {
	    $::tk::table::Priv(mouseMoved)
	    || abs($x-$::tk::table::Priv(x)) > 1
	    || abs($y-$::tk::table::Priv(y)) > 1
	} {
	    set ::tk::table::Priv(mouseMoved) 1
	}
	if {$::tk::table::Priv(mouseMoved)} {
	    ::tk::table::Motion $w [$w index @$x,$y]
	}
    }
}

# ::tk::table::BeginSelect --
#
# This procedure is typically invoked on button-1 presses. It begins
# the process of making a selection in the table. Its exact behavior
# depends on the selection mode currently in effect for the table;
# see the Motif documentation for details.
#
# Arguments:
# w	- The table widget.
# el	- The element for the selection operation (typically the
#	one under the pointer).  Must be in row,col form.

proc ::tk::table::BeginSelect {w el} {
    variable Priv
    if {[scan $el %d,%d r c] != 2} return
    switch [$w cget -selectmode] {
	multiple {
	    if {[$w tag includes title $el]} {
		## in the title area
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			set inc topleft
			set el2 end
		    } else {
			set inc [$w index topleft row],$c
			set el2 [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    set inc $r,[$w index topleft col]
		    set el2 $r,[$w index end col]
		}
	    } else {
		set inc $el
		set el2 $el
	    }
	    if {[$w selection includes $inc]} {
		$w selection clear $el $el2
	    } else {
		$w selection set $el $el2
	    }
	}
	extended {
	    $w selection clear all
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection set $el end
		    } else {
			$w selection set $el [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    $w selection set $el $r,[$w index end col]
		}
	    } else {
		$w selection set $el
	    }
	    $w selection anchor $el
	    set Priv(tablePrev) $el
	}
	default {
	    if {![$w tag includes title $el]} {
		$w selection clear all
		$w selection set $el
		set Priv(tablePrev) $el
	    }
	    $w selection anchor $el
	}
    }
}

# ::tk::table::Motion --
#
# This procedure is called to process mouse motion events while
# button 1 is down. It may move or extend the selection, depending
# on the table's selection mode.
#
# Arguments:
# w	- The table widget.
# el	- The element under the pointer (must be in row,col form).

proc ::tk::table::Motion {w el} {
    variable Priv
    if {![info exists Priv(tablePrev)]} {
	set Priv(tablePrev) $el
	return
    }
    if {[string match $Priv(tablePrev) $el]} return
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set $el
	    set Priv(tablePrev) $el
	}
	extended {
	    # avoid tables that have no anchor index yet.
	    if {[catch {$w index anchor}]} { return }
	    scan $Priv(tablePrev) %d,%d r c
	    scan $el %d,%d elr elc
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection clear anchor end
		    } else {
			$w selection clear anchor [$w index end row],$c
		    }
		    $w selection set anchor [$w index end row],$elc
		} else {
		    ## We're in a row header
		    $w selection clear anchor $r,[$w index end col]
		    $w selection set anchor $elr,[$w index end col]
		}
	    } else {
		$w selection clear anchor $Priv(tablePrev)
		$w selection set anchor $el
	    }
	    set Priv(tablePrev) $el
	}
    }
}

# ::tk::table::BeginExtend --
#
# This procedure is typically invoked on shift-button-1 presses. It
# begins the process of extending a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginExtend {w el} {
    # avoid tables that have no anchor index yet.
    if {[catch {$w index anchor}]} { return }
    if {[string match extended [$w cget -selectmode]] &&
	[$w selection includes anchor]} {
	::tk::table::Motion $w $el
    }
}

# ::tk::table::BeginToggle --
#
# This procedure is typically invoked on control-button-1 presses. It
# begins the process of toggling a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginToggle {w el} {
    if {[string match extended [$w cget -selectmode]]} {
	variable Priv
	set Priv(tablePrev) $el
	$w selection anchor $el
	if {[$w tag includes title $el]} {
	    scan $el %d,%d r c
	    if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		## We're in a column header
		if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
		    ## We're in the topleft title area
		    set end end
		} else {
		    set end [$w index end row],$c
		}
	    } else {
		## We're in a row header
		set end $r,[$w index end col]
	    }
	} else {
	    ## We're in a non-title cell
	    set end $el
	}
	if {[$w selection includes  $end]} {
	    $w selection clear $el $end
	} else {
	    $w selection set   $el $end
        }
    }
}

# ::tk::table::AutoScan --
# This procedure is invoked when the mouse leaves an table window
# with button 1 down. It scrolls the window up, down, left, or
# right, depending on where the mouse left the window, and reschedules
# itself as an "after" command so that the window continues to scroll until
# the mouse moves back into the window or the mouse button is released.
#
# Arguments:
# w - The table window.

proc ::tk::table::AutoScan {w} {
    if {![winfo exists $w]} return
    variable Priv
    set x $Priv(x)
    set y $Priv(y)
    if {$y >= [winfo height $w]} {
	$w yview scroll 1 units
    } elseif {$y < 0} {
	$w yview scroll -1 units
    } elseif {$x >= [winfo width $w]} {
	$w xview scroll 1 units
    } elseif {$x < 0} {
	$w xview scroll -1 units
    } else {
	return
    }
    ::tk::table::Motion $w [$w index @$x,$y]
    set Priv(afterId) [after 50 ::tk::table::AutoScan $w]
}

# ::tk::table::MoveCell --
#
# Moves the location cursor (active element) by the specified number
# of cells and changes the selection if we're in browse or extended
# selection mode.  If the new cell is "hidden", we skip to the next
# visible cell if possible, otherwise just abort.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::MoveCell {w x y} {
    if {[catch {$w index active row} r]} return
    set c [$w index active col]
    set cell [$w index [incr r $x],[incr c $y]]
    while {[string compare [set true [$w hidden $cell]] {}]} {
	# The cell is in some way hidden
	if {[string compare $true [$w index active]]} {
	    # The span cell wasn't the previous cell, so go to that
	    set cell $true
	    break
	}
	if {$x > 0} {incr r} elseif {$x < 0} {incr r -1}
	if {$y > 0} {incr c} elseif {$y < 0} {incr c -1}
	if {[string compare $cell [$w index $r,$c]]} {
	    set cell [$w index $r,$c]
	} else {
	    # We couldn't find a non-hidden cell, just don't move
	    return
	}
    }
    $w activate $cell
    $w see active
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set active
	}
	extended {
	    variable Priv
	    $w selection clear all
	    $w selection set active
	    $w selection anchor active
	    set Priv(tablePrev) [$w index active]
	}
    }
}

# ::tk::table::ExtendSelect --
#
# Does nothing unless we're in extended selection mode; in this
# case it moves the location cursor (active element) by the specified
# number of cells, and extends the selection to that point.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::ExtendSelect {w x y} {
    if {[string compare extended [$w cget -selectmode]] ||
	[catch {$w index active row} r]} return
    set c [$w index active col]
    $w activate [incr r $x],[incr c $y]
    $w see active
    ::tk::table::Motion $w [$w index active]
}

# ::tk::table::DataExtend
#
# This procedure is called for key-presses such as Shift-KEndData.
# If the selection mode isnt multiple or extend then it does nothing.
# Otherwise it moves the active element to el and, if we're in
# extended mode, extends the selection to that point.
#
# Arguments:
# w - The table widget.
# el - An integer cell number.

proc ::tk::table::DataExtend {w el} {
    set mode [$w cget -selectmode]
    if {[string match extended $mode]} {
	$w activate $el
	$w see $el
	if {[$w selection includes anchor]} {::tk::table::Motion $w $el}
    } elseif {[string match multiple $mode]} {
	$w activate $el
	$w see $el
    }
}

# ::tk::table::SelectAll
#
# This procedure is invoked to handle the "select all" operation.
# For single and browse mode, it just selects the active element.
# Otherwise it selects everything in the widget.
#
# Arguments:
# w - The table widget.

proc ::tk::table::SelectAll {w} {
    if {[regexp {^(single|browse)$} [$w cget -selectmode]]} {
	$w selection clear all
	catch {$w selection set active}
    } elseif {[$w cget -selecttitles]} {
	$w selection set [$w cget -roworigin],[$w cget -colorigin] end
    } else {
	$w selection set origin end
    }
}

# ::tk::table::ChangeWidth --
#
# Adjust the widget of the specified cell by $a.
#
# Arguments:
# w - The table widget.
# i - cell index
# a - amount to adjust by

proc ::tk::table::ChangeWidth {w i a} {
    set tmp [$w index $i col]
    if {[set width [$w width $tmp]] >= 0} {
	$w width $tmp [incr width $a]
    } else {
	$w width $tmp [incr width [expr {-$a}]]
    }
}

# tk_tableCopy --
#
# This procedure copies the selection from a table widget into the
# clipboard.
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCopy w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {clipboard append -displayof $w [::tk::table::GetSelection $w]}
    }
}

# tk_tableCut --
#
# This procedure copies the selection from a table widget into the
# clipboard, then deletes the selection (if it exists in the given
# widget).
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCut w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {
	    clipboard append -displayof $w [::tk::table::GetSelection $w]
	    $w cursel {}
	    $w selection clear all
	}
    }
}

# tk_tablePaste --
#
# This procedure pastes the contents of the clipboard to the specified
# cell (active by default) in a table widget.
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePaste {w {cell {}}} {
    if {[string compare {} $cell]} {
	if {[catch {::tk::table::GetSelection $w} data]} return
    } else {
	if {[catch {::tk::table::GetSelection $w CLIPBOARD} data]} {
	    return
	}
	set cell active
    }
    tk_tablePasteHandler $w [$w index $cell] $data
    if {[$w cget -state] == "normal"} {focus $w}
}

# tk_tablePasteHandler --
#
# This procedure handles how data is pasted into the table widget.
# This handles data in the default table selection form.
#
# NOTE: this allows pasting into all cells except title cells,
#       even those with -state disabled
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePasteHandler {w cell data} {
    #
    # Don't allow pasting into the title cells
    #
    if {[$w tag includes title $cell]} {
        return
    }

    set rows	[expr {[$w cget -rows]-[$w cget -roworigin]}]
    set cols	[expr {[$w cget -cols]-[$w cget -colorigin]}]
    set r	[$w index $cell row]
    set c	[$w index $cell col]
    set rsep	[$w cget -rowseparator]
    set csep	[$w cget -colseparator]
    ## Assume separate rows are split by row separator if specified
    ## If you were to want multi-character row separators, you would need:
    # regsub -all $rsep $data <newline> data
    # set data [join $data <newline>]
    if {[string compare {} $rsep]} { set data [split $data $rsep] }
    set row	$r
    foreach line $data {
	if {$row > $rows} break
	set col	$c
	## Assume separate cols are split by col separator if specified
	## Unless a -separator was specified
	if {[string compare {} $csep]} { set line [split $line $csep] }
	## If you were to want multi-character col separators, you would need:
	# regsub -all $csep $line <newline> line
	# set line [join $line <newline>]
	foreach item $line {
	    if {$col > $cols} break
	    $w set $row,$col $item
	    incr col
	}
	incr row
    }
}

# tk::table::Sort --
#
# This procedure handles how data is sorted in the table widget.
# This isn't currently used by tktable, but can be called by the user.
# It's behavior may change in the future.
#
# Arguments:
# w -		Name of a table widget.
# start -	start cell of rectangle to sort
# end -		end cell of rectangle to sort
# col -		column within rectangle to sort on
# args -	passed to lsort proc (ie: -integer -decreasing)

proc ::tk::table::Sort {w start end col args} {
    set start [$w index $start]
    set end   [$w index $end]
    scan $start %d,%d sr sc
    scan $end   %d,%d er ec
    if {($col < $sc) || ($col > $ec)} {
	return -code error "$col is not within sort range $sc to $ec"
    }
    set col [expr {$col - $sc}]

    set data {}
    for {set i $sr} {$i <= $er} {incr i} {
	lappend data [$w get $i,$sc $i,$ec]
    }

    set i $sr
    foreach row [eval [list lsort -index $col] $args [list $data]] {
	$w set row $i,$sc $row
	incr i
    }
}
Added Binaries/Linux-x86_64/craplzma0.1/libcraplzma0.1.so.

cannot compute difference between binary files

Added Binaries/Linux-x86_64/craplzma0.1/pkgIndex.tcl.










>
>
>
>
>
1
2
3
4
5
#
# Tcl package index file
#
package ifneeded miniarc::crap::lzma 0.1 \
    [list load [file join $dir libcraplzma0.1.so] craplzma]
Added Binaries/Linux-x86_64/installkit.

cannot compute difference between binary files

Added Binaries/Linux-x86_64/installkitU.

cannot compute difference between binary files

Added Binaries/Linux-x86_64/tkdnd1.0/License.txt.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
This software (tkdnd) is copyrighted by:
    George Petasis,
    Software and Knowledge Engineering Laboratory,
    Institute of Informatics and Telecommunications,
    National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and 
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

The following terms apply to all files associated
with the software unless explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
Added Binaries/Linux-x86_64/tkdnd1.0/Readme.txt.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
                  
	    tkdnd: Tk Drag & Drop extension
		     (Version 1.0.0)

This directory holds a collection of files that add native drag & drop
capabilities to the tk toolkit. It is designed for tk versions >= 8.3.3,
but with simple modifications can be applied to any tk version greater than
8.1.

Remember that this software is in development. Please report any bugs or
feature requests directly to the author (petasis@iit.demokritos.gr) or by
posting on the comp.lang.tcl newsgroup. In the latter case, please use
"tkdnd" in the title of the posting.

This software (tkdnd) is copyrighted by:
    George Petasis, National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

and is under the same license that covers tcl. Free to use for anything :-)

For any questions and suggestions contact me at

  petasis@iit.demokritos.gr

or post a question at comp.lang.tcl (preferable)
Added Binaries/Linux-x86_64/tkdnd1.0/libtkdnd1.0.so.

cannot compute difference between binary files

Added Binaries/Linux-x86_64/tkdnd1.0/pkgIndex.tcl.






















>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
namespace eval ::dnd {
    proc _load {dir} {
	set version 1.0
	load [file join $dir libtkdnd1.0.so] tkdnd
	source [file join $dir tkdnd.tcl]
	package provide tkdnd 1.0
	rename ::dnd::_load {}
    }
}

package ifneeded tkdnd 1.0  [list ::dnd::_load $dir]
Added Binaries/Linux-x86_64/tkdnd1.0/tkdnd.tcl.
















































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#
# tkdnd.tcl --
# 
#    This file implements some utility procedures that are used by the tkDND
#    package.
#
# This software is copyrighted by:
# George Petasis, National Centre for Scientific Research "Demokritos",
# Aghia Paraskevi, Athens, Greece.
# e-mail: petasis@iit.demokritos.gr
#
# The following terms apply to all files associated
# with the software unless explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
# and license this software and its documentation for any purpose, provided
# that existing copyright notices are retained in all copies and that this
# notice is included verbatim in any distributions. No written agreement,
# license, or royalty fee is required for any of the authorized uses.
# Modifications to this software may be copyrighted by their authors
# and need not follow the licensing terms described here, provided that
# the new terms are clearly indicated on the first page of each file where
# they apply.
# 
# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# 
# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
# MODIFICATIONS.
#

namespace eval ::dnd {
    variable AskSelectedAction
    
    # This procedure is used just to ensure that the object given as its
    # argument can be accessed as a binary object. Many thanks to Paul Duffin
    # for the idea :-)
    proc ConvertToBinary {object} {
	binary scan $object {}
	return $object
    }

    # This procedure handles the special case where we want items into a canvas
    # widget to be drop targets. It emulates this case as follows:
    #
    #  The tkDND extension is able to deliver events only to real windows
    #  (that means tk widgets). This procedure can be the binding script of all
    #  dnd events we are interested in being received by the canvas items.
    #  When this function is called, it tries to find the item that the mouse
    #  is over (if any). Then it examines its bindings, and if it finds the
    #  dnd related event that is processing it delivers this event to the
    #  particular item. Fianlly, it tries to emulate <DragEnter>/<DragLeave>
    #  on every canvas item...
    proc CanvasDeliverEvent {
	event actions action button source_codes curr_code data descriptions
	mods type source_types win X x Y y
    } {
	# This function will find the topmost item that the mouse is over, and
	# Deliver the event specified by the "event" arg to this item...
	global CanvasDeliverEventStatus
	switch $event {
	    <DragEnter>  -
	    <<DragEnter>> {set CanvasDeliverEventStatus(item) {}}
	    default {}
	}

	# Translate mouse coordinates to canvas coordinates...
	set cx [$win canvasx $x]
	set cy [$win canvasy $y]
	set cx_1 [expr {$cx+1}]
	set cy_1 [expr {$cy+1}]
	# Find all tags that are under the mouse...
	set tags [$win find overlapping $cx $cy $cx_1 $cy_1]
	# ... and select the topmost...
	set length [llength $tags]

	# If no tags under the mouse, return...
	if {!$length} {
	    #puts -->$CanvasDeliverEventStatus(item)
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (1) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    set CanvasDeliverEventStatus(item) {}
	    update
	    if {[string equal $event <<Drag>>]} {
		return -code break
	    }
	    return $action
	}
	if {$length == 1} {
	    set id $tags
	} else {
	    set id [$win find closest $cx $cy]
	}

	# Now in "id" we have the tag of the item below the mouse...
	# Has this item a binding?
	foreach tag [concat $id [$win gettags $id]] {
	    set binding [$win bind $tag $event]
	    if {[string length $binding]} {break}
	}
	
	# Is this tag the same as the last one? If is different, we
	# have to send a leave event to the previous item and an enter
	# event to this one...
	if {$CanvasDeliverEventStatus(item) != $id} {
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (2) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    # Send <<DndEnter>>...
	    set _id $id
	    set _binding {}
	    foreach _tag [concat $_id [$win gettags $_id]] {
		set _binding [$win bind $_tag <<DragEnter>>]
		if {[string length $_binding]} {break}
	    }
	    # puts "Sending <DragEnter> to $tag ($_binding)"
	    set script {}
	    foreach element $_binding {
		switch $element {
		    %% {lappend script %}       
		    %A {lappend script $action}
		    %a {lappend script $actions}
		    %b {lappend script $button}
		    %C {lappend script $source_codes}
		    %c {lappend script $curr_code}
		    %D {lappend script $data}
		    %d {lappend script $descriptions}
		    %m {lappend script $mods}
		    %T {lappend script $type}
		    %t {lappend script $source_types}
		    %W {lappend script $win}
		    %X {lappend script $X}
		    %x {lappend script $x}
		    %Y {lappend script $Y}
		    %y {lappend script $y}
		    %I {lappend script $_id}
		    default {lappend script $element}
		}
	    }
	    if {[llength $script]} {uplevel 1 $script}
	    set CanvasDeliverEventStatus(item) $id
	}

	set script {}
	foreach element $binding {
	    switch $element {
		%% {lappend script %}       
		%A {lappend script $action}
		%a {lappend script $actions}
		%b {lappend script $button}
		%C {lappend script $source_codes}
		%c {lappend script $curr_code}
		%D {lappend script $data}
		%d {lappend script $descriptions}
		%m {lappend script $mods}
		%T {lappend script $type}
		%t {lappend script $source_types}
		%W {lappend script $win}
		%X {lappend script $X}
		%x {lappend script $x}
		%Y {lappend script $Y}
		%y {lappend script $y}
		%I {lappend script $id}
		default {lappend script $element}
	    }
	}
	if {[llength $script]} {
	    return [uplevel 1 $script]
	}
	set CanvasDeliverEventStatus(item) {}
	update
	if {[string equal $event <<Drag>>]} {
	    return -code break
	}
	return $action
    }

    # ChooseAskAction --
    #   This procedure displays a dialog with the help of which the user can
    #   select one of the supported actions...
    proc ChooseAskAction {window x y actions descriptions args} {
	variable AskSelectedAction
	set title {Please Select Action:}
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} {
		set title $descr
		break
	    }
	}

	set menu $window.__tk_dnd[pwd]__action_ask__Drop_window_[pid]
	catch {destroy $menu}
	menu $menu -title $title -tearoff 0 -disabledforeground darkgreen
	$menu add command -font {helvetica 12 bold} \
		-label $title -command "destroy $menu" -state disabled
	$menu add separator

	set items 0
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} continue
	    $menu add command -label $descr -command \
		    "set ::dnd::AskSelectedAction $action; destroy $menu"
	    incr items
	}
	if {!$items} {
	    # The drag source accepts the ask action, but has no defined
	    # action list? Add copy action at least...
	    $menu add command -label Copy -command \
		    "set ::dnd::AskSelectedAction copy; destroy $menu"
	}
	
	$menu add separator
	$menu add command -label {Cancel Drop} -command \
		"set ::dnd::AskSelectedAction none; destroy $menu"

	set AskSelectedAction none
	tk_popup $menu $x $y
	update
	bind $menu <Unmap> {after idle {catch {destroy %W}}}
	tkwait window $menu
	
	return $AskSelectedAction
    }
};# namespace eval ::dnd

# EOF
Added Binaries/Solaris-sparc/Tktable2.9/README.txt.






















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Conceptually based on Tk3 table widget by Roland King (rols@lehman.com)
 *
 * see ChangeLog file for details
 *
 * current maintainer: jeff at hobbs org
 *
 * Copyright 1997-2002, Jeffrey Hobbs (jeff@hobbs.org)
 */

		*************************************
		  The Tk Table Widget Version 2.0+
		*************************************

INTRODUCTION

TkTable is a table/matrix widget extension to tk/tcl.
The basic features of the widget are:

 * multi-line cells
 * support for embedded windows (one per cell)
 * row & column spanning
 * variable width columns / height rows (interactively resizable)
 * row and column titles
 * multiple data sources ((Tcl array || Tcl command) &| internal caching)
 * supports standard Tk reliefs, fonts, colors, etc.
 * x/y scrollbar support
 * 'tag' styles per row, column or cell to change visual appearance
 * in-cell editing - returns value back to data source
 * support for disabled (read-only) tables or cells (via tags)
 * multiple selection modes, with "active" cell
 * multiple drawing modes to get optimal performance for larger tables
 * optional 'flashes' when things update
 * cell validation support
 * Works everywhere Tk does (including Windows and Mac!)
 * Unicode support (Tk8.1+)

FINDING THE WIDGET

0. The newest version is most likely found at:
	http://tktable.sourceforge.net/
	http://www.purl.org/net/hobbs/tcl/capp/

BUILDING AND INSTALLING THE WIDGET

1. Uncompress and unpack the distribution

   ON UNIX:
	gzip -cd Tktable<version>.tar.gz | tar xf -

   ON WINDOWS:
	use something like WinZip to unpack the archive.

   ON MACINTOSH:
	use StuffIt Expander to unstuff the archive.
    
   This will create a subdirectory tkTable<version> with all the files in it.

2. Configure

   ON UNIX:
        cd Tktable<version>
	./configure

   tkTable uses information left in tkConfig.sh when you built tk.  This
   file will be found in $exec_prefix/lib/.  You might set the --prefix and
   --exec-prefix options of configure if you don't want the default
   (/usr/local).  If building on multiple unix platforms, the following is
   recommended to isolate build conflicts:
	mkdir <builddir>/<platform>
	cd !$
	/path/to/Tktable<version>/configure

   ON WINDOWS:

   Version 2.8 added support for building in the cygwin environment on
   Windows based on TEA (http://www.tcl.tk/doc/tea/).  You can retrieve
   cygwin from:
	http://sources.redhat.com/cygwin/

   Inside the cygwin environment, you build the same as on Unix.

   Otherwise, hack makefile.vc until it works and compile.  It has problems
   executing wish from a path with a space in it, but the DLL builds just
   fine.  A DLL should be available where you found this archive.

   ON MACINTOSH:
   
   Hack the CodeWarrior XML project mac_tkTable.mcp.xml until it works and
   compile.  The access path to the Tcl/Tk source tree will probably need
   adjusting.  A DLL should be available where you found this archive.

3. Make and Install

   ON UNIX or WINDOWS (with cygwin):
	make
	make test (OPTIONAL)
	make install

   ON WINDOWS (makefile.vc):
	nmake -f makefile.vc
	nmake -f makefile.vc test (OPTIONAL)
	nmake -f makefile.vc install

   ON MACINTOSH:
	Place Tktable.shlb in the Tool Command Language folder

   tkTable is built to comply to the latest tcl package conventions.
   There is also a specific "make static" for those who need it.

4. Use it

   Start a regular wish interpreter, 'load' the library, and use the table.
   Or use the "tablewish" interpreter that has the 'table' command built in.
   There are a few test scripts in the demos directory which you can source.

5. Read the documentation

   There is a Unix manpage and HTML translation provided in the doc/
   subdirectory.  These describe the table widget's features and commands
   in depth.  If something is confusing, just to try it out.


THINGS TO WATCH OUT FOR

Packing
  The table tries not to allocate huge chunks of screen real estate if
  you ask it for a lot of rows and columns.  You can always stretch out
  the frame or explicitly tell it how big it can be.  If you want to
  stretch the table, remember to pack it with fill both and expand on,
  or with grid, give it -sticky news and configure the grid row and column
  for some weighting.

Array   
  The array elements for the table are of the form array(2,3) etc.  Make
  sure there are no spaces around the ','.  Negative indices are allowed.

Editing
  If you can't edit, remember that the focus model in tk is explicit, so
  you need to click on the table or give it the focus command.  Just
  having a selected cell is not the same thing as being able to edit.
  You also need the editing cursor.  If you can't get the cursor, make
  sure that you actually have a variable assigned to the table, and that
  the "state" of the cell is not disabled.

COMMENTS, BUGS, etc.

* Please can you send comments and bug reports to the current maintainer
  and their best will be done to address them.  A mailing list for
  tktable discussion is tktable-users@lists.sourceforge.net.

* If you find a bug, a short piece of Tcl that exercises it would be very
  useful, or even better, compile with debugging and specify where it
  crashed in that short piece of Tcl.  Use the SourceForge site to check
  for known bugs or submit new ones.
Added Binaries/Solaris-sparc/Tktable2.9/libTktable2.9.so.

cannot compute difference between binary files

Added Binaries/Solaris-sparc/Tktable2.9/license.txt.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
		   * COPYRIGHT AND LICENSE TERMS *

(This file blatantly stolen from Tcl/Tk license and adapted - thus assume
it falls under similar license terms).

This software is copyrighted by Jeffrey Hobbs <jeff at hobbs org>.  The
following terms apply to all files associated with the software unless
explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute, and
license this software and its documentation for any purpose, provided that
existing copyright notices are retained in all copies and that this notice
is included verbatim in any distributions.  No written agreement, license,
or royalty fee is required for any of the authorized uses.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS
PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government
is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
of the Rights in Technical Data and Computer Software Clause as DFARS
252.227-7013 and FAR 52.227-19.

SPECIAL NOTES:

This software also falls under the bourbon_ware clause:

    Should you find this software useful in your daily work, you should
    feel obliged to take the author out for a drink if the opportunity
    presents itself.  The user may feel exempt from this clause if they
    are under 21 or think the author has already partaken of too many
    drinks.
Added Binaries/Solaris-sparc/Tktable2.9/pkgIndex.tcl.






>
>
>
1
2
3
if {[catch {package require Tcl 8.2}]} return
package ifneeded Tktable 2.9 \
    [list load [file join $dir libTktable2.9.so] Tktable]
Added Binaries/Solaris-sparc/Tktable2.9/tkTable.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
# table.tcl --
#
# Version align with tkTable 2.7, jeff at hobbs org
# This file defines the default bindings for Tk table widgets
# and provides procedures that help in implementing those bindings.
#
# RCS: @(#) $Id: tkTable.tcl,v 1.14 2005/07/12 23:26:28 hobbs Exp $

#--------------------------------------------------------------------------
# ::tk::table::Priv elements used in this file:
#
# x && y -		Coords in widget
# afterId -		Token returned by "after" for autoscanning.
# tablePrev -		The last element to be selected or deselected
#			during a selection operation.
# mouseMoved -		Boolean to indicate whether mouse moved while
#			the button was pressed.
# borderInfo -		Boolean to know if the user clicked on a border
# borderB1 -		Boolean that set whether B1 can be used for the
#			interactiving resizing
#--------------------------------------------------------------------------

namespace eval ::tk::table {
    # Ensure that a namespace is created for us
    variable Priv
    array set Priv [list x 0 y 0 afterId {} mouseMoved 0 \
	    borderInfo {} borderB1 1]
}

# ::tk::table::ClipboardKeysyms --
# This procedure is invoked to identify the keys that correspond to
# the "copy", "cut", and "paste" functions for the clipboard.
#
# Arguments:
# copy -	Name of the key (keysym name plus modifiers, if any,
#		such as "Meta-y") used for the copy operation.
# cut -		Name of the key used for the cut operation.
# paste -	Name of the key used for the paste operation.

proc ::tk::table::ClipboardKeysyms {copy cut paste} {
    bind Table <$copy>	{tk_tableCopy %W}
    bind Table <$cut>	{tk_tableCut %W}
    bind Table <$paste>	{tk_tablePaste %W}
}
::tk::table::ClipboardKeysyms <Copy> <Cut> <Paste>

##
## Interactive cell resizing, affected by -resizeborders option
##
bind Table <3>		{
    ## You might want to check for cell returned if you want to
    ## restrict the resizing of certain cells
    %W border mark %x %y
}
bind Table <B3-Motion>	{ %W border dragto %x %y }

## Button events

bind Table <1> { ::tk::table::Button1 %W %x %y }
bind Table <B1-Motion> { ::tk::table::B1Motion %W %x %y }

bind Table <ButtonRelease-1> {
    if {$::tk::table::Priv(borderInfo) == "" && [winfo exists %W]} {
	::tk::table::CancelRepeat
	%W activate @%x,%y
    }
}
bind Table <Double-1> {
    # empty
}

bind Table <Shift-1>	{::tk::table::BeginExtend %W [%W index @%x,%y]}
bind Table <Control-1>	{::tk::table::BeginToggle %W [%W index @%x,%y]}
bind Table <B1-Enter>	{::tk::table::CancelRepeat}
bind Table <B1-Leave>	{
    if {$::tk::table::Priv(borderInfo) == ""} {
	array set ::tk::table::Priv {x %x y %y}
	::tk::table::AutoScan %W
    }
}
bind Table <2> {
    %W scan mark %x %y
    array set ::tk::table::Priv {x %x y %y}
    set ::tk::table::Priv(mouseMoved) 0
}
bind Table <B2-Motion> {
    if {(%x != $::tk::table::Priv(x)) || (%y != $::tk::table::Priv(y))} {
	set ::tk::table::Priv(mouseMoved) 1
    }
    if {$::tk::table::Priv(mouseMoved)} { %W scan dragto %x %y }
}
bind Table <ButtonRelease-2> {
    if {!$::tk::table::Priv(mouseMoved)} { tk_tablePaste %W [%W index @%x,%y] }
}

## Key events

# This forces a cell commit if an active cell exists
bind Table <<Table_Commit>> {
    catch {%W activate active}
}
# Remove this if you don't want cell commit to occur on every Leave for
# the table (via mouse) or FocusOut (loss of focus by table).
event add <<Table_Commit>> <Leave> <FocusOut>

bind Table <Shift-Up>		{::tk::table::ExtendSelect %W -1  0}
bind Table <Shift-Down>		{::tk::table::ExtendSelect %W  1  0}
bind Table <Shift-Left>		{::tk::table::ExtendSelect %W  0 -1}
bind Table <Shift-Right>	{::tk::table::ExtendSelect %W  0  1}
bind Table <Prior>		{%W yview scroll -1 pages; %W activate topleft}
bind Table <Next>		{%W yview scroll  1 pages; %W activate topleft}
bind Table <Control-Prior>	{%W xview scroll -1 pages}
bind Table <Control-Next>	{%W xview scroll  1 pages}
bind Table <Home>		{%W see origin}
bind Table <End>		{%W see end}
bind Table <Control-Home> {
    %W selection clear all
    %W activate origin
    %W selection set active
    %W see active
}
bind Table <Control-End> {
    %W selection clear all
    %W activate end
    %W selection set active
    %W see active
}
bind Table <Shift-Control-Home>	{::tk::table::DataExtend %W origin}
bind Table <Shift-Control-End>	{::tk::table::DataExtend %W end}
bind Table <Select>		{::tk::table::BeginSelect %W [%W index active]}
bind Table <Shift-Select>	{::tk::table::BeginExtend %W [%W index active]}
bind Table <Control-slash>	{::tk::table::SelectAll %W}
bind Table <Control-backslash> {
    if {[string match browse [%W cget -selectmode]]} {%W selection clear all}
}
bind Table <Up>			{::tk::table::MoveCell %W -1  0}
bind Table <Down>		{::tk::table::MoveCell %W  1  0}
bind Table <Left>		{::tk::table::MoveCell %W  0 -1}
bind Table <Right>		{::tk::table::MoveCell %W  0  1}
bind Table <KeyPress>		{::tk::table::Insert %W %A}
bind Table <BackSpace>		{::tk::table::BackSpace %W}
bind Table <Delete>		{%W delete active insert}
bind Table <Escape>		{%W reread}

#bind Table <Return>		{::tk::table::MoveCell %W 1 0}
bind Table <Return>		{::tk::table::Insert %W "\n"}

bind Table <Control-Left>	{%W icursor [expr {[%W icursor]-1}]}
bind Table <Control-Right>	{%W icursor [expr {[%W icursor]+1}]}
bind Table <Control-e>		{%W icursor end}
bind Table <Control-a>		{%W icursor 0}
bind Table <Control-k>		{%W delete active insert end}
bind Table <Control-equal>	{::tk::table::ChangeWidth %W active  1}
bind Table <Control-minus>	{::tk::table::ChangeWidth %W active -1}

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# which is wrong.  Ditto for Tab.

bind Table <Alt-KeyPress>	{# nothing}
bind Table <Meta-KeyPress>	{# nothing}
bind Table <Control-KeyPress>	{# nothing}
bind Table <Any-Tab>		{# nothing}
if {[string match "macintosh" $::tcl_platform(platform)]} {
    bind Table <Command-KeyPress> {# nothing}
}

# ::tk::table::GetSelection --
#   This tries to obtain the default selection.  On Unix, we first try
#   and get a UTF8_STRING, a type supported by modern Unix apps for
#   passing Unicode data safely.  We fall back on the default STRING
#   type otherwise.  On Windows, only the STRING type is necessary.
# Arguments:
#   w	The widget for which the selection will be retrieved.
#	Important for the -displayof property.
#   sel	The source of the selection (PRIMARY or CLIPBOARD)
# Results:
#   Returns the selection, or an error if none could be found
#
if {[string compare $::tcl_platform(platform) "unix"]} {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
} else {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel \
		-type UTF8_STRING} txt] \
		&& [catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
}

# ::tk::table::CancelRepeat --
# A copy of tkCancelRepeat, just in case it's not available or changes.
# This procedure is invoked to cancel an auto-repeat action described
# by ::tk::table::Priv(afterId).  It's used by several widgets to auto-scroll
# the widget when the mouse is dragged out of the widget with a
# button pressed.
#
# Arguments:
# None.

proc ::tk::table::CancelRepeat {} {
    variable Priv
    after cancel $Priv(afterId)
    set Priv(afterId) {}
}

# ::tk::table::Insert --
#
#   Insert into the active cell
#
# Arguments:
#   w	- the table widget
#   s	- the string to insert
# Results:
#   Returns nothing
#
proc ::tk::table::Insert {w s} {
    if {[string compare $s {}]} {
	$w insert active insert $s
    }
}

# ::tk::table::BackSpace --
#
#   BackSpace in the current cell
#
# Arguments:
#   w	- the table widget
# Results:
#   Returns nothing
#
proc ::tk::table::BackSpace {w} {
    set cur [$w icursor]
    if {[string compare {} $cur] && $cur} {
	$w delete active [expr {$cur-1}]
    }
}

# ::tk::table::Button1 --
#
# This procedure is called to handle selecting with mouse button 1.
# It will distinguish whether to start selection or mark a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::Button1 {w x y} {
    variable Priv
    #
    # $Priv(borderInfo) is null if the user did not click on a border
    #
    if {$Priv(borderB1) == 1} {
	set Priv(borderInfo) [$w border mark $x $y]
	# account for what resizeborders are set [Bug 876320] (ferenc)
	set rbd [$w cget -resizeborders]
	if {$rbd == "none" || ![llength $Priv(borderInfo)]
	    || ($rbd == "col" && [lindex $Priv(borderInfo) 1] == "")
	    || ($rbd == "row" && [lindex $Priv(borderInfo) 0] == "")} {
	    set Priv(borderInfo) ""
	}
    } else {
	set Priv(borderInfo) ""
    }
    if {$Priv(borderInfo) == ""} {
	#
	# Only do this when a border wasn't selected
	#
	if {[winfo exists $w]} {
	    ::tk::table::BeginSelect $w [$w index @$x,$y]
	    focus $w
	}
	array set Priv [list x $x y $y]
	set Priv(mouseMoved) 0
    }
}

# ::tk::table::B1Motion --
#
# This procedure is called to start processing mouse motion events while
# button 1 moves while pressed.  It will distinguish whether to change
# the selection or move a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::B1Motion {w x y} {
    variable Priv

    # If we already had motion, or we moved more than 1 pixel,
    # then we start the Motion routine
    if {$Priv(borderInfo) != ""} {
	#
	# If the motion is on a border, drag it and skip the rest
	# of this binding.
	#
	$w border dragto $x $y
    } else {
	#
	# If we already had motion, or we moved more than 1 pixel,
	# then we start the Motion routine
	#
	if {
	    $::tk::table::Priv(mouseMoved)
	    || abs($x-$::tk::table::Priv(x)) > 1
	    || abs($y-$::tk::table::Priv(y)) > 1
	} {
	    set ::tk::table::Priv(mouseMoved) 1
	}
	if {$::tk::table::Priv(mouseMoved)} {
	    ::tk::table::Motion $w [$w index @$x,$y]
	}
    }
}

# ::tk::table::BeginSelect --
#
# This procedure is typically invoked on button-1 presses. It begins
# the process of making a selection in the table. Its exact behavior
# depends on the selection mode currently in effect for the table;
# see the Motif documentation for details.
#
# Arguments:
# w	- The table widget.
# el	- The element for the selection operation (typically the
#	one under the pointer).  Must be in row,col form.

proc ::tk::table::BeginSelect {w el} {
    variable Priv
    if {[scan $el %d,%d r c] != 2} return
    switch [$w cget -selectmode] {
	multiple {
	    if {[$w tag includes title $el]} {
		## in the title area
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			set inc topleft
			set el2 end
		    } else {
			set inc [$w index topleft row],$c
			set el2 [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    set inc $r,[$w index topleft col]
		    set el2 $r,[$w index end col]
		}
	    } else {
		set inc $el
		set el2 $el
	    }
	    if {[$w selection includes $inc]} {
		$w selection clear $el $el2
	    } else {
		$w selection set $el $el2
	    }
	}
	extended {
	    $w selection clear all
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection set $el end
		    } else {
			$w selection set $el [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    $w selection set $el $r,[$w index end col]
		}
	    } else {
		$w selection set $el
	    }
	    $w selection anchor $el
	    set Priv(tablePrev) $el
	}
	default {
	    if {![$w tag includes title $el]} {
		$w selection clear all
		$w selection set $el
		set Priv(tablePrev) $el
	    }
	    $w selection anchor $el
	}
    }
}

# ::tk::table::Motion --
#
# This procedure is called to process mouse motion events while
# button 1 is down. It may move or extend the selection, depending
# on the table's selection mode.
#
# Arguments:
# w	- The table widget.
# el	- The element under the pointer (must be in row,col form).

proc ::tk::table::Motion {w el} {
    variable Priv
    if {![info exists Priv(tablePrev)]} {
	set Priv(tablePrev) $el
	return
    }
    if {[string match $Priv(tablePrev) $el]} return
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set $el
	    set Priv(tablePrev) $el
	}
	extended {
	    # avoid tables that have no anchor index yet.
	    if {[catch {$w index anchor}]} { return }
	    scan $Priv(tablePrev) %d,%d r c
	    scan $el %d,%d elr elc
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection clear anchor end
		    } else {
			$w selection clear anchor [$w index end row],$c
		    }
		    $w selection set anchor [$w index end row],$elc
		} else {
		    ## We're in a row header
		    $w selection clear anchor $r,[$w index end col]
		    $w selection set anchor $elr,[$w index end col]
		}
	    } else {
		$w selection clear anchor $Priv(tablePrev)
		$w selection set anchor $el
	    }
	    set Priv(tablePrev) $el
	}
    }
}

# ::tk::table::BeginExtend --
#
# This procedure is typically invoked on shift-button-1 presses. It
# begins the process of extending a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginExtend {w el} {
    # avoid tables that have no anchor index yet.
    if {[catch {$w index anchor}]} { return }
    if {[string match extended [$w cget -selectmode]] &&
	[$w selection includes anchor]} {
	::tk::table::Motion $w $el
    }
}

# ::tk::table::BeginToggle --
#
# This procedure is typically invoked on control-button-1 presses. It
# begins the process of toggling a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginToggle {w el} {
    if {[string match extended [$w cget -selectmode]]} {
	variable Priv
	set Priv(tablePrev) $el
	$w selection anchor $el
	if {[$w tag includes title $el]} {
	    scan $el %d,%d r c
	    if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		## We're in a column header
		if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
		    ## We're in the topleft title area
		    set end end
		} else {
		    set end [$w index end row],$c
		}
	    } else {
		## We're in a row header
		set end $r,[$w index end col]
	    }
	} else {
	    ## We're in a non-title cell
	    set end $el
	}
	if {[$w selection includes  $end]} {
	    $w selection clear $el $end
	} else {
	    $w selection set   $el $end
        }
    }
}

# ::tk::table::AutoScan --
# This procedure is invoked when the mouse leaves an table window
# with button 1 down. It scrolls the window up, down, left, or
# right, depending on where the mouse left the window, and reschedules
# itself as an "after" command so that the window continues to scroll until
# the mouse moves back into the window or the mouse button is released.
#
# Arguments:
# w - The table window.

proc ::tk::table::AutoScan {w} {
    if {![winfo exists $w]} return
    variable Priv
    set x $Priv(x)
    set y $Priv(y)
    if {$y >= [winfo height $w]} {
	$w yview scroll 1 units
    } elseif {$y < 0} {
	$w yview scroll -1 units
    } elseif {$x >= [winfo width $w]} {
	$w xview scroll 1 units
    } elseif {$x < 0} {
	$w xview scroll -1 units
    } else {
	return
    }
    ::tk::table::Motion $w [$w index @$x,$y]
    set Priv(afterId) [after 50 ::tk::table::AutoScan $w]
}

# ::tk::table::MoveCell --
#
# Moves the location cursor (active element) by the specified number
# of cells and changes the selection if we're in browse or extended
# selection mode.  If the new cell is "hidden", we skip to the next
# visible cell if possible, otherwise just abort.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::MoveCell {w x y} {
    if {[catch {$w index active row} r]} return
    set c [$w index active col]
    set cell [$w index [incr r $x],[incr c $y]]
    while {[string compare [set true [$w hidden $cell]] {}]} {
	# The cell is in some way hidden
	if {[string compare $true [$w index active]]} {
	    # The span cell wasn't the previous cell, so go to that
	    set cell $true
	    break
	}
	if {$x > 0} {incr r} elseif {$x < 0} {incr r -1}
	if {$y > 0} {incr c} elseif {$y < 0} {incr c -1}
	if {[string compare $cell [$w index $r,$c]]} {
	    set cell [$w index $r,$c]
	} else {
	    # We couldn't find a non-hidden cell, just don't move
	    return
	}
    }
    $w activate $cell
    $w see active
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set active
	}
	extended {
	    variable Priv
	    $w selection clear all
	    $w selection set active
	    $w selection anchor active
	    set Priv(tablePrev) [$w index active]
	}
    }
}

# ::tk::table::ExtendSelect --
#
# Does nothing unless we're in extended selection mode; in this
# case it moves the location cursor (active element) by the specified
# number of cells, and extends the selection to that point.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::ExtendSelect {w x y} {
    if {[string compare extended [$w cget -selectmode]] ||
	[catch {$w index active row} r]} return
    set c [$w index active col]
    $w activate [incr r $x],[incr c $y]
    $w see active
    ::tk::table::Motion $w [$w index active]
}

# ::tk::table::DataExtend
#
# This procedure is called for key-presses such as Shift-KEndData.
# If the selection mode isnt multiple or extend then it does nothing.
# Otherwise it moves the active element to el and, if we're in
# extended mode, extends the selection to that point.
#
# Arguments:
# w - The table widget.
# el - An integer cell number.

proc ::tk::table::DataExtend {w el} {
    set mode [$w cget -selectmode]
    if {[string match extended $mode]} {
	$w activate $el
	$w see $el
	if {[$w selection includes anchor]} {::tk::table::Motion $w $el}
    } elseif {[string match multiple $mode]} {
	$w activate $el
	$w see $el
    }
}

# ::tk::table::SelectAll
#
# This procedure is invoked to handle the "select all" operation.
# For single and browse mode, it just selects the active element.
# Otherwise it selects everything in the widget.
#
# Arguments:
# w - The table widget.

proc ::tk::table::SelectAll {w} {
    if {[regexp {^(single|browse)$} [$w cget -selectmode]]} {
	$w selection clear all
	catch {$w selection set active}
    } elseif {[$w cget -selecttitles]} {
	$w selection set [$w cget -roworigin],[$w cget -colorigin] end
    } else {
	$w selection set origin end
    }
}

# ::tk::table::ChangeWidth --
#
# Adjust the widget of the specified cell by $a.
#
# Arguments:
# w - The table widget.
# i - cell index
# a - amount to adjust by

proc ::tk::table::ChangeWidth {w i a} {
    set tmp [$w index $i col]
    if {[set width [$w width $tmp]] >= 0} {
	$w width $tmp [incr width $a]
    } else {
	$w width $tmp [incr width [expr {-$a}]]
    }
}

# tk_tableCopy --
#
# This procedure copies the selection from a table widget into the
# clipboard.
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCopy w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {clipboard append -displayof $w [::tk::table::GetSelection $w]}
    }
}

# tk_tableCut --
#
# This procedure copies the selection from a table widget into the
# clipboard, then deletes the selection (if it exists in the given
# widget).
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCut w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {
	    clipboard append -displayof $w [::tk::table::GetSelection $w]
	    $w cursel {}
	    $w selection clear all
	}
    }
}

# tk_tablePaste --
#
# This procedure pastes the contents of the clipboard to the specified
# cell (active by default) in a table widget.
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePaste {w {cell {}}} {
    if {[string compare {} $cell]} {
	if {[catch {::tk::table::GetSelection $w} data]} return
    } else {
	if {[catch {::tk::table::GetSelection $w CLIPBOARD} data]} {
	    return
	}
	set cell active
    }
    tk_tablePasteHandler $w [$w index $cell] $data
    if {[$w cget -state] == "normal"} {focus $w}
}

# tk_tablePasteHandler --
#
# This procedure handles how data is pasted into the table widget.
# This handles data in the default table selection form.
#
# NOTE: this allows pasting into all cells except title cells,
#       even those with -state disabled
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePasteHandler {w cell data} {
    #
    # Don't allow pasting into the title cells
    #
    if {[$w tag includes title $cell]} {
        return
    }

    set rows	[expr {[$w cget -rows]-[$w cget -roworigin]}]
    set cols	[expr {[$w cget -cols]-[$w cget -colorigin]}]
    set r	[$w index $cell row]
    set c	[$w index $cell col]
    set rsep	[$w cget -rowseparator]
    set csep	[$w cget -colseparator]
    ## Assume separate rows are split by row separator if specified
    ## If you were to want multi-character row separators, you would need:
    # regsub -all $rsep $data <newline> data
    # set data [join $data <newline>]
    if {[string compare {} $rsep]} { set data [split $data $rsep] }
    set row	$r
    foreach line $data {
	if {$row > $rows} break
	set col	$c
	## Assume separate cols are split by col separator if specified
	## Unless a -separator was specified
	if {[string compare {} $csep]} { set line [split $line $csep] }
	## If you were to want multi-character col separators, you would need:
	# regsub -all $csep $line <newline> line
	# set line [join $line <newline>]
	foreach item $line {
	    if {$col > $cols} break
	    $w set $row,$col $item
	    incr col
	}
	incr row
    }
}

# tk::table::Sort --
#
# This procedure handles how data is sorted in the table widget.
# This isn't currently used by tktable, but can be called by the user.
# It's behavior may change in the future.
#
# Arguments:
# w -		Name of a table widget.
# start -	start cell of rectangle to sort
# end -		end cell of rectangle to sort
# col -		column within rectangle to sort on
# args -	passed to lsort proc (ie: -integer -decreasing)

proc ::tk::table::Sort {w start end col args} {
    set start [$w index $start]
    set end   [$w index $end]
    scan $start %d,%d sr sc
    scan $end   %d,%d er ec
    if {($col < $sc) || ($col > $ec)} {
	return -code error "$col is not within sort range $sc to $ec"
    }
    set col [expr {$col - $sc}]

    set data {}
    for {set i $sr} {$i <= $er} {incr i} {
	lappend data [$w get $i,$sc $i,$ec]
    }

    set i $sr
    foreach row [eval [list lsort -index $col] $args [list $data]] {
	$w set row $i,$sc $row
	incr i
    }
}
Added Binaries/Solaris-sparc/craplzma0.1/libcraplzma0.1.so.

cannot compute difference between binary files

Added Binaries/Solaris-sparc/craplzma0.1/pkgIndex.tcl.










>
>
>
>
>
1
2
3
4
5
#
# Tcl package index file
#
package ifneeded miniarc::crap::lzma 0.1 \
    [list load [file join $dir libcraplzma0.1.so] craplzma]
Added Binaries/Solaris-sparc/installkit.

cannot compute difference between binary files

Added Binaries/Solaris-sparc/tkdnd1.0/License.txt.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
This software (tkdnd) is copyrighted by:
    George Petasis,
    Software and Knowledge Engineering Laboratory,
    Institute of Informatics and Telecommunications,
    National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and 
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

The following terms apply to all files associated
with the software unless explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
Added Binaries/Solaris-sparc/tkdnd1.0/Readme.txt.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
                  
	    tkdnd: Tk Drag & Drop extension
		     (Version 1.0.0)

This directory holds a collection of files that add native drag & drop
capabilities to the tk toolkit. It is designed for tk versions >= 8.3.3,
but with simple modifications can be applied to any tk version greater than
8.1.

Remember that this software is in development. Please report any bugs or
feature requests directly to the author (petasis@iit.demokritos.gr) or by
posting on the comp.lang.tcl newsgroup. In the latter case, please use
"tkdnd" in the title of the posting.

This software (tkdnd) is copyrighted by:
    George Petasis, National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

and is under the same license that covers tcl. Free to use for anything :-)

For any questions and suggestions contact me at

  petasis@iit.demokritos.gr

or post a question at comp.lang.tcl (preferable)
Added Binaries/Solaris-sparc/tkdnd1.0/libtkdnd1.0.so.

cannot compute difference between binary files

Added Binaries/Solaris-sparc/tkdnd1.0/pkgIndex.tcl.
























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
namespace eval ::dnd {
    proc _load {dir} {
	set version 1.0
	load [file join $dir libtkdnd1.0.so] tkdnd
	source [file join $dir tkdnd.tcl]
	package provide tkdnd 1.0
	rename ::dnd::_load {}
    }
}

package ifneeded tkdnd 1.0 \
	[list ::dnd::_load $dir]
Added Binaries/Solaris-sparc/tkdnd1.0/tkdnd.tcl.
















































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#
# tkdnd.tcl --
# 
#    This file implements some utility procedures that are used by the tkDND
#    package.
#
# This software is copyrighted by:
# George Petasis, National Centre for Scientific Research "Demokritos",
# Aghia Paraskevi, Athens, Greece.
# e-mail: petasis@iit.demokritos.gr
#
# The following terms apply to all files associated
# with the software unless explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
# and license this software and its documentation for any purpose, provided
# that existing copyright notices are retained in all copies and that this
# notice is included verbatim in any distributions. No written agreement,
# license, or royalty fee is required for any of the authorized uses.
# Modifications to this software may be copyrighted by their authors
# and need not follow the licensing terms described here, provided that
# the new terms are clearly indicated on the first page of each file where
# they apply.
# 
# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# 
# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
# MODIFICATIONS.
#

namespace eval ::dnd {
    variable AskSelectedAction
    
    # This procedure is used just to ensure that the object given as its
    # argument can be accessed as a binary object. Many thanks to Paul Duffin
    # for the idea :-)
    proc ConvertToBinary {object} {
	binary scan $object {}
	return $object
    }

    # This procedure handles the special case where we want items into a canvas
    # widget to be drop targets. It emulates this case as follows:
    #
    #  The tkDND extension is able to deliver events only to real windows
    #  (that means tk widgets). This procedure can be the binding script of all
    #  dnd events we are interested in being received by the canvas items.
    #  When this function is called, it tries to find the item that the mouse
    #  is over (if any). Then it examines its bindings, and if it finds the
    #  dnd related event that is processing it delivers this event to the
    #  particular item. Fianlly, it tries to emulate <DragEnter>/<DragLeave>
    #  on every canvas item...
    proc CanvasDeliverEvent {
	event actions action button source_codes curr_code data descriptions
	mods type source_types win X x Y y
    } {
	# This function will find the topmost item that the mouse is over, and
	# Deliver the event specified by the "event" arg to this item...
	global CanvasDeliverEventStatus
	switch $event {
	    <DragEnter>  -
	    <<DragEnter>> {set CanvasDeliverEventStatus(item) {}}
	    default {}
	}

	# Translate mouse coordinates to canvas coordinates...
	set cx [$win canvasx $x]
	set cy [$win canvasy $y]
	set cx_1 [expr {$cx+1}]
	set cy_1 [expr {$cy+1}]
	# Find all tags that are under the mouse...
	set tags [$win find overlapping $cx $cy $cx_1 $cy_1]
	# ... and select the topmost...
	set length [llength $tags]

	# If no tags under the mouse, return...
	if {!$length} {
	    #puts -->$CanvasDeliverEventStatus(item)
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (1) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    set CanvasDeliverEventStatus(item) {}
	    update
	    if {[string equal $event <<Drag>>]} {
		return -code break
	    }
	    return $action
	}
	if {$length == 1} {
	    set id $tags
	} else {
	    set id [$win find closest $cx $cy]
	}

	# Now in "id" we have the tag of the item below the mouse...
	# Has this item a binding?
	foreach tag [concat $id [$win gettags $id]] {
	    set binding [$win bind $tag $event]
	    if {[string length $binding]} {break}
	}
	
	# Is this tag the same as the last one? If is different, we
	# have to send a leave event to the previous item and an enter
	# event to this one...
	if {$CanvasDeliverEventStatus(item) != $id} {
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (2) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    # Send <<DndEnter>>...
	    set _id $id
	    set _binding {}
	    foreach _tag [concat $_id [$win gettags $_id]] {
		set _binding [$win bind $_tag <<DragEnter>>]
		if {[string length $_binding]} {break}
	    }
	    # puts "Sending <DragEnter> to $tag ($_binding)"
	    set script {}
	    foreach element $_binding {
		switch $element {
		    %% {lappend script %}       
		    %A {lappend script $action}
		    %a {lappend script $actions}
		    %b {lappend script $button}
		    %C {lappend script $source_codes}
		    %c {lappend script $curr_code}
		    %D {lappend script $data}
		    %d {lappend script $descriptions}
		    %m {lappend script $mods}
		    %T {lappend script $type}
		    %t {lappend script $source_types}
		    %W {lappend script $win}
		    %X {lappend script $X}
		    %x {lappend script $x}
		    %Y {lappend script $Y}
		    %y {lappend script $y}
		    %I {lappend script $_id}
		    default {lappend script $element}
		}
	    }
	    if {[llength $script]} {uplevel 1 $script}
	    set CanvasDeliverEventStatus(item) $id
	}

	set script {}
	foreach element $binding {
	    switch $element {
		%% {lappend script %}       
		%A {lappend script $action}
		%a {lappend script $actions}
		%b {lappend script $button}
		%C {lappend script $source_codes}
		%c {lappend script $curr_code}
		%D {lappend script $data}
		%d {lappend script $descriptions}
		%m {lappend script $mods}
		%T {lappend script $type}
		%t {lappend script $source_types}
		%W {lappend script $win}
		%X {lappend script $X}
		%x {lappend script $x}
		%Y {lappend script $Y}
		%y {lappend script $y}
		%I {lappend script $id}
		default {lappend script $element}
	    }
	}
	if {[llength $script]} {
	    return [uplevel 1 $script]
	}
	set CanvasDeliverEventStatus(item) {}
	update
	if {[string equal $event <<Drag>>]} {
	    return -code break
	}
	return $action
    }

    # ChooseAskAction --
    #   This procedure displays a dialog with the help of which the user can
    #   select one of the supported actions...
    proc ChooseAskAction {window x y actions descriptions args} {
	variable AskSelectedAction
	set title {Please Select Action:}
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} {
		set title $descr
		break
	    }
	}

	set menu $window.__tk_dnd[pwd]__action_ask__Drop_window_[pid]
	catch {destroy $menu}
	menu $menu -title $title -tearoff 0 -disabledforeground darkgreen
	$menu add command -font {helvetica 12 bold} \
		-label $title -command "destroy $menu" -state disabled
	$menu add separator

	set items 0
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} continue
	    $menu add command -label $descr -command \
		    "set ::dnd::AskSelectedAction $action; destroy $menu"
	    incr items
	}
	if {!$items} {
	    # The drag source accepts the ask action, but has no defined
	    # action list? Add copy action at least...
	    $menu add command -label Copy -command \
		    "set ::dnd::AskSelectedAction copy; destroy $menu"
	}
	
	$menu add separator
	$menu add command -label {Cancel Drop} -command \
		"set ::dnd::AskSelectedAction none; destroy $menu"

	set AskSelectedAction none
	tk_popup $menu $x $y
	update
	bind $menu <Unmap> {after idle {catch {destroy %W}}}
	tkwait window $menu
	
	return $AskSelectedAction
    }
};# namespace eval ::dnd

# EOF
Added Binaries/Solaris-x86/Tktable2.9/README.txt.






















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Conceptually based on Tk3 table widget by Roland King (rols@lehman.com)
 *
 * see ChangeLog file for details
 *
 * current maintainer: jeff at hobbs org
 *
 * Copyright 1997-2002, Jeffrey Hobbs (jeff@hobbs.org)
 */

		*************************************
		  The Tk Table Widget Version 2.0+
		*************************************

INTRODUCTION

TkTable is a table/matrix widget extension to tk/tcl.
The basic features of the widget are:

 * multi-line cells
 * support for embedded windows (one per cell)
 * row & column spanning
 * variable width columns / height rows (interactively resizable)
 * row and column titles
 * multiple data sources ((Tcl array || Tcl command) &| internal caching)
 * supports standard Tk reliefs, fonts, colors, etc.
 * x/y scrollbar support
 * 'tag' styles per row, column or cell to change visual appearance
 * in-cell editing - returns value back to data source
 * support for disabled (read-only) tables or cells (via tags)
 * multiple selection modes, with "active" cell
 * multiple drawing modes to get optimal performance for larger tables
 * optional 'flashes' when things update
 * cell validation support
 * Works everywhere Tk does (including Windows and Mac!)
 * Unicode support (Tk8.1+)

FINDING THE WIDGET

0. The newest version is most likely found at:
	http://tktable.sourceforge.net/
	http://www.purl.org/net/hobbs/tcl/capp/

BUILDING AND INSTALLING THE WIDGET

1. Uncompress and unpack the distribution

   ON UNIX:
	gzip -cd Tktable<version>.tar.gz | tar xf -

   ON WINDOWS:
	use something like WinZip to unpack the archive.

   ON MACINTOSH:
	use StuffIt Expander to unstuff the archive.
    
   This will create a subdirectory tkTable<version> with all the files in it.

2. Configure

   ON UNIX:
        cd Tktable<version>
	./configure

   tkTable uses information left in tkConfig.sh when you built tk.  This
   file will be found in $exec_prefix/lib/.  You might set the --prefix and
   --exec-prefix options of configure if you don't want the default
   (/usr/local).  If building on multiple unix platforms, the following is
   recommended to isolate build conflicts:
	mkdir <builddir>/<platform>
	cd !$
	/path/to/Tktable<version>/configure

   ON WINDOWS:

   Version 2.8 added support for building in the cygwin environment on
   Windows based on TEA (http://www.tcl.tk/doc/tea/).  You can retrieve
   cygwin from:
	http://sources.redhat.com/cygwin/

   Inside the cygwin environment, you build the same as on Unix.

   Otherwise, hack makefile.vc until it works and compile.  It has problems
   executing wish from a path with a space in it, but the DLL builds just
   fine.  A DLL should be available where you found this archive.

   ON MACINTOSH:
   
   Hack the CodeWarrior XML project mac_tkTable.mcp.xml until it works and
   compile.  The access path to the Tcl/Tk source tree will probably need
   adjusting.  A DLL should be available where you found this archive.

3. Make and Install

   ON UNIX or WINDOWS (with cygwin):
	make
	make test (OPTIONAL)
	make install

   ON WINDOWS (makefile.vc):
	nmake -f makefile.vc
	nmake -f makefile.vc test (OPTIONAL)
	nmake -f makefile.vc install

   ON MACINTOSH:
	Place Tktable.shlb in the Tool Command Language folder

   tkTable is built to comply to the latest tcl package conventions.
   There is also a specific "make static" for those who need it.

4. Use it

   Start a regular wish interpreter, 'load' the library, and use the table.
   Or use the "tablewish" interpreter that has the 'table' command built in.
   There are a few test scripts in the demos directory which you can source.

5. Read the documentation

   There is a Unix manpage and HTML translation provided in the doc/
   subdirectory.  These describe the table widget's features and commands
   in depth.  If something is confusing, just to try it out.


THINGS TO WATCH OUT FOR

Packing
  The table tries not to allocate huge chunks of screen real estate if
  you ask it for a lot of rows and columns.  You can always stretch out
  the frame or explicitly tell it how big it can be.  If you want to
  stretch the table, remember to pack it with fill both and expand on,
  or with grid, give it -sticky news and configure the grid row and column
  for some weighting.

Array   
  The array elements for the table are of the form array(2,3) etc.  Make
  sure there are no spaces around the ','.  Negative indices are allowed.

Editing
  If you can't edit, remember that the focus model in tk is explicit, so
  you need to click on the table or give it the focus command.  Just
  having a selected cell is not the same thing as being able to edit.
  You also need the editing cursor.  If you can't get the cursor, make
  sure that you actually have a variable assigned to the table, and that
  the "state" of the cell is not disabled.

COMMENTS, BUGS, etc.

* Please can you send comments and bug reports to the current maintainer
  and their best will be done to address them.  A mailing list for
  tktable discussion is tktable-users@lists.sourceforge.net.

* If you find a bug, a short piece of Tcl that exercises it would be very
  useful, or even better, compile with debugging and specify where it
  crashed in that short piece of Tcl.  Use the SourceForge site to check
  for known bugs or submit new ones.
Added Binaries/Solaris-x86/Tktable2.9/libTktable2.9.so.

cannot compute difference between binary files

Added Binaries/Solaris-x86/Tktable2.9/license.txt.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
		   * COPYRIGHT AND LICENSE TERMS *

(This file blatantly stolen from Tcl/Tk license and adapted - thus assume
it falls under similar license terms).

This software is copyrighted by Jeffrey Hobbs <jeff at hobbs org>.  The
following terms apply to all files associated with the software unless
explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute, and
license this software and its documentation for any purpose, provided that
existing copyright notices are retained in all copies and that this notice
is included verbatim in any distributions.  No written agreement, license,
or royalty fee is required for any of the authorized uses.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS
PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government
is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
of the Rights in Technical Data and Computer Software Clause as DFARS
252.227-7013 and FAR 52.227-19.

SPECIAL NOTES:

This software also falls under the bourbon_ware clause:

    Should you find this software useful in your daily work, you should
    feel obliged to take the author out for a drink if the opportunity
    presents itself.  The user may feel exempt from this clause if they
    are under 21 or think the author has already partaken of too many
    drinks.
Added Binaries/Solaris-x86/Tktable2.9/pkgIndex.tcl.




>
>
1
2
if {[catch {package require Tcl 8.2}]} return
package ifneeded Tktable 2.9  [list load [file join $dir libTktable2.9.so] Tktable]
Added Binaries/Solaris-x86/Tktable2.9/tkTable.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
# table.tcl --
#
# Version align with tkTable 2.7, jeff at hobbs org
# This file defines the default bindings for Tk table widgets
# and provides procedures that help in implementing those bindings.
#
# RCS: @(#) $Id: tkTable.tcl,v 1.14 2005/07/12 23:26:28 hobbs Exp $

#--------------------------------------------------------------------------
# ::tk::table::Priv elements used in this file:
#
# x && y -		Coords in widget
# afterId -		Token returned by "after" for autoscanning.
# tablePrev -		The last element to be selected or deselected
#			during a selection operation.
# mouseMoved -		Boolean to indicate whether mouse moved while
#			the button was pressed.
# borderInfo -		Boolean to know if the user clicked on a border
# borderB1 -		Boolean that set whether B1 can be used for the
#			interactiving resizing
#--------------------------------------------------------------------------

namespace eval ::tk::table {
    # Ensure that a namespace is created for us
    variable Priv
    array set Priv [list x 0 y 0 afterId {} mouseMoved 0 \
	    borderInfo {} borderB1 1]
}

# ::tk::table::ClipboardKeysyms --
# This procedure is invoked to identify the keys that correspond to
# the "copy", "cut", and "paste" functions for the clipboard.
#
# Arguments:
# copy -	Name of the key (keysym name plus modifiers, if any,
#		such as "Meta-y") used for the copy operation.
# cut -		Name of the key used for the cut operation.
# paste -	Name of the key used for the paste operation.

proc ::tk::table::ClipboardKeysyms {copy cut paste} {
    bind Table <$copy>	{tk_tableCopy %W}
    bind Table <$cut>	{tk_tableCut %W}
    bind Table <$paste>	{tk_tablePaste %W}
}
::tk::table::ClipboardKeysyms <Copy> <Cut> <Paste>

##
## Interactive cell resizing, affected by -resizeborders option
##
bind Table <3>		{
    ## You might want to check for cell returned if you want to
    ## restrict the resizing of certain cells
    %W border mark %x %y
}
bind Table <B3-Motion>	{ %W border dragto %x %y }

## Button events

bind Table <1> { ::tk::table::Button1 %W %x %y }
bind Table <B1-Motion> { ::tk::table::B1Motion %W %x %y }

bind Table <ButtonRelease-1> {
    if {$::tk::table::Priv(borderInfo) == "" && [winfo exists %W]} {
	::tk::table::CancelRepeat
	%W activate @%x,%y
    }
}
bind Table <Double-1> {
    # empty
}

bind Table <Shift-1>	{::tk::table::BeginExtend %W [%W index @%x,%y]}
bind Table <Control-1>	{::tk::table::BeginToggle %W [%W index @%x,%y]}
bind Table <B1-Enter>	{::tk::table::CancelRepeat}
bind Table <B1-Leave>	{
    if {$::tk::table::Priv(borderInfo) == ""} {
	array set ::tk::table::Priv {x %x y %y}
	::tk::table::AutoScan %W
    }
}
bind Table <2> {
    %W scan mark %x %y
    array set ::tk::table::Priv {x %x y %y}
    set ::tk::table::Priv(mouseMoved) 0
}
bind Table <B2-Motion> {
    if {(%x != $::tk::table::Priv(x)) || (%y != $::tk::table::Priv(y))} {
	set ::tk::table::Priv(mouseMoved) 1
    }
    if {$::tk::table::Priv(mouseMoved)} { %W scan dragto %x %y }
}
bind Table <ButtonRelease-2> {
    if {!$::tk::table::Priv(mouseMoved)} { tk_tablePaste %W [%W index @%x,%y] }
}

## Key events

# This forces a cell commit if an active cell exists
bind Table <<Table_Commit>> {
    catch {%W activate active}
}
# Remove this if you don't want cell commit to occur on every Leave for
# the table (via mouse) or FocusOut (loss of focus by table).
event add <<Table_Commit>> <Leave> <FocusOut>

bind Table <Shift-Up>		{::tk::table::ExtendSelect %W -1  0}
bind Table <Shift-Down>		{::tk::table::ExtendSelect %W  1  0}
bind Table <Shift-Left>		{::tk::table::ExtendSelect %W  0 -1}
bind Table <Shift-Right>	{::tk::table::ExtendSelect %W  0  1}
bind Table <Prior>		{%W yview scroll -1 pages; %W activate topleft}
bind Table <Next>		{%W yview scroll  1 pages; %W activate topleft}
bind Table <Control-Prior>	{%W xview scroll -1 pages}
bind Table <Control-Next>	{%W xview scroll  1 pages}
bind Table <Home>		{%W see origin}
bind Table <End>		{%W see end}
bind Table <Control-Home> {
    %W selection clear all
    %W activate origin
    %W selection set active
    %W see active
}
bind Table <Control-End> {
    %W selection clear all
    %W activate end
    %W selection set active
    %W see active
}
bind Table <Shift-Control-Home>	{::tk::table::DataExtend %W origin}
bind Table <Shift-Control-End>	{::tk::table::DataExtend %W end}
bind Table <Select>		{::tk::table::BeginSelect %W [%W index active]}
bind Table <Shift-Select>	{::tk::table::BeginExtend %W [%W index active]}
bind Table <Control-slash>	{::tk::table::SelectAll %W}
bind Table <Control-backslash> {
    if {[string match browse [%W cget -selectmode]]} {%W selection clear all}
}
bind Table <Up>			{::tk::table::MoveCell %W -1  0}
bind Table <Down>		{::tk::table::MoveCell %W  1  0}
bind Table <Left>		{::tk::table::MoveCell %W  0 -1}
bind Table <Right>		{::tk::table::MoveCell %W  0  1}
bind Table <KeyPress>		{::tk::table::Insert %W %A}
bind Table <BackSpace>		{::tk::table::BackSpace %W}
bind Table <Delete>		{%W delete active insert}
bind Table <Escape>		{%W reread}

#bind Table <Return>		{::tk::table::MoveCell %W 1 0}
bind Table <Return>		{::tk::table::Insert %W "\n"}

bind Table <Control-Left>	{%W icursor [expr {[%W icursor]-1}]}
bind Table <Control-Right>	{%W icursor [expr {[%W icursor]+1}]}
bind Table <Control-e>		{%W icursor end}
bind Table <Control-a>		{%W icursor 0}
bind Table <Control-k>		{%W delete active insert end}
bind Table <Control-equal>	{::tk::table::ChangeWidth %W active  1}
bind Table <Control-minus>	{::tk::table::ChangeWidth %W active -1}

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# which is wrong.  Ditto for Tab.

bind Table <Alt-KeyPress>	{# nothing}
bind Table <Meta-KeyPress>	{# nothing}
bind Table <Control-KeyPress>	{# nothing}
bind Table <Any-Tab>		{# nothing}
if {[string match "macintosh" $::tcl_platform(platform)]} {
    bind Table <Command-KeyPress> {# nothing}
}

# ::tk::table::GetSelection --
#   This tries to obtain the default selection.  On Unix, we first try
#   and get a UTF8_STRING, a type supported by modern Unix apps for
#   passing Unicode data safely.  We fall back on the default STRING
#   type otherwise.  On Windows, only the STRING type is necessary.
# Arguments:
#   w	The widget for which the selection will be retrieved.
#	Important for the -displayof property.
#   sel	The source of the selection (PRIMARY or CLIPBOARD)
# Results:
#   Returns the selection, or an error if none could be found
#
if {[string compare $::tcl_platform(platform) "unix"]} {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
} else {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel \
		-type UTF8_STRING} txt] \
		&& [catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
}

# ::tk::table::CancelRepeat --
# A copy of tkCancelRepeat, just in case it's not available or changes.
# This procedure is invoked to cancel an auto-repeat action described
# by ::tk::table::Priv(afterId).  It's used by several widgets to auto-scroll
# the widget when the mouse is dragged out of the widget with a
# button pressed.
#
# Arguments:
# None.

proc ::tk::table::CancelRepeat {} {
    variable Priv
    after cancel $Priv(afterId)
    set Priv(afterId) {}
}

# ::tk::table::Insert --
#
#   Insert into the active cell
#
# Arguments:
#   w	- the table widget
#   s	- the string to insert
# Results:
#   Returns nothing
#
proc ::tk::table::Insert {w s} {
    if {[string compare $s {}]} {
	$w insert active insert $s
    }
}

# ::tk::table::BackSpace --
#
#   BackSpace in the current cell
#
# Arguments:
#   w	- the table widget
# Results:
#   Returns nothing
#
proc ::tk::table::BackSpace {w} {
    set cur [$w icursor]
    if {[string compare {} $cur] && $cur} {
	$w delete active [expr {$cur-1}]
    }
}

# ::tk::table::Button1 --
#
# This procedure is called to handle selecting with mouse button 1.
# It will distinguish whether to start selection or mark a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::Button1 {w x y} {
    variable Priv
    #
    # $Priv(borderInfo) is null if the user did not click on a border
    #
    if {$Priv(borderB1) == 1} {
	set Priv(borderInfo) [$w border mark $x $y]
	# account for what resizeborders are set [Bug 876320] (ferenc)
	set rbd [$w cget -resizeborders]
	if {$rbd == "none" || ![llength $Priv(borderInfo)]
	    || ($rbd == "col" && [lindex $Priv(borderInfo) 1] == "")
	    || ($rbd == "row" && [lindex $Priv(borderInfo) 0] == "")} {
	    set Priv(borderInfo) ""
	}
    } else {
	set Priv(borderInfo) ""
    }
    if {$Priv(borderInfo) == ""} {
	#
	# Only do this when a border wasn't selected
	#
	if {[winfo exists $w]} {
	    ::tk::table::BeginSelect $w [$w index @$x,$y]
	    focus $w
	}
	array set Priv [list x $x y $y]
	set Priv(mouseMoved) 0
    }
}

# ::tk::table::B1Motion --
#
# This procedure is called to start processing mouse motion events while
# button 1 moves while pressed.  It will distinguish whether to change
# the selection or move a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::B1Motion {w x y} {
    variable Priv

    # If we already had motion, or we moved more than 1 pixel,
    # then we start the Motion routine
    if {$Priv(borderInfo) != ""} {
	#
	# If the motion is on a border, drag it and skip the rest
	# of this binding.
	#
	$w border dragto $x $y
    } else {
	#
	# If we already had motion, or we moved more than 1 pixel,
	# then we start the Motion routine
	#
	if {
	    $::tk::table::Priv(mouseMoved)
	    || abs($x-$::tk::table::Priv(x)) > 1
	    || abs($y-$::tk::table::Priv(y)) > 1
	} {
	    set ::tk::table::Priv(mouseMoved) 1
	}
	if {$::tk::table::Priv(mouseMoved)} {
	    ::tk::table::Motion $w [$w index @$x,$y]
	}
    }
}

# ::tk::table::BeginSelect --
#
# This procedure is typically invoked on button-1 presses. It begins
# the process of making a selection in the table. Its exact behavior
# depends on the selection mode currently in effect for the table;
# see the Motif documentation for details.
#
# Arguments:
# w	- The table widget.
# el	- The element for the selection operation (typically the
#	one under the pointer).  Must be in row,col form.

proc ::tk::table::BeginSelect {w el} {
    variable Priv
    if {[scan $el %d,%d r c] != 2} return
    switch [$w cget -selectmode] {
	multiple {
	    if {[$w tag includes title $el]} {
		## in the title area
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			set inc topleft
			set el2 end
		    } else {
			set inc [$w index topleft row],$c
			set el2 [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    set inc $r,[$w index topleft col]
		    set el2 $r,[$w index end col]
		}
	    } else {
		set inc $el
		set el2 $el
	    }
	    if {[$w selection includes $inc]} {
		$w selection clear $el $el2
	    } else {
		$w selection set $el $el2
	    }
	}
	extended {
	    $w selection clear all
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection set $el end
		    } else {
			$w selection set $el [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    $w selection set $el $r,[$w index end col]
		}
	    } else {
		$w selection set $el
	    }
	    $w selection anchor $el
	    set Priv(tablePrev) $el
	}
	default {
	    if {![$w tag includes title $el]} {
		$w selection clear all
		$w selection set $el
		set Priv(tablePrev) $el
	    }
	    $w selection anchor $el
	}
    }
}

# ::tk::table::Motion --
#
# This procedure is called to process mouse motion events while
# button 1 is down. It may move or extend the selection, depending
# on the table's selection mode.
#
# Arguments:
# w	- The table widget.
# el	- The element under the pointer (must be in row,col form).

proc ::tk::table::Motion {w el} {
    variable Priv
    if {![info exists Priv(tablePrev)]} {
	set Priv(tablePrev) $el
	return
    }
    if {[string match $Priv(tablePrev) $el]} return
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set $el
	    set Priv(tablePrev) $el
	}
	extended {
	    # avoid tables that have no anchor index yet.
	    if {[catch {$w index anchor}]} { return }
	    scan $Priv(tablePrev) %d,%d r c
	    scan $el %d,%d elr elc
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection clear anchor end
		    } else {
			$w selection clear anchor [$w index end row],$c
		    }
		    $w selection set anchor [$w index end row],$elc
		} else {
		    ## We're in a row header
		    $w selection clear anchor $r,[$w index end col]
		    $w selection set anchor $elr,[$w index end col]
		}
	    } else {
		$w selection clear anchor $Priv(tablePrev)
		$w selection set anchor $el
	    }
	    set Priv(tablePrev) $el
	}
    }
}

# ::tk::table::BeginExtend --
#
# This procedure is typically invoked on shift-button-1 presses. It
# begins the process of extending a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginExtend {w el} {
    # avoid tables that have no anchor index yet.
    if {[catch {$w index anchor}]} { return }
    if {[string match extended [$w cget -selectmode]] &&
	[$w selection includes anchor]} {
	::tk::table::Motion $w $el
    }
}

# ::tk::table::BeginToggle --
#
# This procedure is typically invoked on control-button-1 presses. It
# begins the process of toggling a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginToggle {w el} {
    if {[string match extended [$w cget -selectmode]]} {
	variable Priv
	set Priv(tablePrev) $el
	$w selection anchor $el
	if {[$w tag includes title $el]} {
	    scan $el %d,%d r c
	    if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		## We're in a column header
		if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
		    ## We're in the topleft title area
		    set end end
		} else {
		    set end [$w index end row],$c
		}
	    } else {
		## We're in a row header
		set end $r,[$w index end col]
	    }
	} else {
	    ## We're in a non-title cell
	    set end $el
	}
	if {[$w selection includes  $end]} {
	    $w selection clear $el $end
	} else {
	    $w selection set   $el $end
        }
    }
}

# ::tk::table::AutoScan --
# This procedure is invoked when the mouse leaves an table window
# with button 1 down. It scrolls the window up, down, left, or
# right, depending on where the mouse left the window, and reschedules
# itself as an "after" command so that the window continues to scroll until
# the mouse moves back into the window or the mouse button is released.
#
# Arguments:
# w - The table window.

proc ::tk::table::AutoScan {w} {
    if {![winfo exists $w]} return
    variable Priv
    set x $Priv(x)
    set y $Priv(y)
    if {$y >= [winfo height $w]} {
	$w yview scroll 1 units
    } elseif {$y < 0} {
	$w yview scroll -1 units
    } elseif {$x >= [winfo width $w]} {
	$w xview scroll 1 units
    } elseif {$x < 0} {
	$w xview scroll -1 units
    } else {
	return
    }
    ::tk::table::Motion $w [$w index @$x,$y]
    set Priv(afterId) [after 50 ::tk::table::AutoScan $w]
}

# ::tk::table::MoveCell --
#
# Moves the location cursor (active element) by the specified number
# of cells and changes the selection if we're in browse or extended
# selection mode.  If the new cell is "hidden", we skip to the next
# visible cell if possible, otherwise just abort.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::MoveCell {w x y} {
    if {[catch {$w index active row} r]} return
    set c [$w index active col]
    set cell [$w index [incr r $x],[incr c $y]]
    while {[string compare [set true [$w hidden $cell]] {}]} {
	# The cell is in some way hidden
	if {[string compare $true [$w index active]]} {
	    # The span cell wasn't the previous cell, so go to that
	    set cell $true
	    break
	}
	if {$x > 0} {incr r} elseif {$x < 0} {incr r -1}
	if {$y > 0} {incr c} elseif {$y < 0} {incr c -1}
	if {[string compare $cell [$w index $r,$c]]} {
	    set cell [$w index $r,$c]
	} else {
	    # We couldn't find a non-hidden cell, just don't move
	    return
	}
    }
    $w activate $cell
    $w see active
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set active
	}
	extended {
	    variable Priv
	    $w selection clear all
	    $w selection set active
	    $w selection anchor active
	    set Priv(tablePrev) [$w index active]
	}
    }
}

# ::tk::table::ExtendSelect --
#
# Does nothing unless we're in extended selection mode; in this
# case it moves the location cursor (active element) by the specified
# number of cells, and extends the selection to that point.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::ExtendSelect {w x y} {
    if {[string compare extended [$w cget -selectmode]] ||
	[catch {$w index active row} r]} return
    set c [$w index active col]
    $w activate [incr r $x],[incr c $y]
    $w see active
    ::tk::table::Motion $w [$w index active]
}

# ::tk::table::DataExtend
#
# This procedure is called for key-presses such as Shift-KEndData.
# If the selection mode isnt multiple or extend then it does nothing.
# Otherwise it moves the active element to el and, if we're in
# extended mode, extends the selection to that point.
#
# Arguments:
# w - The table widget.
# el - An integer cell number.

proc ::tk::table::DataExtend {w el} {
    set mode [$w cget -selectmode]
    if {[string match extended $mode]} {
	$w activate $el
	$w see $el
	if {[$w selection includes anchor]} {::tk::table::Motion $w $el}
    } elseif {[string match multiple $mode]} {
	$w activate $el
	$w see $el
    }
}

# ::tk::table::SelectAll
#
# This procedure is invoked to handle the "select all" operation.
# For single and browse mode, it just selects the active element.
# Otherwise it selects everything in the widget.
#
# Arguments:
# w - The table widget.

proc ::tk::table::SelectAll {w} {
    if {[regexp {^(single|browse)$} [$w cget -selectmode]]} {
	$w selection clear all
	catch {$w selection set active}
    } elseif {[$w cget -selecttitles]} {
	$w selection set [$w cget -roworigin],[$w cget -colorigin] end
    } else {
	$w selection set origin end
    }
}

# ::tk::table::ChangeWidth --
#
# Adjust the widget of the specified cell by $a.
#
# Arguments:
# w - The table widget.
# i - cell index
# a - amount to adjust by

proc ::tk::table::ChangeWidth {w i a} {
    set tmp [$w index $i col]
    if {[set width [$w width $tmp]] >= 0} {
	$w width $tmp [incr width $a]
    } else {
	$w width $tmp [incr width [expr {-$a}]]
    }
}

# tk_tableCopy --
#
# This procedure copies the selection from a table widget into the
# clipboard.
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCopy w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {clipboard append -displayof $w [::tk::table::GetSelection $w]}
    }
}

# tk_tableCut --
#
# This procedure copies the selection from a table widget into the
# clipboard, then deletes the selection (if it exists in the given
# widget).
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCut w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {
	    clipboard append -displayof $w [::tk::table::GetSelection $w]
	    $w cursel {}
	    $w selection clear all
	}
    }
}

# tk_tablePaste --
#
# This procedure pastes the contents of the clipboard to the specified
# cell (active by default) in a table widget.
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePaste {w {cell {}}} {
    if {[string compare {} $cell]} {
	if {[catch {::tk::table::GetSelection $w} data]} return
    } else {
	if {[catch {::tk::table::GetSelection $w CLIPBOARD} data]} {
	    return
	}
	set cell active
    }
    tk_tablePasteHandler $w [$w index $cell] $data
    if {[$w cget -state] == "normal"} {focus $w}
}

# tk_tablePasteHandler --
#
# This procedure handles how data is pasted into the table widget.
# This handles data in the default table selection form.
#
# NOTE: this allows pasting into all cells except title cells,
#       even those with -state disabled
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePasteHandler {w cell data} {
    #
    # Don't allow pasting into the title cells
    #
    if {[$w tag includes title $cell]} {
        return
    }

    set rows	[expr {[$w cget -rows]-[$w cget -roworigin]}]
    set cols	[expr {[$w cget -cols]-[$w cget -colorigin]}]
    set r	[$w index $cell row]
    set c	[$w index $cell col]
    set rsep	[$w cget -rowseparator]
    set csep	[$w cget -colseparator]
    ## Assume separate rows are split by row separator if specified
    ## If you were to want multi-character row separators, you would need:
    # regsub -all $rsep $data <newline> data
    # set data [join $data <newline>]
    if {[string compare {} $rsep]} { set data [split $data $rsep] }
    set row	$r
    foreach line $data {
	if {$row > $rows} break
	set col	$c
	## Assume separate cols are split by col separator if specified
	## Unless a -separator was specified
	if {[string compare {} $csep]} { set line [split $line $csep] }
	## If you were to want multi-character col separators, you would need:
	# regsub -all $csep $line <newline> line
	# set line [join $line <newline>]
	foreach item $line {
	    if {$col > $cols} break
	    $w set $row,$col $item
	    incr col
	}
	incr row
    }
}

# tk::table::Sort --
#
# This procedure handles how data is sorted in the table widget.
# This isn't currently used by tktable, but can be called by the user.
# It's behavior may change in the future.
#
# Arguments:
# w -		Name of a table widget.
# start -	start cell of rectangle to sort
# end -		end cell of rectangle to sort
# col -		column within rectangle to sort on
# args -	passed to lsort proc (ie: -integer -decreasing)

proc ::tk::table::Sort {w start end col args} {
    set start [$w index $start]
    set end   [$w index $end]
    scan $start %d,%d sr sc
    scan $end   %d,%d er ec
    if {($col < $sc) || ($col > $ec)} {
	return -code error "$col is not within sort range $sc to $ec"
    }
    set col [expr {$col - $sc}]

    set data {}
    for {set i $sr} {$i <= $er} {incr i} {
	lappend data [$w get $i,$sc $i,$ec]
    }

    set i $sr
    foreach row [eval [list lsort -index $col] $args [list $data]] {
	$w set row $i,$sc $row
	incr i
    }
}
Added Binaries/Solaris-x86/craplzma0.1/libcraplzma0.1.so.

cannot compute difference between binary files

Added Binaries/Solaris-x86/craplzma0.1/pkgIndex.tcl.










>
>
>
>
>
1
2
3
4
5
#
# Tcl package index file
#
package ifneeded miniarc::crap::lzma 0.1 \
    [list load [file join $dir libcraplzma0.1.so] craplzma]
Added Binaries/Solaris-x86/installkit.

cannot compute difference between binary files

Added Binaries/Solaris-x86/tkdnd1.0/License.txt.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
This software (tkdnd) is copyrighted by:
    George Petasis,
    Software and Knowledge Engineering Laboratory,
    Institute of Informatics and Telecommunications,
    National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and 
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

The following terms apply to all files associated
with the software unless explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
Added Binaries/Solaris-x86/tkdnd1.0/Readme.txt.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
                  
	    tkdnd: Tk Drag & Drop extension
		     (Version 1.0.0)

This directory holds a collection of files that add native drag & drop
capabilities to the tk toolkit. It is designed for tk versions >= 8.3.3,
but with simple modifications can be applied to any tk version greater than
8.1.

Remember that this software is in development. Please report any bugs or
feature requests directly to the author (petasis@iit.demokritos.gr) or by
posting on the comp.lang.tcl newsgroup. In the latter case, please use
"tkdnd" in the title of the posting.

This software (tkdnd) is copyrighted by:
    George Petasis, National Centre for Scientific Research "Demokritos",
    Aghia Paraskevi, Athens, Greece.
    e-mail: petasis@iit.demokritos.gr
                 and
    Laurent Riesterer, Rennes, France.
    e-mail: (laurent.riesterer@free.fr)

and is under the same license that covers tcl. Free to use for anything :-)

For any questions and suggestions contact me at

  petasis@iit.demokritos.gr

or post a question at comp.lang.tcl (preferable)
Added Binaries/Solaris-x86/tkdnd1.0/libtkdnd1.0.so.

cannot compute difference between binary files

Added Binaries/Solaris-x86/tkdnd1.0/pkgIndex.tcl.






















>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
namespace eval ::dnd {
    proc _load {dir} {
	set version 1.0
	load [file join $dir libtkdnd1.0.so] tkdnd
	source [file join $dir tkdnd.tcl]
	package provide tkdnd 1.0
	rename ::dnd::_load {}
    }
}

package ifneeded tkdnd 1.0  [list ::dnd::_load $dir]
Added Binaries/Solaris-x86/tkdnd1.0/tkdnd.tcl.
















































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#
# tkdnd.tcl --
# 
#    This file implements some utility procedures that are used by the tkDND
#    package.
#
# This software is copyrighted by:
# George Petasis, National Centre for Scientific Research "Demokritos",
# Aghia Paraskevi, Athens, Greece.
# e-mail: petasis@iit.demokritos.gr
#
# The following terms apply to all files associated
# with the software unless explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
# and license this software and its documentation for any purpose, provided
# that existing copyright notices are retained in all copies and that this
# notice is included verbatim in any distributions. No written agreement,
# license, or royalty fee is required for any of the authorized uses.
# Modifications to this software may be copyrighted by their authors
# and need not follow the licensing terms described here, provided that
# the new terms are clearly indicated on the first page of each file where
# they apply.
# 
# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# 
# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
# MODIFICATIONS.
#

namespace eval ::dnd {
    variable AskSelectedAction
    
    # This procedure is used just to ensure that the object given as its
    # argument can be accessed as a binary object. Many thanks to Paul Duffin
    # for the idea :-)
    proc ConvertToBinary {object} {
	binary scan $object {}
	return $object
    }

    # This procedure handles the special case where we want items into a canvas
    # widget to be drop targets. It emulates this case as follows:
    #
    #  The tkDND extension is able to deliver events only to real windows
    #  (that means tk widgets). This procedure can be the binding script of all
    #  dnd events we are interested in being received by the canvas items.
    #  When this function is called, it tries to find the item that the mouse
    #  is over (if any). Then it examines its bindings, and if it finds the
    #  dnd related event that is processing it delivers this event to the
    #  particular item. Fianlly, it tries to emulate <DragEnter>/<DragLeave>
    #  on every canvas item...
    proc CanvasDeliverEvent {
	event actions action button source_codes curr_code data descriptions
	mods type source_types win X x Y y
    } {
	# This function will find the topmost item that the mouse is over, and
	# Deliver the event specified by the "event" arg to this item...
	global CanvasDeliverEventStatus
	switch $event {
	    <DragEnter>  -
	    <<DragEnter>> {set CanvasDeliverEventStatus(item) {}}
	    default {}
	}

	# Translate mouse coordinates to canvas coordinates...
	set cx [$win canvasx $x]
	set cy [$win canvasy $y]
	set cx_1 [expr {$cx+1}]
	set cy_1 [expr {$cy+1}]
	# Find all tags that are under the mouse...
	set tags [$win find overlapping $cx $cy $cx_1 $cy_1]
	# ... and select the topmost...
	set length [llength $tags]

	# If no tags under the mouse, return...
	if {!$length} {
	    #puts -->$CanvasDeliverEventStatus(item)
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (1) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    set CanvasDeliverEventStatus(item) {}
	    update
	    if {[string equal $event <<Drag>>]} {
		return -code break
	    }
	    return $action
	}
	if {$length == 1} {
	    set id $tags
	} else {
	    set id [$win find closest $cx $cy]
	}

	# Now in "id" we have the tag of the item below the mouse...
	# Has this item a binding?
	foreach tag [concat $id [$win gettags $id]] {
	    set binding [$win bind $tag $event]
	    if {[string length $binding]} {break}
	}
	
	# Is this tag the same as the last one? If is different, we
	# have to send a leave event to the previous item and an enter
	# event to this one...
	if {$CanvasDeliverEventStatus(item) != $id} {
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (2) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    # Send <<DndEnter>>...
	    set _id $id
	    set _binding {}
	    foreach _tag [concat $_id [$win gettags $_id]] {
		set _binding [$win bind $_tag <<DragEnter>>]
		if {[string length $_binding]} {break}
	    }
	    # puts "Sending <DragEnter> to $tag ($_binding)"
	    set script {}
	    foreach element $_binding {
		switch $element {
		    %% {lappend script %}       
		    %A {lappend script $action}
		    %a {lappend script $actions}
		    %b {lappend script $button}
		    %C {lappend script $source_codes}
		    %c {lappend script $curr_code}
		    %D {lappend script $data}
		    %d {lappend script $descriptions}
		    %m {lappend script $mods}
		    %T {lappend script $type}
		    %t {lappend script $source_types}
		    %W {lappend script $win}
		    %X {lappend script $X}
		    %x {lappend script $x}
		    %Y {lappend script $Y}
		    %y {lappend script $y}
		    %I {lappend script $_id}
		    default {lappend script $element}
		}
	    }
	    if {[llength $script]} {uplevel 1 $script}
	    set CanvasDeliverEventStatus(item) $id
	}

	set script {}
	foreach element $binding {
	    switch $element {
		%% {lappend script %}       
		%A {lappend script $action}
		%a {lappend script $actions}
		%b {lappend script $button}
		%C {lappend script $source_codes}
		%c {lappend script $curr_code}
		%D {lappend script $data}
		%d {lappend script $descriptions}
		%m {lappend script $mods}
		%T {lappend script $type}
		%t {lappend script $source_types}
		%W {lappend script $win}
		%X {lappend script $X}
		%x {lappend script $x}
		%Y {lappend script $Y}
		%y {lappend script $y}
		%I {lappend script $id}
		default {lappend script $element}
	    }
	}
	if {[llength $script]} {
	    return [uplevel 1 $script]
	}
	set CanvasDeliverEventStatus(item) {}
	update
	if {[string equal $event <<Drag>>]} {
	    return -code break
	}
	return $action
    }

    # ChooseAskAction --
    #   This procedure displays a dialog with the help of which the user can
    #   select one of the supported actions...
    proc ChooseAskAction {window x y actions descriptions args} {
	variable AskSelectedAction
	set title {Please Select Action:}
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} {
		set title $descr
		break
	    }
	}

	set menu $window.__tk_dnd[pwd]__action_ask__Drop_window_[pid]
	catch {destroy $menu}
	menu $menu -title $title -tearoff 0 -disabledforeground darkgreen
	$menu add command -font {helvetica 12 bold} \
		-label $title -command "destroy $menu" -state disabled
	$menu add separator

	set items 0
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} continue
	    $menu add command -label $descr -command \
		    "set ::dnd::AskSelectedAction $action; destroy $menu"
	    incr items
	}
	if {!$items} {
	    # The drag source accepts the ask action, but has no defined
	    # action list? Add copy action at least...
	    $menu add command -label Copy -command \
		    "set ::dnd::AskSelectedAction copy; destroy $menu"
	}
	
	$menu add separator
	$menu add command -label {Cancel Drop} -command \
		"set ::dnd::AskSelectedAction none; destroy $menu"

	set AskSelectedAction none
	tk_popup $menu $x $y
	update
	bind $menu <Unmap> {after idle {catch {destroy %W}}}
	tkwait window $menu
	
	return $AskSelectedAction
    }
};# namespace eval ::dnd

# EOF
Added Binaries/Windows/Tktable2.9/Tktable29.dll.

cannot compute difference between binary files

Added Binaries/Windows/Tktable2.9/license.txt.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
		   * COPYRIGHT AND LICENSE TERMS *

(This file blatantly stolen from Tcl/Tk license and adapted - thus assume
it falls under similar license terms).

This software is copyrighted by Jeffrey Hobbs <jeff.hobbs@acm.org>.  The
following terms apply to all files associated with the software unless
explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute, and
license this software and its documentation for any purpose, provided that
existing copyright notices are retained in all copies and that this notice
is included verbatim in any distributions.  No written agreement, license,
or royalty fee is required for any of the authorized uses.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS
PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government
is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
of the Rights in Technical Data and Computer Software Clause as DFARS
252.227-7013 and FAR 52.227-19.

SPECIAL NOTES:

This software also falls under the bourbon_ware clause:

    Should you find this software useful in your daily work, you should
    feel obliged to take the author out for a drink if the opportunity
    presents itself.  The user may feel exempt from this clause if they
    are under 21 or think the author has already partaken of too many
    drinks.
Added Binaries/Windows/Tktable2.9/pkgIndex.tcl.




>
>
1
2
if {[catch {package require Tcl 8.2}]} return
package ifneeded Tktable 2.9  [list load [file join $dir Tktable29.dll] Tktable]
Added Binaries/Windows/Tktable2.9/readme.txt.






















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
 * Conceptually based on Tk3 table widget by Roland King (rols@lehman.com)
 *
 * see ChangeLog file for details
 *
 * current maintainer: jeff.hobbs@acm.org
 *
 * Copyright 1997-2002, Jeffrey Hobbs (jeff@hobbs.org)
 */

		*************************************
		  The Tk Table Widget Version 2.0+
		*************************************

INTRODUCTION

TkTable is a table/matrix widget extension to tk/tcl.
The basic features of the widget are:

 * multi-line cells
 * support for embedded windows (one per cell)
 * row & column spanning
 * variable width columns / height rows (interactively resizable)
 * row and column titles
 * multiple data sources ((Tcl array || Tcl command) &| internal caching)
 * supports standard Tk reliefs, fonts, colors, etc.
 * x/y scrollbar support
 * 'tag' styles per row, column or cell to change visual appearance
 * in-cell editing - returns value back to data source
 * support for disabled (read-only) tables or cells (via tags)
 * multiple selection modes, with "active" cell
 * multiple drawing modes to get optimal performance for larger tables
 * optional 'flashes' when things update
 * cell validation support
 * Works everywhere Tk does (including Windows and Mac!)
 * Unicode support (Tk8.1+)

FINDING THE WIDGET

0. The newest version is most likely found at:
	http://tktable.sourceforge.net/
	http://www.purl.org/net/hobbs/tcl/capp/

BUILDING AND INSTALLING THE WIDGET

1. Uncompress and unpack the distribution

   ON UNIX:
	gzip -cd Tktable<version>.tar.gz | tar xf -

   ON WINDOWS:
	use something like WinZip to unpack the archive.

   ON MACINTOSH:
	use StuffIt Expander to unstuff the archive.
    
   This will create a subdirectory tkTable<version> with all the files in it.

2. Configure

   ON UNIX:
        cd Tktable<version>
	./configure

   tkTable uses information left in tkConfig.sh when you built tk.  This
   file will be found in $exec_prefix/lib/.  You might set the --prefix and
   --exec-prefix options of configure if you don't want the default
   (/usr/local).  If building on multiple unix platforms, the following is
   recommended to isolate build conflicts:
	mkdir <builddir>/<platform>
	cd !$
	/path/to/Tktable<version>/configure

   ON WINDOWS:

   Version 2.8 added support for building in the cygwin environment on
   Windows based on TEA (http://www.tcl.tk/doc/tea/).  You can retrieve
   cygwin from:
	http://sources.redhat.com/cygwin/

   Inside the cygwin environment, you build the same as on Unix.

   Otherwise, hack makefile.vc until it works and compile.  It has problems
   executing wish from a path with a space in it, but the DLL builds just
   fine.  A DLL should be available where you found this archive.

   ON MACINTOSH:
   
   Hack the CodeWarrior XML project mac_tkTable.mcp.xml until it works and
   compile.  The access path to the Tcl/Tk source tree will probably need
   adjusting.  A DLL should be available where you found this archive.

3. Make and Install

   ON UNIX or WINDOWS (with cygwin):
	make
	make test (OPTIONAL)
	make install

   ON WINDOWS (makefile.vc):
	nmake -f makefile.vc
	nmake -f makefile.vc test (OPTIONAL)
	nmake -f makefile.vc install

   ON MACINTOSH:
	Place Tktable.shlb in the Tool Command Language folder

   tkTable is built to comply to the latest tcl package conventions.
   There is also a specific "make static" for those who need it.

4. Use it

   Start a regular wish interpreter, 'load' the library, and use the table.
   Or use the "tablewish" interpreter that has the 'table' command built in.
   There are a few test scripts in the demos directory which you can source.

5. Read the documentation

   There is a Unix manpage and HTML translation provided in the doc/
   subdirectory.  These describe the table widget's features and commands
   in depth.  If something is confusing, just to try it out.


THINGS TO WATCH OUT FOR

Packing
  The table tries not to allocate huge chunks of screen real estate if
  you ask it for a lot of rows and columns.  You can always stretch out
  the frame or explicitly tell it how big it can be.  If you want to
  stretch the table, remember to pack it with fill both and expand on,
  or with grid, give it -sticky news and configure the grid row and column
  for some weighting.

Array   
  The array elements for the table are of the form array(2,3) etc.  Make
  sure there are no spaces around the ','.  Negative indices are allowed.

Editing
  If you can't edit, remember that the focus model in tk is explicit, so
  you need to click on the table or give it the focus command.  Just
  having a selected cell is not the same thing as being able to edit.
  You also need the editing cursor.  If you can't get the cursor, make
  sure that you actually have a variable assigned to the table, and that
  the "state" of the cell is not disabled.

COMMENTS, BUGS, etc.

* Please can you send comments and bug reports to the current maintainer
  and their best will be done to address them.  A mailing list for
  tktable discussion is tktable-users@lists.sourceforge.net.

* If you find a bug, a short piece of Tcl that exercises it would be very
  useful, or even better, compile with debugging and specify where it
  crashed in that short piece of Tcl.  Use the SourceForge site to check
  for known bugs or submit new ones.
Added Binaries/Windows/Tktable2.9/tkTable.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
# table.tcl --
#
# Version align with tkTable 2.7, jeff.hobbs@acm.org
# This file defines the default bindings for Tk table widgets
# and provides procedures that help in implementing those bindings.
#
# RCS: @(#) $Id: tkTable.tcl,v 1.13 2004/11/19 04:27:11 hobbs Exp $

#--------------------------------------------------------------------------
# ::tk::table::Priv elements used in this file:
#
# x && y -		Coords in widget
# afterId -		Token returned by "after" for autoscanning.
# tablePrev -		The last element to be selected or deselected
#			during a selection operation.
# mouseMoved -		Boolean to indicate whether mouse moved while
#			the button was pressed.
# borderInfo -		Boolean to know if the user clicked on a border
# borderB1 -		Boolean that set whether B1 can be used for the
#			interactiving resizing
#--------------------------------------------------------------------------

namespace eval ::tk::table {
    # Ensure that a namespace is created for us
    variable Priv
    array set Priv [list x 0 y 0 afterId {} mouseMoved 0 \
	    borderInfo {} borderB1 1]
}

# ::tk::table::ClipboardKeysyms --
# This procedure is invoked to identify the keys that correspond to
# the "copy", "cut", and "paste" functions for the clipboard.
#
# Arguments:
# copy -	Name of the key (keysym name plus modifiers, if any,
#		such as "Meta-y") used for the copy operation.
# cut -		Name of the key used for the cut operation.
# paste -	Name of the key used for the paste operation.

proc ::tk::table::ClipboardKeysyms {copy cut paste} {
    bind Table <$copy>	{tk_tableCopy %W}
    bind Table <$cut>	{tk_tableCut %W}
    bind Table <$paste>	{tk_tablePaste %W}
}
::tk::table::ClipboardKeysyms <Copy> <Cut> <Paste>

##
## Interactive cell resizing, affected by -resizeborders option
##
bind Table <3>		{
    ## You might want to check for cell returned if you want to
    ## restrict the resizing of certain cells
    %W border mark %x %y
}
bind Table <B3-Motion>	{ %W border dragto %x %y }

## Button events

bind Table <1> { ::tk::table::Button1 %W %x %y }
bind Table <B1-Motion> { ::tk::table::B1Motion %W %x %y }

bind Table <ButtonRelease-1> {
    if {$::tk::table::Priv(borderInfo) == "" && [winfo exists %W]} {
	::tk::table::CancelRepeat
	%W activate @%x,%y
    }
}
bind Table <Double-1> {
    # empty
}

bind Table <Shift-1>	{::tk::table::BeginExtend %W [%W index @%x,%y]}
bind Table <Control-1>	{::tk::table::BeginToggle %W [%W index @%x,%y]}
bind Table <B1-Enter>	{::tk::table::CancelRepeat}
bind Table <B1-Leave>	{
    if {$::tk::table::Priv(borderInfo) == ""} {
	array set ::tk::table::Priv {x %x y %y}
	::tk::table::AutoScan %W
    }
}
bind Table <2> {
    %W scan mark %x %y
    array set ::tk::table::Priv {x %x y %y}
    set ::tk::table::Priv(mouseMoved) 0
}
bind Table <B2-Motion> {
    if {(%x != $::tk::table::Priv(x)) || (%y != $::tk::table::Priv(y))} {
	set ::tk::table::Priv(mouseMoved) 1
    }
    if {$::tk::table::Priv(mouseMoved)} { %W scan dragto %x %y }
}
bind Table <ButtonRelease-2> {
    if {!$::tk::table::Priv(mouseMoved)} { tk_tablePaste %W [%W index @%x,%y] }
}

## Key events

# This forces a cell commit if an active cell exists
bind Table <<Table_Commit>> {
    catch {%W activate active}
}
# Remove this if you don't want cell commit to occur on every Leave for
# the table (via mouse) or FocusOut (loss of focus by table).
event add <<Table_Commit>> <Leave> <FocusOut>

bind Table <Shift-Up>		{::tk::table::ExtendSelect %W -1  0}
bind Table <Shift-Down>		{::tk::table::ExtendSelect %W  1  0}
bind Table <Shift-Left>		{::tk::table::ExtendSelect %W  0 -1}
bind Table <Shift-Right>	{::tk::table::ExtendSelect %W  0  1}
bind Table <Prior>		{%W yview scroll -1 pages; %W activate topleft}
bind Table <Next>		{%W yview scroll  1 pages; %W activate topleft}
bind Table <Control-Prior>	{%W xview scroll -1 pages}
bind Table <Control-Next>	{%W xview scroll  1 pages}
bind Table <Home>		{%W see origin}
bind Table <End>		{%W see end}
bind Table <Control-Home> {
    %W selection clear all
    %W activate origin
    %W selection set active
    %W see active
}
bind Table <Control-End> {
    %W selection clear all
    %W activate end
    %W selection set active
    %W see active
}
bind Table <Shift-Control-Home>	{::tk::table::DataExtend %W origin}
bind Table <Shift-Control-End>	{::tk::table::DataExtend %W end}
bind Table <Select>		{::tk::table::BeginSelect %W [%W index active]}
bind Table <Shift-Select>	{::tk::table::BeginExtend %W [%W index active]}
bind Table <Control-slash>	{::tk::table::SelectAll %W}
bind Table <Control-backslash> {
    if {[string match browse [%W cget -selectmode]]} {%W selection clear all}
}
bind Table <Up>			{::tk::table::MoveCell %W -1  0}
bind Table <Down>		{::tk::table::MoveCell %W  1  0}
bind Table <Left>		{::tk::table::MoveCell %W  0 -1}
bind Table <Right>		{::tk::table::MoveCell %W  0  1}
bind Table <KeyPress>		{::tk::table::Insert %W %A}
bind Table <BackSpace>		{::tk::table::BackSpace %W}
bind Table <Delete>		{%W delete active insert}
bind Table <Escape>		{%W reread}

#bind Table <Return>		{::tk::table::MoveCell %W 1 0}
bind Table <Return>		{::tk::table::Insert %W "\n"}

bind Table <Control-Left>	{%W icursor [expr {[%W icursor]-1}]}
bind Table <Control-Right>	{%W icursor [expr {[%W icursor]+1}]}
bind Table <Control-e>		{%W icursor end}
bind Table <Control-a>		{%W icursor 0}
bind Table <Control-k>		{%W delete active insert end}
bind Table <Control-equal>	{::tk::table::ChangeWidth %W active  1}
bind Table <Control-minus>	{::tk::table::ChangeWidth %W active -1}

# Ignore all Alt, Meta, and Control keypresses unless explicitly bound.
# Otherwise, if a widget binding for one of these is defined, the
# <KeyPress> class binding will also fire and insert the character,
# which is wrong.  Ditto for Tab.

bind Table <Alt-KeyPress>	{# nothing}
bind Table <Meta-KeyPress>	{# nothing}
bind Table <Control-KeyPress>	{# nothing}
bind Table <Any-Tab>		{# nothing}
if {[string match "macintosh" $::tcl_platform(platform)]} {
    bind Table <Command-KeyPress> {# nothing}
}

# ::tk::table::GetSelection --
#   This tries to obtain the default selection.  On Unix, we first try
#   and get a UTF8_STRING, a type supported by modern Unix apps for
#   passing Unicode data safely.  We fall back on the default STRING
#   type otherwise.  On Windows, only the STRING type is necessary.
# Arguments:
#   w	The widget for which the selection will be retrieved.
#	Important for the -displayof property.
#   sel	The source of the selection (PRIMARY or CLIPBOARD)
# Results:
#   Returns the selection, or an error if none could be found
#
if {[string compare $::tcl_platform(platform) "unix"]} {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
} else {
    proc ::tk::table::GetSelection {w {sel PRIMARY}} {
	if {[catch {selection get -displayof $w -selection $sel \
		-type UTF8_STRING} txt] \
		&& [catch {selection get -displayof $w -selection $sel} txt]} {
	    return -code error "could not find default selection"
	} else {
	    return $txt
	}
    }
}

# ::tk::table::CancelRepeat --
# A copy of tkCancelRepeat, just in case it's not available or changes.
# This procedure is invoked to cancel an auto-repeat action described
# by ::tk::table::Priv(afterId).  It's used by several widgets to auto-scroll
# the widget when the mouse is dragged out of the widget with a
# button pressed.
#
# Arguments:
# None.

proc ::tk::table::CancelRepeat {} {
    variable Priv
    after cancel $Priv(afterId)
    set Priv(afterId) {}
}

# ::tk::table::Insert --
#
#   Insert into the active cell
#
# Arguments:
#   w	- the table widget
#   s	- the string to insert
# Results:
#   Returns nothing
#
proc ::tk::table::Insert {w s} {
    if {[string compare $s {}]} {
	$w insert active insert $s
    }
}

# ::tk::table::BackSpace --
#
#   BackSpace in the current cell
#
# Arguments:
#   w	- the table widget
# Results:
#   Returns nothing
#
proc ::tk::table::BackSpace {w} {
    set cur [$w icursor]
    if {[string compare {} $cur] && $cur} {
	$w delete active [expr {$cur-1}]
    }
}

# ::tk::table::Button1 --
#
# This procedure is called to handle selecting with mouse button 1.
# It will distinguish whether to start selection or mark a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::Button1 {w x y} {
    variable Priv
    #
    # $Priv(borderInfo) is null if the user did not click on a border
    #
    if {$Priv(borderB1) == 1} {
	set Priv(borderInfo) [$w border mark $x $y]
	# account for what resizeborders are set [Bug 876320] (ferenc)
	set rbd [$w cget -resizeborders]
	if {$rbd == "none" || ![llength $Priv(borderInfo)]
	    || ($rbd == "col" && [lindex $Priv(borderInfo) 1] == "")
	    || ($rbd == "row" && [lindex $Priv(borderInfo) 0] == "")} {
	    set Priv(borderInfo) ""
	}
    } else {
	set Priv(borderInfo) ""
    }
    if {$Priv(borderInfo) == ""} {
	#
	# Only do this when a border wasn't selected
	#
	if {[winfo exists $w]} {
	    ::tk::table::BeginSelect $w [$w index @$x,$y]
	    focus $w
	}
	array set Priv [list x $x y $y]
	set Priv(mouseMoved) 0
    }
}

# ::tk::table::B1Motion --
#
# This procedure is called to start processing mouse motion events while
# button 1 moves while pressed.  It will distinguish whether to change
# the selection or move a border.
#
# Arguments:
#   w	- the table widget
#   x	- x coord
#   y	- y coord
# Results:
#   Returns nothing
#
proc ::tk::table::B1Motion {w x y} {
    variable Priv

    # If we already had motion, or we moved more than 1 pixel,
    # then we start the Motion routine
    if {$Priv(borderInfo) != ""} {
	#
	# If the motion is on a border, drag it and skip the rest
	# of this binding.
	#
	$w border dragto $x $y
    } else {
	#
	# If we already had motion, or we moved more than 1 pixel,
	# then we start the Motion routine
	#
	if {
	    $::tk::table::Priv(mouseMoved)
	    || abs($x-$::tk::table::Priv(x)) > 1
	    || abs($y-$::tk::table::Priv(y)) > 1
	} {
	    set ::tk::table::Priv(mouseMoved) 1
	}
	if {$::tk::table::Priv(mouseMoved)} {
	    ::tk::table::Motion $w [$w index @$x,$y]
	}
    }
}

# ::tk::table::BeginSelect --
#
# This procedure is typically invoked on button-1 presses. It begins
# the process of making a selection in the table. Its exact behavior
# depends on the selection mode currently in effect for the table;
# see the Motif documentation for details.
#
# Arguments:
# w	- The table widget.
# el	- The element for the selection operation (typically the
#	one under the pointer).  Must be in row,col form.

proc ::tk::table::BeginSelect {w el} {
    variable Priv
    if {[scan $el %d,%d r c] != 2} return
    switch [$w cget -selectmode] {
	multiple {
	    if {[$w tag includes title $el]} {
		## in the title area
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			set inc topleft
			set el2 end
		    } else {
			set inc [$w index topleft row],$c
			set el2 [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    set inc $r,[$w index topleft col]
		    set el2 $r,[$w index end col]
		}
	    } else {
		set inc $el
		set el2 $el
	    }
	    if {[$w selection includes $inc]} {
		$w selection clear $el $el2
	    } else {
		$w selection set $el $el2
	    }
	}
	extended {
	    $w selection clear all
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection set $el end
		    } else {
			$w selection set $el [$w index end row],$c
		    }
		} else {
		    ## We're in a row header
		    $w selection set $el $r,[$w index end col]
		}
	    } else {
		$w selection set $el
	    }
	    $w selection anchor $el
	    set Priv(tablePrev) $el
	}
	default {
	    if {![$w tag includes title $el]} {
		$w selection clear all
		$w selection set $el
		set Priv(tablePrev) $el
	    }
	    $w selection anchor $el
	}
    }
}

# ::tk::table::Motion --
#
# This procedure is called to process mouse motion events while
# button 1 is down. It may move or extend the selection, depending
# on the table's selection mode.
#
# Arguments:
# w	- The table widget.
# el	- The element under the pointer (must be in row,col form).

proc ::tk::table::Motion {w el} {
    variable Priv
    if {![info exists Priv(tablePrev)]} {
	set Priv(tablePrev) $el
	return
    }
    if {[string match $Priv(tablePrev) $el]} return
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set $el
	    set Priv(tablePrev) $el
	}
	extended {
	    # avoid tables that have no anchor index yet.
	    if {[catch {$w index anchor}]} { return }
	    scan $Priv(tablePrev) %d,%d r c
	    scan $el %d,%d elr elc
	    if {[$w tag includes title $el]} {
		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		    ## We're in a column header
		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
			## We're in the topleft title area
			$w selection clear anchor end
		    } else {
			$w selection clear anchor [$w index end row],$c
		    }
		    $w selection set anchor [$w index end row],$elc
		} else {
		    ## We're in a row header
		    $w selection clear anchor $r,[$w index end col]
		    $w selection set anchor $elr,[$w index end col]
		}
	    } else {
		$w selection clear anchor $Priv(tablePrev)
		$w selection set anchor $el
	    }
	    set Priv(tablePrev) $el
	}
    }
}

# ::tk::table::BeginExtend --
#
# This procedure is typically invoked on shift-button-1 presses. It
# begins the process of extending a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginExtend {w el} {
    # avoid tables that have no anchor index yet.
    if {[catch {$w index anchor}]} { return }
    if {[string match extended [$w cget -selectmode]] &&
	[$w selection includes anchor]} {
	::tk::table::Motion $w $el
    }
}

# ::tk::table::BeginToggle --
#
# This procedure is typically invoked on control-button-1 presses. It
# begins the process of toggling a selection in the table. Its
# exact behavior depends on the selection mode currently in effect
# for the table; see the Motif documentation for details.
#
# Arguments:
# w - The table widget.
# el - The element for the selection operation (typically the
# one under the pointer). Must be in numerical form.

proc ::tk::table::BeginToggle {w el} {
    if {[string match extended [$w cget -selectmode]]} {
	variable Priv
	set Priv(tablePrev) $el
	$w selection anchor $el
	if {[$w tag includes title $el]} {
	    scan $el %d,%d r c
	    if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
		## We're in a column header
		if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
		    ## We're in the topleft title area
		    set end end
		} else {
		    set end [$w index end row],$c
		}
	    } else {
		## We're in a row header
		set end $r,[$w index end col]
	    }
	} else {
	    ## We're in a non-title cell
	    set end $el
	}
	if {[$w selection includes  $end]} {
	    $w selection clear $el $end
	} else {
	    $w selection set   $el $end
        }
    }
}

# ::tk::table::AutoScan --
# This procedure is invoked when the mouse leaves an table window
# with button 1 down. It scrolls the window up, down, left, or
# right, depending on where the mouse left the window, and reschedules
# itself as an "after" command so that the window continues to scroll until
# the mouse moves back into the window or the mouse button is released.
#
# Arguments:
# w - The table window.

proc ::tk::table::AutoScan {w} {
    if {![winfo exists $w]} return
    variable Priv
    set x $Priv(x)
    set y $Priv(y)
    if {$y >= [winfo height $w]} {
	$w yview scroll 1 units
    } elseif {$y < 0} {
	$w yview scroll -1 units
    } elseif {$x >= [winfo width $w]} {
	$w xview scroll 1 units
    } elseif {$x < 0} {
	$w xview scroll -1 units
    } else {
	return
    }
    ::tk::table::Motion $w [$w index @$x,$y]
    set Priv(afterId) [after 50 ::tk::table::AutoScan $w]
}

# ::tk::table::MoveCell --
#
# Moves the location cursor (active element) by the specified number
# of cells and changes the selection if we're in browse or extended
# selection mode.  If the new cell is "hidden", we skip to the next
# visible cell if possible, otherwise just abort.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::MoveCell {w x y} {
    if {[catch {$w index active row} r]} return
    set c [$w index active col]
    set cell [$w index [incr r $x],[incr c $y]]
    while {[string compare [set true [$w hidden $cell]] {}]} {
	# The cell is in some way hidden
	if {[string compare $true [$w index active]]} {
	    # The span cell wasn't the previous cell, so go to that
	    set cell $true
	    break
	}
	if {$x > 0} {incr r} elseif {$x < 0} {incr r -1}
	if {$y > 0} {incr c} elseif {$y < 0} {incr c -1}
	if {[string compare $cell [$w index $r,$c]]} {
	    set cell [$w index $r,$c]
	} else {
	    # We couldn't find a non-hidden cell, just don't move
	    return
	}
    }
    $w activate $cell
    $w see active
    switch [$w cget -selectmode] {
	browse {
	    $w selection clear all
	    $w selection set active
	}
	extended {
	    variable Priv
	    $w selection clear all
	    $w selection set active
	    $w selection anchor active
	    set Priv(tablePrev) [$w index active]
	}
    }
}

# ::tk::table::ExtendSelect --
#
# Does nothing unless we're in extended selection mode; in this
# case it moves the location cursor (active element) by the specified
# number of cells, and extends the selection to that point.
#
# Arguments:
# w - The table widget.
# x - +1 to move down one cell, -1 to move up one cell.
# y - +1 to move right one cell, -1 to move left one cell.

proc ::tk::table::ExtendSelect {w x y} {
    if {[string compare extended [$w cget -selectmode]] ||
	[catch {$w index active row} r]} return
    set c [$w index active col]
    $w activate [incr r $x],[incr c $y]
    $w see active
    ::tk::table::Motion $w [$w index active]
}

# ::tk::table::DataExtend
#
# This procedure is called for key-presses such as Shift-KEndData.
# If the selection mode isnt multiple or extend then it does nothing.
# Otherwise it moves the active element to el and, if we're in
# extended mode, extends the selection to that point.
#
# Arguments:
# w - The table widget.
# el - An integer cell number.

proc ::tk::table::DataExtend {w el} {
    set mode [$w cget -selectmode]
    if {[string match extended $mode]} {
	$w activate $el
	$w see $el
	if {[$w selection includes anchor]} {::tk::table::Motion $w $el}
    } elseif {[string match multiple $mode]} {
	$w activate $el
	$w see $el
    }
}

# ::tk::table::SelectAll
#
# This procedure is invoked to handle the "select all" operation.
# For single and browse mode, it just selects the active element.
# Otherwise it selects everything in the widget.
#
# Arguments:
# w - The table widget.

proc ::tk::table::SelectAll {w} {
    if {[regexp {^(single|browse)$} [$w cget -selectmode]]} {
	$w selection clear all
	catch {$w selection set active}
    } elseif {[$w cget -selecttitles]} {
	$w selection set [$w cget -roworigin],[$w cget -colorigin] end
    } else {
	$w selection set origin end
    }
}

# ::tk::table::ChangeWidth --
#
# Adjust the widget of the specified cell by $a.
#
# Arguments:
# w - The table widget.
# i - cell index
# a - amount to adjust by

proc ::tk::table::ChangeWidth {w i a} {
    set tmp [$w index $i col]
    if {[set width [$w width $tmp]] >= 0} {
	$w width $tmp [incr width $a]
    } else {
	$w width $tmp [incr width [expr {-$a}]]
    }
}

# tk_tableCopy --
#
# This procedure copies the selection from a table widget into the
# clipboard.
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCopy w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {clipboard append -displayof $w [::tk::table::GetSelection $w]}
    }
}

# tk_tableCut --
#
# This procedure copies the selection from a table widget into the
# clipboard, then deletes the selection (if it exists in the given
# widget).
#
# Arguments:
# w -		Name of a table widget.

proc tk_tableCut w {
    if {[selection own -displayof $w] == "$w"} {
	clipboard clear -displayof $w
	catch {
	    clipboard append -displayof $w [::tk::table::GetSelection $w]
	    $w cursel {}
	    $w selection clear all
	}
    }
}

# tk_tablePaste --
#
# This procedure pastes the contents of the clipboard to the specified
# cell (active by default) in a table widget.
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePaste {w {cell {}}} {
    if {[string compare {} $cell]} {
	if {[catch {::tk::table::GetSelection $w} data]} return
    } else {
	if {[catch {::tk::table::GetSelection $w CLIPBOARD} data]} {
	    return
	}
	set cell active
    }
    tk_tablePasteHandler $w [$w index $cell] $data
    if {[$w cget -state] == "normal"} {focus $w}
}

# tk_tablePasteHandler --
#
# This procedure handles how data is pasted into the table widget.
# This handles data in the default table selection form.
#
# NOTE: this allows pasting into all cells except title cells,
#       even those with -state disabled
#
# Arguments:
# w -		Name of a table widget.
# cell -	Cell to start pasting in.
#
proc tk_tablePasteHandler {w cell data} {
    #
    # Don't allow pasting into the title cells
    #
    if {[$w tag includes title $cell]} {
        return
    }

    set rows	[expr {[$w cget -rows]-[$w cget -roworigin]}]
    set cols	[expr {[$w cget -cols]-[$w cget -colorigin]}]
    set r	[$w index $cell row]
    set c	[$w index $cell col]
    set rsep	[$w cget -rowseparator]
    set csep	[$w cget -colseparator]
    ## Assume separate rows are split by row separator if specified
    ## If you were to want multi-character row separators, you would need:
    # regsub -all $rsep $data <newline> data
    # set data [join $data <newline>]
    if {[string compare {} $rsep]} { set data [split $data $rsep] }
    set row	$r
    foreach line $data {
	if {$row > $rows} break
	set col	$c
	## Assume separate cols are split by col separator if specified
	## Unless a -separator was specified
	if {[string compare {} $csep]} { set line [split $line $csep] }
	## If you were to want multi-character col separators, you would need:
	# regsub -all $csep $line <newline> line
	# set line [join $line <newline>]
	foreach item $line {
	    if {$col > $cols} break
	    $w set $row,$col $item
	    incr col
	}
	incr row
    }
}

# tk::table::Sort --
#
# This procedure handles how data is sorted in the table widget.
# This isn't currently used by tktable, but can be called by the user.
# It's behavior may change in the future.
#
# Arguments:
# w -		Name of a table widget.
# start -	start cell of rectangle to sort
# end -		end cell of rectangle to sort
# col -		column within rectangle to sort on
# args -	passed to lsort proc (ie: -integer -decreasing)

proc ::tk::table::Sort {w start end col args} {
    set start [$w index $start]
    set end   [$w index $end]
    scan $start %d,%d sr sc
    scan $end   %d,%d er ec
    if {($col < $sc) || ($col > $ec)} {
	return -code error "$col is not within sort range $sc to $ec"
    }
    set col [expr {$col - $sc}]

    set data {}
    for {set i $sr} {$i <= $er} {incr i} {
	lappend data [$w get $i,$sc $i,$ec]
    }

    set i $sr
    foreach row [eval [list lsort -index $col] $args [list $data]] {
	$w set row $i,$sc $row
	incr i
    }
}
Added Binaries/Windows/craplzma0.1/craplzma01.dll.

cannot compute difference between binary files

Added Binaries/Windows/craplzma0.1/pkgIndex.tcl.










>
>
>
>
>
1
2
3
4
5
#
# Tcl package index file
#
package ifneeded miniarc::crap::lzma 0.1 \
    [list load [file join $dir craplzma01.dll] craplzma]
Added Binaries/Windows/installkit.com.

cannot compute difference between binary files

Added Binaries/Windows/installkit.exe.

cannot compute difference between binary files

Added Binaries/Windows/installkitA.exe.

cannot compute difference between binary files

Added Binaries/Windows/installkitU.exe.

cannot compute difference between binary files

Added Binaries/Windows/installkitUA.exe.

cannot compute difference between binary files

Added Binaries/Windows/tkdnd1.0/libtkdnd10.dll.

cannot compute difference between binary files

Added Binaries/Windows/tkdnd1.0/pkgIndex.tcl.






































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace eval ::dnd {
    proc _load {dir} {
	set version 1.0
	switch $::tcl_platform(platform) {
	  windows {
	    load [file join $dir libtkdnd[string map {. {}} \
		$version][info sharedlibext]] tkdnd
	  }
	  default {
	    load [file join $dir libtkdnd1.0.so] tkdnd
	  }
	}
	source [file join $dir tkdnd.tcl]
	package provide tkdnd 1.0
	rename ::dnd::_load {}
    }
}

package ifneeded tkdnd 1.0  [list ::dnd::_load $dir]
Added Binaries/Windows/tkdnd1.0/tkdnd.tcl.
















































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#
# tkdnd.tcl --
# 
#    This file implements some utility procedures that are used by the tkDND
#    package.
#
# This software is copyrighted by:
# George Petasis, National Centre for Scientific Research "Demokritos",
# Aghia Paraskevi, Athens, Greece.
# e-mail: petasis@iit.demokritos.gr
#
# The following terms apply to all files associated
# with the software unless explicitly disclaimed in individual files.
#
# The authors hereby grant permission to use, copy, modify, distribute,
# and license this software and its documentation for any purpose, provided
# that existing copyright notices are retained in all copies and that this
# notice is included verbatim in any distributions. No written agreement,
# license, or royalty fee is required for any of the authorized uses.
# Modifications to this software may be copyrighted by their authors
# and need not follow the licensing terms described here, provided that
# the new terms are clearly indicated on the first page of each file where
# they apply.
# 
# IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
# FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
# ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
# DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# 
# THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
# IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
# NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
# MODIFICATIONS.
#

namespace eval ::dnd {
    variable AskSelectedAction
    
    # This procedure is used just to ensure that the object given as its
    # argument can be accessed as a binary object. Many thanks to Paul Duffin
    # for the idea :-)
    proc ConvertToBinary {object} {
	binary scan $object {}
	return $object
    }

    # This procedure handles the special case where we want items into a canvas
    # widget to be drop targets. It emulates this case as follows:
    #
    #  The tkDND extension is able to deliver events only to real windows
    #  (that means tk widgets). This procedure can be the binding script of all
    #  dnd events we are interested in being received by the canvas items.
    #  When this function is called, it tries to find the item that the mouse
    #  is over (if any). Then it examines its bindings, and if it finds the
    #  dnd related event that is processing it delivers this event to the
    #  particular item. Fianlly, it tries to emulate <DragEnter>/<DragLeave>
    #  on every canvas item...
    proc CanvasDeliverEvent {
	event actions action button source_codes curr_code data descriptions
	mods type source_types win X x Y y
    } {
	# This function will find the topmost item that the mouse is over, and
	# Deliver the event specified by the "event" arg to this item...
	global CanvasDeliverEventStatus
	switch $event {
	    <DragEnter>  -
	    <<DragEnter>> {set CanvasDeliverEventStatus(item) {}}
	    default {}
	}

	# Translate mouse coordinates to canvas coordinates...
	set cx [$win canvasx $x]
	set cy [$win canvasy $y]
	set cx_1 [expr {$cx+1}]
	set cy_1 [expr {$cy+1}]
	# Find all tags that are under the mouse...
	set tags [$win find overlapping $cx $cy $cx_1 $cy_1]
	# ... and select the topmost...
	set length [llength $tags]

	# If no tags under the mouse, return...
	if {!$length} {
	    #puts -->$CanvasDeliverEventStatus(item)
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (1) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    set CanvasDeliverEventStatus(item) {}
	    update
	    if {[string equal $event <<Drag>>]} {
		return -code break
	    }
	    return $action
	}
	if {$length == 1} {
	    set id $tags
	} else {
	    set id [$win find closest $cx $cy]
	}

	# Now in "id" we have the tag of the item below the mouse...
	# Has this item a binding?
	foreach tag [concat $id [$win gettags $id]] {
	    set binding [$win bind $tag $event]
	    if {[string length $binding]} {break}
	}
	
	# Is this tag the same as the last one? If is different, we
	# have to send a leave event to the previous item and an enter
	# event to this one...
	if {$CanvasDeliverEventStatus(item) != $id} {
	    if {[string length $CanvasDeliverEventStatus(item)]} {
		# Send <<DragLeave>>...
		set _id $CanvasDeliverEventStatus(item)
		set _binding {}
		foreach _tag [concat $_id [$win gettags $_id]] {
		    set _binding [$win bind $_tag <<DragLeave>>]
		    if {[string length $_binding]} {break}
		}
		# puts "Sending <DragLeave> (2) to $_id ($_binding)"
		set script {}
		foreach element $_binding {
		    switch $element {
			%% {lappend script %}       
			%A {lappend script $action}
			%a {lappend script $actions}
			%b {lappend script $button}
			%C {lappend script $source_codes}
			%c {lappend script $curr_code}
			%D {lappend script $data}
			%d {lappend script $descriptions}
			%m {lappend script $mods}
			%T {lappend script $type}
			%t {lappend script $source_types}
			%W {lappend script $win}
			%X {lappend script $X}
			%x {lappend script $x}
			%Y {lappend script $Y}
			%y {lappend script $y}
			%I {lappend script $_id}
			default {lappend script $element}
		    }
		}
		if {[llength $script]} {uplevel 1 $script}
	    }
	    # Send <<DndEnter>>...
	    set _id $id
	    set _binding {}
	    foreach _tag [concat $_id [$win gettags $_id]] {
		set _binding [$win bind $_tag <<DragEnter>>]
		if {[string length $_binding]} {break}
	    }
	    # puts "Sending <DragEnter> to $tag ($_binding)"
	    set script {}
	    foreach element $_binding {
		switch $element {
		    %% {lappend script %}       
		    %A {lappend script $action}
		    %a {lappend script $actions}
		    %b {lappend script $button}
		    %C {lappend script $source_codes}
		    %c {lappend script $curr_code}
		    %D {lappend script $data}
		    %d {lappend script $descriptions}
		    %m {lappend script $mods}
		    %T {lappend script $type}
		    %t {lappend script $source_types}
		    %W {lappend script $win}
		    %X {lappend script $X}
		    %x {lappend script $x}
		    %Y {lappend script $Y}
		    %y {lappend script $y}
		    %I {lappend script $_id}
		    default {lappend script $element}
		}
	    }
	    if {[llength $script]} {uplevel 1 $script}
	    set CanvasDeliverEventStatus(item) $id
	}

	set script {}
	foreach element $binding {
	    switch $element {
		%% {lappend script %}       
		%A {lappend script $action}
		%a {lappend script $actions}
		%b {lappend script $button}
		%C {lappend script $source_codes}
		%c {lappend script $curr_code}
		%D {lappend script $data}
		%d {lappend script $descriptions}
		%m {lappend script $mods}
		%T {lappend script $type}
		%t {lappend script $source_types}
		%W {lappend script $win}
		%X {lappend script $X}
		%x {lappend script $x}
		%Y {lappend script $Y}
		%y {lappend script $y}
		%I {lappend script $id}
		default {lappend script $element}
	    }
	}
	if {[llength $script]} {
	    return [uplevel 1 $script]
	}
	set CanvasDeliverEventStatus(item) {}
	update
	if {[string equal $event <<Drag>>]} {
	    return -code break
	}
	return $action
    }

    # ChooseAskAction --
    #   This procedure displays a dialog with the help of which the user can
    #   select one of the supported actions...
    proc ChooseAskAction {window x y actions descriptions args} {
	variable AskSelectedAction
	set title {Please Select Action:}
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} {
		set title $descr
		break
	    }
	}

	set menu $window.__tk_dnd[pwd]__action_ask__Drop_window_[pid]
	catch {destroy $menu}
	menu $menu -title $title -tearoff 0 -disabledforeground darkgreen
	$menu add command -font {helvetica 12 bold} \
		-label $title -command "destroy $menu" -state disabled
	$menu add separator

	set items 0
	foreach action $actions descr $descriptions {
	    if {[string equal $action ask]} continue
	    $menu add command -label $descr -command \
		    "set ::dnd::AskSelectedAction $action; destroy $menu"
	    incr items
	}
	if {!$items} {
	    # The drag source accepts the ask action, but has no defined
	    # action list? Add copy action at least...
	    $menu add command -label Copy -command \
		    "set ::dnd::AskSelectedAction copy; destroy $menu"
	}
	
	$menu add separator
	$menu add command -label {Cancel Drop} -command \
		"set ::dnd::AskSelectedAction none; destroy $menu"

	set AskSelectedAction none
	tk_popup $menu $x $y
	update
	bind $menu <Unmap> {after idle {catch {destroy %W}}}
	tkwait window $menu
	
	return $AskSelectedAction
    }
};# namespace eval ::dnd

# EOF
Added Binaries/Windows/twapi/LICENSE.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Copyright (c) 2003-2007, Ashok P. Nadkarni
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.  

- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

- The name of the copyright holder and any other contributors may not
be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Added Binaries/Windows/twapi/clipboard.tcl.






























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#
# Copyright (c) 2004, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

# Clipboard related commands

namespace eval twapi {
}

#
# Open the clipboard
proc twapi::open_clipboard {} {
    OpenClipboard
}

#
# Close the clipboard
proc twapi::close_clipboard {} {
    catch {CloseClipboard}
    return
}

#
# Empty the clipboard
proc twapi::empty_clipboard {} {
    EmptyClipboard
}

#
# Read data from the clipboard
proc twapi::read_clipboard {fmt} {
    # Always catch errors and close clipboard before passing exception on
    # Also ensure memory unlocked
    try {
        set h [GetClipboardData $fmt]
        set p [GlobalLock $h]
        set data [Twapi_ReadMemoryBinary $p 0 [GlobalSize $h]]
    } onerror {} {
        catch {close_clipboard}
        error $errorResult $errorInfo $errorCode
    } finally {
        # If p exists, then we must have locked the handle
        if {[info exists p]} {
            GlobalUnlock $h
        }
    }
    return $data
}


#
# Read text data from the clipboard
proc twapi::read_clipboard_text {args} {
    array set opts [parseargs args {
        {raw.bool 0}
    }]

    try {
        set h [GetClipboardData 13];    # 13 -> Unicode
        set p [GlobalLock $h]
        # Read data discarding terminating null
        set data [string range [Twapi_ReadMemoryUnicode $p 0 [GlobalSize $h]] 0 end-1]
        if {! $opts(raw)} {
            set data [string map {"\r\n" "\n"} $data]
        }
    } onerror {} {
        catch {close_clipboard}
        error $errorResult $errorInfo $errorCode
    } finally {
        if {[info exists p]} {
            GlobalUnlock $h
        }
    }

    return $data
}


#
# Write data to the clipboard
proc twapi::write_clipboard {fmt data} {
    # Always catch errors and close
    # clipboard before passing exception on
    try {
        # For byte arrays, string length does return correct size
        # (DO NOT USE string bytelength - see Tcl docs!)
        set len [string length $data]

        # Allocate global memory 
        set mem_h [GlobalAlloc 2 $len]
        set mem_p [GlobalLock $mem_h]

        Twapi_WriteMemoryBinary $mem_p 0 $len $data

        # The rest of this code just to ensure we do not free
        # memory beyond this point irrespective of error/success
        set h $mem_h
        unset mem_p mem_h
        GlobalUnlock $h
        SetClipboardData $fmt $h
    } onerror {} {
        catch {close_clipboard}
        error $errorResult $errorInfo $errorCode
    } finally {
        if {[info exists mem_p]} {
            GlobalUnlock $mem_h
        }
        if {[info exists mem_h]} {
            GlobalFree $mem_h
        }
    }
    return
}


#
# Write text to the clipboard
proc twapi::write_clipboard_text {data} {
    # Always catch errors and close
    # clipboard before passing exception on
    try {
        set mem_size [expr {2*(1+[string length $data])}]
        
        # Allocate global memory 
        set mem_h [GlobalAlloc 2 $mem_size]
        set mem_p [GlobalLock $mem_h]

        Twapi_WriteMemoryUnicode $mem_p 0 $mem_size $data

        # The rest of this code just to ensure we do not free
        # memory beyond this point irrespective of error/success
        set h $mem_h
        unset mem_h mem_p
        GlobalUnlock $h
        SetClipboardData 13 $h;         # 13 -> Unicode format
    } onerror {} {
        catch {close_clipboard}
        error $errorResult $errorInfo $errorCode
    } finally {
        if {[info exists mem_p]} {
            GlobalUnlock $mem_h
        }
        if {[info exists mem_h]} {
            GlobalFree $mem_h
        }
    }
    return
}

#
# Get current clipboard formats
proc twapi::get_clipboard_formats {} {
    return [Twapi_EnumClipboardFormats]
}

#
# Get registered clipboard format name. Clipboard does not have to be open
proc twapi::get_registered_clipboard_format_name {fmt} {
    return [GetClipboardFormatName $fmt]
}

#
# Register a clipboard format
proc twapi::register_clipboard_format {fmt_name} {
    RegisterClipboardFormat $fmt_name
}

#
# Returns 1/0 depending on whether a format is on the clipboard. Clipboard
# does not have to be open
proc twapi::clipboard_format_available {fmt} {
    return [IsClipboardFormatAvailable $fmt]
}
Added Binaries/Windows/twapi/com.tcl.










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
#
# Copyright (c) 2006 Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

# TBD - object identity comparison 
#   - see http://blogs.msdn.com/ericlippert/archive/2005/04/26/412199.aspx

namespace eval twapi {
    # Maps TYPEKIND data values to symbols
    array set _typekind_map {
        0 enum
        1 record
        2 module
        3 interface
        4 dispatch
        5 coclass
        6 alias
        7 union
    }

    # Cache of Interface names - IID mappings
    array set _iid_to_name_cache {
    }
    array set _name_to_iid_cache {
        idispatch {{00020400-0000-0000-C000-000000000046}}
        iunknown  {{00000000-0000-0000-C000-000000000046}}
        ipersist  {{0000010c-0000-0000-C000-000000000046}}
        ipersistfile {{0000010b-0000-0000-C000-000000000046}}
        itasktrigger {{148BD52B-A2AB-11CE-B11F-00AA00530503}}
        ischeduleworkitem {{a6b952f0-a4b1-11d0-997d-00aa006887ec}}
        itask {{148BD524-A2AB-11CE-B11F-00AA00530503}}
        ienumworkitems {{148BD528-A2AB-11CE-B11F-00AA00530503}}
        itaskscheduler {{148BD527-A2AB-11CE-B11F-00AA00530503}}
        iprovidetaskpage {{4086658a-cbbb-11cf-b604-00c04fd8d565}}
    }

    # Prototype definitions in the format generated by
    # idispatch_fill_prototypes
    array set idispatch_prototypes {}

    # Mapping table from COM instances to related data. We
    # need this level of indirection because multiple object creation
    # can return the same interface pointer if the referenced resource
    # is the same. We need to treat these as separate objects from
    # the application's point of view.
    # Indexed by ($comobj,field) where field may be
    #  ifc  - corresponding idispatch interface
    #  sinks,SINKID - event sinks with id SINKID bound to this object
    #  connpts,SINKID - connection points with id SINKID bound to this object
    array set com_instance_data {}

    # Counter of COM instances - used for name generation
    variable com_instance_counter 0

    # Controls debug checks
    variable com_debug 1
}

# Get the CLSID for a ProgID
proc twapi::progid_to_clsid {progid} {
    return [CLSIDFromProgID $progid]
}

# Get the ProgID for a CLSID
proc twapi::clsid_to_progid {progid} {
    return [ProgIDFromCLSID $progid]
}

# Increment ref count for an interface
proc twapi::iunknown_release {ifc} {
    if {$::twapi::com_debug} {
        # Check if we are releaseing once too often
        # We may even crash if the memory has been reclaimed already
        set refs [IUnknown_AddRef $ifc]
        if {$refs >= 2} {
            # Fine. Undo our addref
            IUnknown_Release $ifc
        } else {
            error "Internal error: attempt to release interface that's already released"
            # TBD - should really exit
            # Fall thru to undo a single addref (our addref)
        }
    }
    IUnknown_Release $ifc
}

# Release an interface
proc twapi::iunknown_addref {ifc} {
    IUnknown_AddRef $ifc
}

# Query interface
proc twapi::iunknown_query_interface {ifc name_or_iid} {
    foreach {iid name} [_resolve_iid $name_or_iid] break
    return [IUnknown_QueryInterface $ifc $iid $name]
}

#
# Get an existing active object interface
proc twapi::get_iunknown_active {clsid} {
    return [GetActiveObject $clsid]
}

#
# Create a new object and get an interface to it
# Generates exception if no such interface
proc twapi::com_create_instance {clsid name_or_iid args} {
    array set opts [parseargs args {
        {model.arg any}
        download.bool
        {disablelog.bool false}
        enableaaa.bool
        {nocustommarshal.bool false}
    } -maxleftover 0]

    # CLSCTX_NO_CUSTOM_MARSHAL ?
    set flags [expr { $opts(nocustommarshal) ? 0x1000 : 0}]

    set model 0
    if {[info exists opts(model)]} {
        foreach m $opts(model) {
            switch -exact -- $m {
                any           {setbits model 23}
                inprocserver  {setbits model 1}
                inprochandler {setbits model 2}
                localserver   {setbits model 4}
                remoteserver  {setbits model 16}
            }
        }
    }

    setbits flags $model

    if {[info exists opts(download)]} {
        if {$opts(download)} {
            setbits flags 0x2000;       # CLSCTX_ENABLE_CODE_DOWNLOAD
        } else {
            setbits flags 0x400;       # CLSCTX_NO_CODE_DOWNLOAD
        }
    }

    if {$opts(disablelog)} {
        setbits flags 0x4000;           # CLSCTX_NO_FAILURE_LOG
    }

    if {[info exists opts(enableaaa)]} {
        if {$opts(enableaaa)} {
            setbits flags 0x10000;       # CLSCTX_ENABLE_AAA
        } else {
            setbits flags 0x8000;       # CLSCTX_DISABLE_AAA
        }
    }

    foreach {iid iid_name} [_resolve_iid $name_or_iid] break

    # In some cases, like Microsoft Office getting an interface other
    # than IUnknown fails fails.
    # We need to get IUnknown, wait for the object to run, and then
    # get the desired interface from IUnknown.
    #  We could check for a specific error code but no guarantee that
    #  the error is same in all versions so we catch and retry on all errors
    if {[catch {set ifc [Twapi_CoCreateInstance $clsid NULL $flags $iid $iid_name]}]} {
        # Try through IUnknown
        set iunk [Twapi_CoCreateInstance $clsid NULL $flags [_iid_iunknown] IUnknown]
        try {
            # Wait for it to run, then get IDispatch from it
            twapi::OleRun $iunk
            set ifc [iunknown_query_interface $iunk $iid]
        } finally {
            iunknown_release $iunk
        }
    }

    return $ifc
}


#
proc twapi::get_iunknown {clsid args} {
    return [eval [list com_create_instance $clsid IUnknown] $args]
}

#
# IDispatch commands


# Get the IDispatch interface for a class
# Generates exception if no such interface
#
proc twapi::get_idispatch {clsid args} {
    return [eval [list com_create_instance $clsid IDispatch] $args]
}

#
# Has type information?
proc twapi::idispatch_has_typeinfo {ifc} {
    return [IDispatch_GetTypeInfoCount $ifc]
}

#
# Returns the type information for a IDispatch interface
proc twapi::idispatch_get_itypeinfo {ifc args} {
    array set opts [parseargs args {
        lcid.int
    } -maxleftover 0 -nulldefault]

    # TBD - what is the second param (0) supposed to be?
    IDispatch_GetTypeInfo $ifc 0 $opts(lcid)
}

#
# Get ids of names
proc twapi::idispatch_names_to_ids {ifc name args} {
    array set opts [parseargs args {
        lcid.int
        paramnames.arg
    } -maxleftover 0 -nulldefault]
    
    
    return [IDispatch_GetIDsOfNames $ifc [concat [list $name] $opts(paramnames)] $opts(lcid)]
}


#
# Invoke an IDispatch function
# prototype should consist of basically params to IDispatch_Invoke - this
# format is happily returned by idispatch_fill_prototypes
proc twapi::idispatch_invoke {ifc prototype args} {
    if {$prototype eq ""} {
        # Treat as a property get DISPID_VALLUE (default value)
        # {dispid=0, riid="" lcid=0 cmd=propget(2) ret type=bstr(8) {} (no params)}
        set prototype {0 {} 0 2 8 {}}
    }
    uplevel 1 [list twapi::IDispatch_Invoke $ifc $prototype] $args
}

#
# Creates an object command for a COM object from a dispatch interface
# need_addref should be false if the object will own the interface
# and true if the caller will be independently using it (and releasing it)
# as well
proc twapi::comobj_idispatch {ifc need_addref {objclsid ""}} {

    if {$need_addref} {
        iunknown_addref $ifc
    }

    set objname ::twapi::com_[incr twapi::com_instance_counter]
    set ::twapi::com_instance_data($objname,ifc) $ifc
    interp alias {} $objname {} ::twapi::_comobj_wrapper $objname $objclsid
    return $objname
}

#
# Create a object command for a COM object
# comid is either a CLSID or a PROGID
proc twapi::comobj {comid args} {
    set clsid [_convert_to_clsid $comid]
    return [comobj_idispatch [eval [list get_idispatch $clsid] $args] false $clsid]
}


#
# Returns the "prototypes" for idispatch methods (non-dispatch methods
# are ignored!
#
# $args is a list of names.
#
# Stores prototypes for each function in array $v_protos. 
# The array elements are indexed as 
# ($ifc,$name,$lcid,$invokeflag)  - contains the full prototype in a form
#     that can be passed to idispatch_invoke. This is a list with the
#     elements {DISPID "" LCID INVOKEFLAGS RETTYPE PARAMTYPES}
# Entries are created for every match, so for example if the name
# was a property, entries would be created for both the set property
# and the get property method ($invokeflag would be different in the
# two cases
#
# Returns number of entries found
proc twapi::idispatch_fill_prototypes {ifc v_protos lcid args} {
    upvar $v_protos protos

    array set protos {};                #  Just to make sure array is created

    # Filter out the names we already have
    set names [list ]
    foreach name $args {
        set count [llength [array names protos $ifc,$name,$lcid*]]
        if {$count} {
            # Already have the prototypes
            return $count
        }
    }

    set ti [idispatch_get_itypeinfo $ifc -lcid $lcid]

    set count 0
    try {
        # In case of dual interfaces, we need the typeinfo for the dispatch
        switch -exact -- [lindex [itypeinfo_get_info $ti -typekind] 1] {
            dispatch {
                # Fine, just what we want
            }
            interface {
                # Get the dispatch interface
                set ti2 [itypeinfo_get_referenced_itypeinfo $ti -1]
                iunknown_release $ti
                set ti $ti2
            }
            default {
                error "Interface is not a dispatch interface"
            }
        }

        set tc [itypeinfo_get_itypecomp $ti]
        
        foreach name $args {
            # Check for existence of method, propget, propput
            foreach invkind {1 2 4} {
                if {![catch {
                    set binddata [ITypeComp_Bind $tc $name $invkind $lcid]
                }]} {
                    if {[llength $binddata] == 0} {
                        continue;       # Not found
                    }
                    foreach {type data ti2} $binddata break
                    iunknown_release $ti2; # Don't need this but must release
                    if {$type ne "funcdesc"} continue
                    array set bindings $data
                    set protos($ifc,$name,$lcid,$bindings(invkind)) [list $bindings(memid) "" $lcid $bindings(invkind) $bindings(elemdescFunc.tdesc) $bindings(lprgelemdescParam)]
                    incr count
                }
            }
        }

    } finally {
        if {[info exists tc]} {
            iunknown_release $tc
        }
        iunknown_release $ti
    }    

    if {$count} {
        return $count
    }

    # No interfaces found. See if we have a IDispatchEx interface that
    # will has dynamic members. Note that these DISPID will work with
    # the original IDispatch as well
    try {
        set dispex [iunknown_query_interface $ifc IDispatchEx]
        if {$dispex ne ""} {
            # flags = 10 - case insensitive, create if required
            set dispid [IDispatchEx_GetDispID $dispex $name 10]
            # No type information is available for dynamic members.
            # Try at least getting the invocation type but even that is not
            # supported by all objects

            # Invoke kind - 1 (method), 2 (propget), 4 (propput)
            set invkinds [list 1 2 4];      # In case call below fails

            # 1+4+10+100
            # We look for the following flags
            #  0x1 - property get
            #  0x4 - property put
            #  0x10 - property putref
            #  0x100 - method call
            if {! [catch {set flags [IDispatchEx_GetMemberProperties $dispex 0x115] }]} {
                set invkinds [list ]
                if {$flags & 0x100} {lappend invkinds 1}
                if {$flags & 0x1} {lappend invkinds 2}
                if {$flags & 0x14} {
                    # TBD - we are marking putref and put the same. Is that OK?
                    lappend invkinds 4
                }
            }

            foreach invkind $invkinds {
                # Note that the last element in prototype is missing indicating
                # we do not have parameter information. Also, we assume return
                # type of 8 (BSTR) (although the actual return type doesn't matter)
                set protos($ifc,$name,$lcid,$invkind) [list $dispid "" $lcid $invkind 8]
                incr count
            }
        }
    } onerror {} {
        # Ignore errors, just means prototypes not filled
    } finally {
        if {[info exists dispex] && $dispex ne ""} {
            iunknown_release $dispex
        }
    }

    return $count
}



#
# Return attributes of a ITypeInfo
proc twapi::itypeinfo_get_info {ifc args} {
    array set opts [parseargs args {
        all
        guid
        lcid
        constructorid
        destructorid
        schema
        instancesize
        typekind
        fncount
        varcount
        interfacecount
        vtblsize
        alignment
        majorversion
        minorversion
        aliasdesc
        flags
        idldesc
        memidmap
    } -maxleftover 0]

    array set data [ITypeInfo_GetTypeAttr $ifc]
    set result [list ]
    foreach {opt key} {
        guid guid
        lcid lcid
        constructorid memidConstructor
        destructorid  memidDestructor
        schema lpstrSchema
        instancesize cbSizeInstance
        fncount cFuncs
        varcount cVars
        interfacecount cImplTypes
        vtblsize cbSizeVft
        alignment cbAlignment
        majorversion wMajorVerNum
        minorversion wMinorVerNum
        aliasdesc tdescAlias
    } {
        if {$opts(all) || $opts($opt)} {
            lappend result -$opt $data($key)
        }
    }

    if {$opts(all) || $opts(typekind)} {
        set typekind $data(typekind)
        if {[info exists ::twapi::_typekind_map($typekind)]} {
            set typekind $::twapi::_typekind_map($typekind)
        }
        lappend result -typekind $typekind
    }

    if {$opts(all) || $opts(flags)} {
        lappend result -flags [_make_symbolic_bitmask $data(wTypeFlags) {
            appobject       1
            cancreate       2
            licensed        4
            predeclid       8
            hidden         16
            control        32
            dual           64
            nonextensible 128
            oleautomation 256
            restricted    512
            aggregatable 1024
            replaceable  2048
            dispatchable 4096
            reversebind  8192
            proxy       16384
        }]
    }

    if {$opts(all) || $opts(idldesc)} {
        lappend result -idldesc [_make_symbolic_bitmask $data(idldescType) {
            in 1
            out 2
            lcid 4
            retval 8
        }]
    }

    if {$opts(all) || $opts(memidmap)} {
        set memidmap [list ]
        for {set i 0} {$i < $data(cFuncs)} {incr i} {
            array set fninfo [itypeinfo_get_func_info $ifc $i -memid -name]
            lappend memidmap $fninfo(-memid) $fninfo(-name)
        }
        lappend result -memidmap $memidmap
    }

    return $result
}

#
# Get the referenced typeinfo of a typeinfo
proc twapi::itypeinfo_get_referenced_itypeinfo {ifc index} {
    set hreftype [ITypeInfo_GetRefTypeOfImplType $ifc $index]
    return [ITypeInfo_GetRefTypeInfo $ifc $hreftype]
}

#
# Get the containing typelib
proc twapi::itypeinfo_get_itypelib {ifc} {
    return [ITypeInfo_GetContainingTypeLib $ifc]
}

#
# Get the typecomp for a typeinfo
proc twapi::itypeinfo_get_itypecomp {ifc} {
    return [ITypeInfo_GetTypeComp $ifc]
}

#
# Get a function definition
proc twapi::itypeinfo_get_name {ifc} {
    return [lindex [itypeinfo_get_doc $ifc -1 -name] 1]
}


#
# Get a variable description associated with a type
proc twapi::itypeinfo_get_var_info {ifc index args} {
    # TBD - add support for retrieving elemdescVar.paramdesc fields

    array set opts [parseargs args {
        all
        name
        memid
        schema
        datatype
        value
        valuetype
        varkind
        flags
    } -maxleftover 0]

    array set data [ITypeInfo_GetVarDesc $ifc $index]
    
    set result [list ]
    foreach {opt key} {
        memid memid
        schema lpstrSchema
        datatype elemdescVar.tdesc
    } {
        if {$opts(all) || $opts($opt)} {
            lappend result -$opt $data($key)
        }
    }

    if {$opts(all) || $opts(value)} {
        if {[info exists data(lpvarValue)]} {
            # Const value
            lappend result -value [lindex $data(lpvarValue) 1]
        } else {
            lappend result -value $data(oInst)
        }
    }

    if {$opts(all) || $opts(valuetype)} {
        if {[info exists data(lpvarValue)]} {
            lappend result -valuetype [lindex $data(lpvarValue) 0]
        } else {
            lappend result -valuetype int
        }
    }

    if {$opts(all) || $opts(varkind)} {
        lappend result -varkind [string map {
            0 perinstance
            1 static
            2 const
            3 dispatch
        } $data(varkind)]
    }

    if {$opts(all) || $opts(flags)} {
        lappend result -flags [_make_symbolic_bitmask $data(wVarFlags) {
            readonly       1
            source       2
            bindable        4
            requestedit       8
            displaybind         16
            defaultbind        32
            hidden           64
            restricted 128
            defaultcollelem 256
            uidefault    512
            nonbrowsable 1024
            replaceable  2048
            immediatebind 4096
        }]
    }
    
    if {$opts(all) || $opts(name)} {
        set result [concat $result [itypeinfo_get_doc $ifc $data(memid) -name]]
    }    

    return $result
}

#
# Get a function definition
proc twapi::itypeinfo_get_func_info {ifc index args} {

    array set opts [parseargs args {
        all
        name
        memid
        funckind
        invkind
        callconv
        params
        flags
        datatype
        resultcodes
        vtbloffset
    } -maxleftover 0]

    array set data [ITypeInfo_GetFuncDesc $ifc $index]

    set result [list ]

    foreach {opt key} {
        memid       memid
        vtbloffset  oVft
        datatype    elemdescFunc.tdesc
        resultcodes lprgscode
    } {
        if {$opts(all) || $opts($opt)} {
            lappend result -$opt $data($key)
        }
    }

    if {$opts(all) || $opts(funckind)} {
        lappend result -funckind [string map {
            0 virtual
            1 purevirtual
            2 nonvirtual
            3 static
            4 dispatch
        } $data(funckind)]
    }

    if {$opts(all) || $opts(invkind)} {
        lappend result -invkind [string map {
            0 func
            1 propget
            2 propput
            3 propputref
        } $data(invkind)]
    }

    if {$opts(all) || $opts(callconv)} {
        lappend result -callconv [string map {
            0 fastcall
            1 cdecl
            2 pascal
            3 macpascal
            4 stdcall
            5 fpfastcall
            6 syscall
            7 mpwcdecl
            8 mpwpascal
        } $data(callconv)]
    }

    if {$opts(all) || $opts(flags)} {
        lappend result -flags [_make_symbolic_bitmask $data(wFuncFlags) {
            restricted   1
            source       2
            bindable     4
            requestedit  8
            displaybind  16
            defaultbind  32
            hidden       64
            usesgetlasterror  128
            defaultcollelem 256
            uidefault    512
            nonbrowsable 1024
            replaceable  2048
            immediatebind 4096
        }]
    }

    if {$opts(all) || $opts(params)} {
        set params [list ]
        foreach param $data(lprgelemdescParam) {
            foreach {paramtype paramdesc} $param break
            set paramflags [_make_symbolic_bitmask [lindex $paramdesc 0] {
                in 1
                out 2
                lcid 4
                retval 8
                optional 16
                hasdefault 32
                hascustom  64
            }]
            if {[llength $paramdesc] > 1} {
                # There is a default value associated with the parameter
                lappend params [list $paramtype $paramflags [lindex $paramdesc 1]]
            } else {
                lappend params [list $paramtype $paramflags]
            }
        }
        lappend result -params $params
    }

    if {$opts(all) || $opts(name)} {
        set result [concat $result [itypeinfo_get_doc $ifc $data(memid) -name]]
    }    

    return $result
}

#
# Get documentation for a element of a type
proc twapi::itypeinfo_get_doc {ifc memid args} {
    array set opts [parseargs args {
        all
        name
        docstring
        helpctx
        helpfile
    } -maxleftover 0]

    foreach {name docstring helpctx helpfile} [ITypeInfo_GetDocumentation $ifc $memid] break

    set result [list ]
    foreach opt {name docstring helpctx helpfile} {
        if {$opts(all) || $opts($opt)} {
            lappend result -$opt [set $opt]
        }
    }
    return $result
}

#
# Get ids of names
proc twapi::itypeinfo_names_to_ids {ifc name args} {
    array set opts [parseargs args {
        paramnames.arg
    } -maxleftover 0 -nulldefault]

    return [ITypeInfo_GetIDsOfNames $ifc [concat [list $name] $opts(paramnames)]]
}


#
# Get type information
proc twapi::itypeinfo_get_impl_type_flags {ifc index} {
    return [_make_symbolic_bitmask \
                [ITypeInfo_GetImplTypeFlags $ifc $index] \
                {
                    default      1
                    source       2
                    restricted   4
                    defaultvtable 8
                }]    
}

#
# Get names in a typeinfo
proc twapi::itypeinfo_get_names {ifc memid} {
    return [ITypeInfo_GetNames $ifc $memid]
}


#
# ITypeLib commands
#

# Return an interface to a typelib
proc twapi::get_itypelib {path args} {
    array set opts [parseargs args {
        {registration.arg none {none register default}}
    } -maxleftover 0]

    return [LoadTypeLibEx $path [string map {default 0 register 1 none 2} $opts(registration)]]
}

#
# Return an interface to a typelib from the registry
proc twapi::get_registered_itypelib {uuid major minor args} {
    array set opts [parseargs args {
        lcid.int
    } -maxleftover 0 -nulldefault]
    
    return [LoadRegTypeLib $uuid $major $minor $opts(lcid)]
}

#
# Register a typelib
proc twapi::itypelib_register {ifc path helppath args} {
    RegisterTypeLib $ifc $path $helppath
}

#
# Unregister a typelib
proc twapi::itypelib_unregister {uuid major minor args} {
    array set opts [parseargs args {
        lcid.int
    } -maxleftover 0 -nulldefault]

    UnRegisterTypeLib $uuid $major $minor $opts(lcid) 1
}



#
# Return count of entries in a typelib
proc twapi::itypelib_count {ifc} {
    return [ITypeLib_GetTypeInfoCount $ifc]
}

#
# Returns the type of a type description
proc twapi::itypelib_get_entry_typekind {ifc id} {
    set typekind [ITypeLib_GetTypeInfoType $ifc $id]
    if {[info exists ::twapi::_typekind_map($typekind)]} {
        set typekind $::twapi::_typekind_map($typekind)
    }
}

#
# Get documentation for a element of a typelib
proc twapi::itypelib_get_entry_doc {ifc id args} {
    array set opts [parseargs args {
        all
        name
        docstring
        helpctx
        helpfile
    } -maxleftover 0]

    foreach {name docstring helpctx helpfile} [ITypeLib_GetDocumentation $ifc $id] break

    set result [list ]
    foreach opt {name docstring helpctx helpfile} {
        if {$opts(all) || $opts($opt)} {
            lappend result -$opt [set $opt]
        }
    }
    return $result
}

#
# Returns the ITypeInfo interface for a typelib entry
interp alias {} twapi::itypelib_get_entry_itypeinfo {} twapi::ITypeLib_GetTypeInfo


#
# Returns the ITypeInfo interface for a typelib guid
interp alias {} twapi::itypelib_get_registered_itypeinfo {} ITypeLib_GetTypeInfoOfGuid


#
# Returns the path to the typelib based on a guid
proc twapi::itypelib_get_registered_path {guid major minor args} {
    array set opts [parseargs args {
        lcid.int
    } -maxleftover 0 -nulldefault]


    set path [QueryPathOfRegTypeLib $guid $major $minor $opts(lcid)]
    # At least some versions have a bug in that there is an extra \0
    # at the end.
    if {[string equal [string index $path end] \0]} {
        set path [string range $path 0 end-1]
    }
    return $path
}

#
# Get attributes of a library
proc twapi::itypelib_get_info {ifc args} {
    array set opts [parseargs args {
        all
        guid
        lcid
        syskind
        majorversion
        minorversion
        flags
    } -maxleftover 0]

    array set data [ITypeLib_GetLibAttr $ifc]
    set result [list ]
    foreach {opt key} {
        guid guid
        lcid lcid
        majorversion wMajorVerNum
        minorversion wMinorVerNum
    } {
        if {$opts(all) || $opts($opt)} {
            lappend result -$opt $data($key)
        }
    }

    if {$opts(all) || $opts(flags)} {
        lappend result -flags [_make_symbolic_bitmask $data(wLibFlags) {
            restricted      1
            control         2
            hidden          4
            hasdiskimage    8
        }]
    }

    if {$opts(all) || $opts(syskind)} {
        lappend result -syskind [string map {
            0 win16
            1 win32
            2 mac
        } $data(syskind)]
    }

    return $result
}

#
# Iterate through a typelib. Caller is responsible for each itypeinfo
# passed
proc twapi::itypelib_foreach {args} {

    array set opts [parseargs args {
        type.arg
        name.arg
        guid.arg
    } -maxleftover 3]

    if {[llength $args] != 3} {
        error "Syntax error: Should be 'itypelib_foreach ?options? VARNAME ITYPELIB SCRIPT'"
    }

    foreach {varname tl script} $args break

    set count [itypelib_count $tl]

    for {set i 0} {$i < $count} {incr i} {
        if {[info exists opts(type)] &&
            $opts(type) ne [itypelib_get_entry_typekind $tl $i]} {
            continue;                   # Type does not match
        }
        if {[info exists opts(name)] &&
            [string compare -nocase $opts(name) [lindex [itypelib_get_entry_doc $tl $i -name] 1]]} {
            continue;                   # Name does not match
        }
        upvar $varname ti
        set ti [itypelib_get_entry_itypeinfo $tl $i]
        if {[info exists opts(guid)]} {
            if {[string compare -nocase [lindex [itypeinfo_get_info $ti -guid] 1] $opts(guid)]} {
                continue
            }
        }
        set ret [catch {uplevel $script} msg]
        switch -exact -- $ret {
            1 {
                error $msg $::errorInfo $::errorCode
            }
            2 {
                return; # TCL_RETURN
            }
            3 {
                set i $count; # TCL_BREAK
            }
        }
    }
    return
}





#
# Map interface name to IID
proc twapi::name_to_iid {iname} {

    set iname [string tolower $iname]

    if {[info exists ::twapi::_name_to_iid_cache($iname)]} {
        return $::twapi::_name_to_iid_cache($iname)
    }

    # Look up the registry
    foreach iid [registry keys HKEY_CLASSES_ROOT\\Interface] {
        if {![catch {
            set val [registry get HKEY_CLASSES_ROOT\\Interface\\$iid ""]
        }]} {
            if {[string equal -nocase $iname $val]} {
                return [set ::twapi::_name_to_iid_cache($iname) $iid]
            }
        }
    }
    return [set ::twapi::_name_to_iid_cache($iname) ""]
}


#
# Map interface IID to name
proc twapi::iid_to_name {iid} {
    set iname ""
    catch {set iname [registry get HKEY_CLASSES_ROOT\\Interface\\$iid ""]}
    return $iname
}

#
# Given a collection, iterates over it and returns a list consisting of
# {name value} pairs. Assumes the collection is a list of COM objects
# which have properties Name and value
# obj is a COM object as returned by comobj command
proc twapi::com_named_property_list {obj} {
    set result [list ]
    $obj -iterate itemobj {
        lappend result [$itemobj Name] [$itemobj]
        $itemobj -destroy
    }
    return $result
}


#
# Get the typeinfo for the default source interface of a coclass
# $coti is the typeinfo of the coclass
proc twapi::get_coclass_default_source_itypeinfo {coti} {
    set count [lindex [itypeinfo_get_info $coti -interfacecount] 1]
    for {set i 0} {$i < $count} {incr i} {
        set flags [ITypeInfo_GetImplTypeFlags $coti $i]
        # default 0x1, source 0x2
        if {($flags & 3) == 3} {
            return [itypeinfo_get_referenced_itypeinfo $coti $i]
        }
    }
    return ""
}

#
# Convert a variant time to a time list
proc twapi::variant_time_to_timelist {double} {
    return [VariantTimeToSystemTime $double]
}

#
# Convert a time list time to a variant time
proc twapi::timelist_to_variant_time {timelist} {
    return [SystemTimeToVariantTime $timelist]
}


################################################################

#
# Test code
proc twapi::_print_typelib {path args} {
    array set opts [parseargs args {
        type.arg
        name.arg
    } -maxleftover 0]

    
    set ifc [get_itypelib $path -registration none]
    set count [itypelib_count $ifc]

    for {set i 0} {$i < $count} {incr i} {
        set type [itypelib_get_entry_typekind $ifc $i]
        if {[info exists opts(type)] && $opts(type) ne $type} continue
        array set tlinfo [itypelib_get_entry_doc $ifc $i -all]
        if {[info exists opts(name)] && [string compare -nocase $opts(name) $tlinfo(-name)]} continue
        set desc [list "$i:\t$type\t$tlinfo(-name) - $tlinfo(-docstring)"]
        set ti [twapi::itypelib_get_entry_itypeinfo $ifc $i]
        array set attrs [itypeinfo_get_info $ti -all]
        switch -exact -- $type {
            record -
            union  -
            enum {
                for {set j 0} {$j < $attrs(-varcount)} {incr j} {
                    array set vardata [itypeinfo_get_var_info $ti $j -all]
                    set vardesc "\t\t$vardata(-varkind) $vardata(-datatype) $vardata(-name)"
                    if {$type eq "enum"} {
                        append vardesc " = $vardata(-value)"
                    } else {
                        append vardesc " (offset $vardata(-value))"
                    }
                    lappend desc $vardesc
                }
            }
            alias {
                lappend desc "\t\ttypedef $attrs(-aliasdesc)"
            }
            dispatch -
            interface {
                for {set j 0} {$j < $attrs(-fncount)} {incr j} {
                    array set funcdata [itypeinfo_get_func_info $ti $j -all] 
                    if {$funcdata(-funckind) eq "dispatch"} {
                        set funckind "(dispid $funcdata(-memid))"
                    } else {
                        set funckind "(vtable $funcdata(-vtbloffset))"
                    }
                    lappend desc "\t\t$funckind [_resolve_com_type $ti $funcdata(-datatype)] $funcdata(-name) [_resolve_com_params $ti $funcdata(-params)]"
                }
            }
            coclass {
                for {set j 0} {$j < $attrs(-interfacecount)} {incr j} {
                    set ti2 [itypeinfo_get_referenced_itypeinfo $ti $j]
                    set idesc "\t\t[itypeinfo_get_name $ti2]"
                    set iflags [itypeinfo_get_impl_type_flags $ti $j]
                    if {[llength $iflags]} {
                        append idesc " ([join $iflags ,])"
                    }
                    lappend desc $idesc
                    iunknown_release $ti2
                }
            }
        }
        puts [join $desc \n]
        iunknown_release $ti
    }

    iunknown_release $ifc
    return
}


#
# Print methods in an interface
proc twapi::_print_interface {ifc} {
    set ti [idispatch_get_itypeinfo $ifc]
    twapi::_print_interface_helper $ti
    iunknown_release $ti
}

proc twapi::_print_interface_helper {ti {names_already_done ""}} {
    set name [itypeinfo_get_name $ti]
    if {[lsearch -exact $names_already_done $name] >= 0} {
        # Already printed this
        return $names_already_done
    }
    lappend names_already_done $name
    array set attrs [itypeinfo_get_info $ti -all]
    for {set j 0} {$j < $attrs(-fncount)} {incr j} {
        array set funcdata [itypeinfo_get_func_info $ti $j -all] 
        if {$funcdata(-funckind) eq "dispatch"} {
            set funckind "(dispid $funcdata(-memid))"
        } else {
            set funckind "(vtable $funcdata(-vtbloffset))"
        }
        lappend desc "\t$funckind [_resolve_com_type $ti $funcdata(-datatype)] $funcdata(-name) [_resolve_com_params $ti $funcdata(-params)]"
    }

    puts $name
    puts [join $desc \n]

    # Now get any referenced typeinfos and print them
    for {set j 0} {$j < $attrs(-interfacecount)} {incr j} {
        set ti2 [itypeinfo_get_referenced_itypeinfo $ti $j]
        set names_already_done [_print_interface_helper $ti2 $names_already_done]
        iunknown_release $ti2
    }
    return $names_already_done
}



#
# Resolves references to parameter definition
proc twapi::_resolve_com_params {ti params} {
    set result [list ]
    foreach param $params {
        lappend result [lreplace $param 0 0 [_resolve_com_type $ti [lindex $param 0]]]
    }
    return $result
}

#
# Resolves typedefs
proc twapi::_resolve_com_type {ti typedesc} {
    switch -exact -- [lindex $typedesc 0] {
        ptr {
            # Recurse to resolve any inner types
            set typedesc [list ptr [_resolve_com_type $ti [lindex $typedesc 1]]]
        }
        userdefined {
            set hreftype [lindex $typedesc 1]
            set ti2 [ITypeInfo_GetRefTypeInfo $ti $hreftype]
            set typedesc [list userdefined [itypeinfo_get_name $ti2]]
            iunknown_release $ti2
        }
        default {
        }
    }

    return $typedesc
}

#
# Returns a string value from a formatted variant value pair {VT_xxx value}
# $addref controls whether we do an AddRef when the value is a pointer to
# an interface. $raw controls whether interfaces are converted to comobjs
# or not.
proc twapi::_convert_from_variant {variant addref {raw false}} {
    # TBD - format appropriately depending on variant type for dates and
    # currency
    if {[llength $variant] == 0} {
        return ""
    }
    set vt [lindex $variant 0]

    if {$vt & 0x2000} {
        # VT_ARRAY
        if {[llength $variant] < 3} {
            return [list ]
        }
        set vt [expr {$vt & ~ 0x2000}]
        if {$vt == 12} {
            # Array of variants. Recursively convert values
            set result [list ]
            foreach elem [lindex $variant 2] {
                lappend result [_convert_from_variant $elem $addref $raw]
            }
            return $result
        } else {
            return [lindex $variant 2]
        }
    } else {
        if {$vt == 9} {
            # IDispatch - return as comobj
            set idisp [lindex $variant 1]
            if {$raw} {
                if {$addref} {
                    iunknown_addref $idisp
                }
                return $idisp
            } else {
                return [comobj_idispatch $idisp $addref]
            }
        } elseif {$vt == 13} {
            # IUnknown - try converting to IDispatch
            set iunk [lindex $variant 1]
            if {$raw} {
                if {$addref} {
                    iunknown_addref $iunk
                }
                return $iunk
            } else {
                # Try to return as idispatch
                set idisp [iunknown_query_interface $iunk IDispatch]
                if {$idisp eq ""} {
                    # No IDispatch - return as is
                    if {$addref} {
                        iunknown_addref $iunk
                    }
                    return $iunk
                } else {
                    # If caller did not need us to do an addref, implies
                    # it would already have done it, and app code is expected
                    # to release. However, what we pass the appcode is
                    # a converted idispatch. So we have to do the release
                    # on the original interface ourselves.
                    if {! $addref} {
                        iunknown_release $iunk
                    }
                    return [comobj_idispatch $idisp false]
                }
            }
        }
    }
    return [lindex $variant 1]
}


#
# Wrapper used by comobj
proc twapi::_comobj_wrapper {comobj clsid args} {

    # Look for the interface object corresponding to this object
    if {![info exists ::twapi::com_instance_data($comobj,ifc)]} {
        error "Missing COM interface"
    }
    set ifc $::twapi::com_instance_data($comobj,ifc)

    set nargs [llength $args]
    # parse to figure out what the command is
    switch -exact -- [lindex $args 0] {
        -get {
            if {$nargs < 2} {
                error "Insufficient number of arguments supplied for method call"
            }
            set name [lindex $args 1]
            set params [lrange $args 2 end]
            set flags  2;           # Property get
        }
        -set {
            if {$nargs < 3} {
                error "Insufficient number of arguments supplied for method call"
            }
            set name [lindex $args 1]
            set params [lrange $args 2 end]
            set flags  4;           # Property set
        }
        -call {
            if {$nargs < 2} {
                error "Insufficient number of arguments supplied for method call"
            }
            set name [lindex $args 1]
            set params [lrange $args 2 end]
            set flags  1;           # Method call
        }
        -destroy {
            # Release sinks, connection points
            foreach sink_item [array names ::twapi::com_instance_data "$comobj,sink,*"] {
                set sinkid [lindex [split $sink_item ,] 2]
                $comobj -unbind $sinkid
            }

            # Get rid of dispatch prototypes. This is important for two
            # reasons. A different idispatch allocated later for a different
            # interface may have the same pointer value but will have
            # totally different prototypes. Even if it is the same
            # object and interface type, in the case of dynamic properties
            # we need to call IDispatchEx::GetDispIDs for the dynamic
            # properties to show up for the new object.
            array unset twapi::idispatch_prototypes ${ifc}*
            twapi::iunknown_release $ifc
            rename $comobj ""
            return
        }
        -precache {
            # TBD - prepopulate with method or property names
            return;                 # Currently a no-op
        }
        "" {
            return [_convert_from_variant [twapi::idispatch_invoke $ifc ""] false]
        }
        -print {
            _print_interface $ifc
            return
        }
        -interface {
            return $ifc
        }
        -queryinterface {
            return [iunknown_query_interface $ifc [lindex $args 1]]
        }
        -with {
            # $obj -with SUBOBJECTPATHLIST arguments
            # where SUBOBJECTPATHLIST is list each element of which is
            # either a property or a method of the previous element in
            # the list. The element may itself be a list in which case
            # the first element is the property/method and remaining
            # are passed to it
            #
            # Note that 'arguments' may themselves be comobj subcommands!
            set subobjlist [lindex $args 1]
            set next $comobj
            set releaselist [list ]

            try {
                while {[llength $subobjlist]} {
                    set nextargs [lindex $subobjlist 0]
                    set subobjlist [lrange $subobjlist 1 end]
                    set next [uplevel [list $next] $nextargs]
                    lappend releaselist $next
                }
                # We use uplevel here because again we want to run in caller
                # context 
                return [uplevel [list $next] [lrange $args 2 end]]
            } finally {
                foreach next $releaselist {
                    $next -destroy
                }
            }
        }
        -iterate {
            # $obj -iterate VARNAME arguments
            if {[llength $args] < 3} {
                error "Insufficient arguments. Syntax '$comobj -iterate VARNAME CODEBLOCK'"
            }
            upvar [lindex $args 1] var
            # First get IEnumVariant iterator using the _NewEnum method
            set enum_disp [$comobj -get _NewEnum]
            # This gives us an IUnknown.
            try {
                # Convert the IUnknown to IEnumVARIANT
                set iter [iunknown_query_interface $enum_disp IEnumVARIANT]
                if {$iter ne ""} {
                    while {1} {
                        # Get the next item from iterator
                        set next [IEnumVARIANT_Next $iter 1]
                        foreach {more values} $next break
                        if {[llength $values]} {
                            # TBD - does var have to be released?
                            set var [_convert_from_variant [lindex $values 0] false]
                            set ret [catch {uplevel [lindex $args 2]} msg]
                            switch -exact -- $ret {
                                1 {
                                    error $msg $::errorInfo $::errorCode
                                }
                                2 {
                                    return; # TCL_RETURN
                                }
                                3 {
                                    set more 0; # TCL_BREAK
                                }
                            }
                        }
                        if {! $more} break
                    }
                }
            } finally {
                iunknown_release $enum_disp
                if {[info exists iter] && $iter ne ""} {
                    iunknown_release $iter
                }
            }
            return
        }
        -bind {
            # $comobj -bind callbackscript
            if {[llength $args] != 2} {
                error "Syntax error: should be '$comobj -bind SCRIPT"
            }

            # We need the typeinfo for the coclass. We get this one of
            # two ways - 
            # If the object supports IProvideClassInfo, we use it. Else
            # we try the following:
            #   - from the idispatch, we get its typeinfo
            #   - from the typeinfo, we get the containing typelib
            #   - then we search the typelib for the coclass clsid
            # Once we have the coclass we can locate the source interface
            # within it and retrieve disp id mappings
            try {
                set pci [iunknown_query_interface $ifc IProvideClassInfo]
                if {$pci ne ""} {
                    # Great, get the coclass from it
                    catch {set coti [IProvideClassInfo_GetClassInfo $pci]}
                }

                if {![info exists coti]} {
                    # Couldn't get the coclass above, try the second way
                    if {$clsid eq ""} {
                        error "Do not have class information for binding"
                    }

                    set ti [idispatch_get_itypeinfo $ifc]
                    set tl [lindex [itypeinfo_get_itypelib $ti] 0]
                    itypelib_foreach -guid $clsid -type coclass coti $tl {
                        break
                    }
                }
                if {![info exists coti]} {
                    error "Could not find coclass for binding"
                }
                # $coti is the coclass information. Get dispids for the default
                # source interface for events and its guid
                set srcti [get_coclass_default_source_itypeinfo $coti]
                array set srcinfo [itypeinfo_get_info $srcti -memidmap -guid]

                # Now we need to get the actual connection point itself
                set container [iunknown_query_interface $ifc IConnectionPointContainer]
                if {$container eq ""} {
                    error "Object does not have any event source interfaces"
                }
                set connpt [IConnectionPointContainer_FindConnectionPoint $container $srcinfo(-guid)]
                if {$connpt eq ""} {
                    error "Object has no matching event source"
                }

                # Finally, create our sink object
                # TBD - need to make sure comobj is not deleted or
                # should the callback itself check?
                set sink [ComEventSink $srcinfo(-guid) [list ::twapi::_eventsink_callback $comobj $srcinfo(-memidmap) [lindex $args 1]]]

                # OK, we finally have everything we need. Tell the event source
                set sinkid [IConnectionPoint_Advise $connpt $sink]
                set ::twapi::com_instance_data($comobj,sink,$sinkid) $sink
                set ::twapi::com_instance_data($comobj,connpt,$sinkid) $connpt
                return $sinkid
            } onerror {} {
                # These are released only on error as otherwise they have
                # to be kept until unbind time
                foreach x {connpt sink} {
                    if {[info exists $x] && [set $x] ne ""} {
                        iunknown_release [set $x]
                    }
                }
                error $errorResult $errorInfo $errorCode
            } finally {
                # In all cases, release any interfaces we created
                # Note connpt and sink are released at unbind time except
                # on error
                foreach x {ti tl coti srcti container pci} {
                    if {[info exists $x] && [set $x] ne ""} {
                        iunknown_release [set $x]
                    }
                }
            }
        }
        -unbind {
            # $obj -unbind SINKID
            if {[llength $args] != 2} {
                error "Syntax error: Should be '$comobj -unbind BINDID'"
            }
            set sinkid [lindex $args 1]
            if {[info exists ::twapi::com_instance_data($comobj,connpt,$sinkid)]} {
                IConnectionPoint_Unadvise $::twapi::com_instance_data($comobj,connpt,$sinkid) $sinkid
                unset ::twapi::com_instance_data($comobj,connpt,$sinkid)
            }
            if {[info exists ::twapi::com_instance_data($comobj,sink,$sinkid)]} {
                iunknown_release $::twapi::com_instance_data($comobj,sink,$sinkid)
                unset ::twapi::com_instance_data($comobj,sink,$sinkid)
            }
            return
        }
        default {
            # Try to figure out whether it is a name or method
            set name [lindex $args 0]
            set params [lrange $args 1 end]
            twapi::idispatch_fill_prototypes $ifc ::twapi::idispatch_prototypes 0 $name
            # We have to figure out if it is a property get, property put
            # or a method. We will check in that order. If multiple matches
            # we check if number of parameters matches that in prototype

            set flags 0
            if {[info exists ::twapi::idispatch_prototypes($ifc,$name,0,2)]} {
                # Property get
                set flags [expr {$flags | 2}]
            }
            if {[info exists ::twapi::idispatch_prototypes($ifc,$name,0,4)]} {
                # Property set
                set flags [expr {$flags | 4}]
            }
            if {[info exists ::twapi::idispatch_prototypes($ifc,$name,0,1)]} {
                # Property set
                set flags [expr {$flags | 1}]
            }
            # If only one of the bits is set, then that's what we go with
            # else we have to use a priority scheme
            if {$flags != 0 && $flags != 1 && $flags != 2 && $flags != 4} {
                # More than 1 possibility
                # Check for match on exact number of parameters
                set nparams [llength $params]
                foreach flag {1 2 4} {
                    if {$flags & $flag} {
                        set proto $::twapi::idispatch_prototypes($ifc,$name,0,$flag)
                        # See if we do have parameter info in prototype
                        if {[llength $proto] > 5} {
                            # Yes we do. see if number matches supplied args
                            if {$nparams == [llength [lindex $proto 5]]} {
                                # Matched
                                set matched_flags $flag
                                break
                            }
                        }
                    }
                }
                if {![info exists matched_flags]} {
                    # Still ambiguity. Use following heruristic. 
                    # If possible get, and no args supplied, assume get
                    # If possible put, and one arg supplied, assume put
                    # Else method if set
                    # TBD - maybe we should use return type to distinguish
                    # between put and get? But not sure that's always
                    # supplied in prototype
                    if {($flags & 2) && $nparams == 0} {
                        set matched_flags 2
                    } elseif {($flags & 4) && $nparams == 1} {
                        set matched_flags 4
                    } elseif {$flags & 1} {
                        set matched_flags 1
                    }
                }
                if {[info exists matched_flags]} {
                    set flags $matched_flags
                } else {
                    set flags 0
                }
            }
            if {$flags == 0} {
                # Could not figure out, assume method
                set flags 1
            }
        }
    }

    # Check if a prototype exists
    if {![info exists ::twapi::idispatch_prototypes($ifc,$name,0,$flags)]} {
        twapi::idispatch_fill_prototypes $ifc ::twapi::idispatch_prototypes 0 $name
        if {![info exists ::twapi::idispatch_prototypes($ifc,$name,0,$flags)]} {
            win32_error 0x80020003 "No property or method found with name '$name'."
        }
    }
    
    # Invoke the function. TBD - should we do a uplevel instead of eval
    # here so variables if any are in caller's context ?
    return [_convert_from_variant [eval [list twapi::idispatch_invoke $ifc $::twapi::idispatch_prototypes($ifc,$name,0,$flags)] $params] false]
}


proc twapi::_comobj_active {comobj} {
    # TBD - temporary
    if {[info exists ::twapi::com_instance_data($comobj,ifc)]} {
        return 1
    } else {
        return 0
    }
}

#
# General dispatcher for callbacks from event sinks. Invokes the actual
# registered script after mapping dispid's
proc twapi::_eventsink_callback {comobj dispidmap script dispid lcid flags params} {
    # Check if the comobj is still active
    if {![_comobj_active $comobj]} {
        if {$::twapi::com_debug} {
            debug_puts "COM event received for inactive object"
        }
        return;                         # Object has gone away, ignore
    }

    set result ""
    set retcode [catch {
        # Map dispid to event if possible
        set dispid [twapi::kl_get_default $dispidmap $dispid $dispid]
        set converted_params [list ]
        foreach param $params {
            lappend converted_params [_convert_from_variant $param false true]
        }
        set result [uplevel \#0 $script [list $dispid] $converted_params]
    } msg]

    if {$::twapi::com_debug && $retcode} {
        debug_puts "Event sink callback error ($retcode): $msg\n$::errorInfo"
    }

    # $retcode is returned as HRESULT by the Invoke
    return -code $retcode $result
}

#
# Return clsid from a string. If $clsid is a valid CLSID - returns as is
# else tries to convert it from progid. An error is generated if neither
# works
proc twapi::_convert_to_clsid {comid} {
    if {[catch {IIDFromString $comid}]} {
        return [progid_to_clsid $comid]
    }
    return $comid
}


#
# Get WMI service
proc twapi::_wmi {} {
    return [comobj_idispatch [::twapi::Twapi_GetObjectIDispatch "winmgmts:{impersonationLevel=impersonate}!//./root/cimv2"] false]
}


# Get cached IDispatch and IUNknown IID's
proc twapi::_iid_iunknown {} {
    return $::twapi::_name_to_iid_cache(iunknown)
}
proc twapi::_iid_idispatch {} {
    return $::twapi::_name_to_iid_cache(idispatch)
}

#
# Return IID and name given a IID or name
proc twapi::_resolve_iid {name_or_iid} {

    # IID -> name mapping is more efficient so first assume it is
    # an IID else we will unnecessarily trundle through the whole
    # registry area looking for an IID when we already have it
    # Assume it is a name
    set other [iid_to_name $name_or_iid]
    if {$other ne ""} {
        # It was indeed the IID. Return the pair
        return [list $name_or_iid $other]
    }

    # Else resolve as a name
    set other [name_to_iid $name_or_iid]
    if {$other ne ""} {
        # Yep
        return [list $other $name_or_iid]
    }

    win32_error 0x80004002 "Could not find IID $name_or_iid"
}


#
# Some simple tests

proc twapi::_com_tests {} {
    puts "Invoking Internet Explorer"
    set ie [comobj InternetExplorer.Application -enableaaa true]
    $ie Visible 1
    $ie Navigate http://www.google.com
    after 2000
    puts "Exiting Internet Explorer"
    $ie Quit
    $ie -destroy
    puts "Internet Explorer done."

    puts "------------------------------------------"

    puts "Invoking Word"
    set word [comobj Word.Application]
    set doc [$word -with Documents Add]
    $word Visible 1
    puts "Inserting text"
    $word -with {selection font} name "Courier New"
    $word -with {selection font} size 10.0
    $doc -with content text "Text in Courier 10 point"
    after 2000
    puts "Exiting Word"
    $word Quit 0
    puts "Word done."
    
    puts "------------------------------------------"

    puts "WMI BIOS test"
    puts [get_bios_info]
    puts "WMI BIOS done."

    puts "------------------------------------------"
    
    puts "WMI direct property access test (get bios version)"
    set wmi [twapi::_wmi]
    $wmi -with {{ExecQuery "select * from Win32_BIOS"}} -iterate biosobj {
        puts "BIOS version: [$biosobj BiosVersion]"
        $biosobj -destroy
    }
    $wmi -destroy

    puts "------------------------------------------"

    puts " Starting process tracker. Type 'twapi::_stop_process_tracker' to stop it."
    twapi::_start_process_tracker
    vwait ::twapi::_stop_tracker
}

#
proc twapi::_wmi_read_popups {} {
    set res {}
    set wmi [twapi::_wmi]
    set wql {select * from Win32_NTLogEvent where LogFile='System' and \
                 EventType='3'    and \
                 SourceName='Application Popup'}
    set svcs [$wmi ExecQuery $wql]

    # Iterate all records
    $svcs -iterate instance {
        set propSet [$instance Properties_]
        # only the property (object) 'Message' is of interest here
        set msgVal [[$propSet Item Message] Value]
        lappend res $msgVal
    }
    return $res
}

#
proc twapi::_wmi_read_popups_succint {} {
    set res [list ]
    set wmi [twapi::_wmi]
    $wmi -with {
        {ExecQuery "select * from Win32_NTLogEvent where LogFile='System' and EventType='3' and SourceName='Application Popup'"}
    } -iterate event {
        lappend res [$event Message]
    }
    return $res
}

#
proc twapi::_wmi_get_autostart_services {} {
    set res [list ]
    set wmi [twapi::_wmi]
    $wmi -with {
        {ExecQuery "select * from Win32_Service where StartMode='Auto'"}
    } -iterate svc {
        lappend res [$svc DisplayName]
    }
    return $res
}

proc twapi::get_bios_info {} {
    set wmi [twapi::_wmi]
    array set entries [list ]
    $wmi -with {{ExecQuery "select * from Win32_BIOS"}} -iterate elem {
        set propset [$elem Properties_]
        array set entries [com_named_property_list $propset]
        $elem -destroy
        $propset -destroy
    }
    $wmi -destroy
    return [array get entries]
}

# Handler invoked when a process is started.  Will print exe name of process.
proc twapi::_process_start_handler {wmi_event args} {
    if {$wmi_event eq "OnObjectReady"} {
        # First arg is a IDispatch interface of the event object
        # Create a TWAPI COM object out of it
        set event_obj [comobj_idispatch [lindex $args 0] true]

        # Get and print the Name property
        puts "Process [$event_obj ProcessID] [$event_obj ProcessName] started at [clock format [large_system_time_to_secs [$event_obj TIME_CREATED]] -format {%x %X}]"

        # Get rid of the event object
        $event_obj -destroy
    }
}

# Call to begin tracking of processes.
proc twapi::_start_process_tracker {} {
    # Get local WMI root provider
    set ::twapi::_process_wmi [twapi::_wmi]

    # Create an WMI event sink
    set ::twapi::_process_event_sink [comobj wbemscripting.swbemsink]

    # Attach our handler to it
    set ::twapi::_process_event_sink_id [$::twapi::_process_event_sink -bind twapi::_process_start_handler]

    # Associate the sink with a query that polls every 1 sec for process
    # starts.
    $::twapi::_process_wmi ExecNotificationQueryAsync [$::twapi::_process_event_sink -interface] "select * from Win32_ProcessStartTrace"
}

# Stop tracking of process starts
proc twapi::_stop_process_tracker {} {
    # Cancel event notifications
    $::twapi::_process_event_sink Cancel

    # Unbind our callback
    $::twapi::_process_event_sink -unbind $::twapi::_process_event_sink_id

    # Get rid of all objects
    $::twapi::_process_event_sink -destroy
    $::twapi::_process_wmi -destroy

    set ::twapi::_stop_tracker 1
    return
}


# Handler invoked when a service status changes.
proc twapi::_service_change_handler {wmi_event args} {
    if {$wmi_event eq "OnObjectReady"} {
        # First arg is a IDispatch interface of the event object
        # Create a TWAPI COM object out of it
        set event_obj [twapi::comobj_idispatch [lindex $args 0] true]

        puts "Previous: [$event_obj PreviousInstance]"
        #puts "Target: [$event_obj -with TargetInstance State]"

        # Get rid of the event object
        $event_obj -destroy
    }
}

# Call to begin tracking of service state
proc twapi::_start_service_tracker {} {
    # Get local WMI root provider
    set ::twapi::_service_wmi [twapi::_wmi]

    # Create an WMI event sink
    set ::twapi::_service_event_sink [twapi::comobj wbemscripting.swbemsink]

    # Attach our handler to it
    set ::twapi::_service_event_sink_id [$::twapi::_service_event_sink -bind twapi::_service_change_handler]

    # Associate the sink with a query that polls every 1 sec for service
    # starts.
    $::twapi::_service_wmi ExecNotificationQueryAsync [$::twapi::_service_event_sink -interface] "select * from __InstanceModificationEvent within 1 where TargetInstance ISA 'Win32_Service'"
}

# Stop tracking of services
proc twapi::_stop_service_tracker {} {
    # Cancel event notifications
    $::twapi::_service_event_sink Cancel

    # Unbind our callback
    $::twapi::_service_event_sink -unbind $::twapi::_service_event_sink_id

    # Get rid of all objects
    $::twapi::_service_event_sink -destroy
    $::twapi::_service_wmi -destroy
}
Added Binaries/Windows/twapi/console.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
#
# Copyright (c) 2004, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

namespace eval twapi {
}

#
# Allocate a new console
proc twapi::allocate_console {} {
    AllocConsole
}

#
# Free a console
proc twapi::free_console {} {
    FreeConsole
}

#
# Get a console handle
proc twapi::get_console_handle {type} {
    variable windefs
    switch -exact -- $type {
        0 -
        stdin { set fn "CONIN\$" }
        1 -
        stdout -
        2 -
        stderr { set fn "CONOUT\$" }
        default {
            error "Unknown console handle type '$type'"
        }
    }
    return [CreateFile $fn \
                [expr {$windefs(GENERIC_READ) | $windefs(GENERIC_WRITE)}] \
                [expr {$windefs(FILE_SHARE_READ) | $windefs(FILE_SHARE_WRITE)}] \
                {{} 1} \
                $windefs(OPEN_EXISTING) \
                0 \
                NULL]
}

#
# Get a console handle
proc twapi::get_standard_handle {type} {
    switch -exact -- $type {
        0 -
        -11 -
        stdin { set type -11 }
        1 -
        -12 -
        stdout { set type -12 }
        2 -
        -13 -
        stderr { set type -13 }
        default {
            error "Unknown console handle type '$type'"
        }
    }
    return [GetStdHandle $type]
}


#
# Get a console handle
proc twapi::set_standard_handle {type handle} {
    switch -exact -- $type {
        0 -
        -11 -
        stdin { set type -11 }
        1 -
        -12 -
        stdout { set type -12 }
        2 -
        -13 -
        stderr { set type -13 }
        default {
            error "Unknown console handle type '$type'"
        }
    }
    return [SetStdHandle $type $handle]
}


array set twapi::_console_input_mode_syms {
    -processedinput 0x0001
    -lineinput      0x0002
    -echoinput      0x0004
    -windowinput    0x0008
    -mouseinput     0x0010
    -insertmode     0x0020
    -quickeditmode  0x0040
    -extendedmode   0x0080
    -autoposition   0x0100
}

array set twapi::_console_output_mode_syms {
    -processedoutput 1
    -wrapoutput      2
}

array set twapi::_console_output_attr_syms {
    -fgblue 1
    -fggreen 2
    -fgturquoise 3
    -fgred 4
    -fgpurple 5
    -fgyellow 6
    -fggray 7
    -fgbright 8
    -fgwhite 15
    -bgblue 16
    -bggreen 32
    -bgturquoise 48
    -bgred 64
    -bgyellow 96
    -bgbright 128
    -bgwhite 240
}

#
# Get the current mode settings for the console
proc twapi::_get_console_input_mode {conh} {
    set mode [GetConsoleMode $conh]
    return [_bitmask_to_switches $mode twapi::_console_input_mode_syms]
}
interp alias {} twapi::get_console_input_mode {} twapi::_do_console_proc twapi::_get_console_input_mode stdin

#
# Get the current mode settings for the console
proc twapi::_get_console_output_mode {conh} {
    set mode [GetConsoleMode $conh]
    return [_bitmask_to_switches $mode twapi::_console_output_mode_syms]
}
interp alias {} twapi::get_console_output_mode {} twapi::_do_console_proc twapi::_get_console_output_mode stdout

#
# Set console input mode
proc twapi::_set_console_input_mode {conh args} {
    set mode [_switches_to_bitmask $args twapi::_console_input_mode_syms]
    # If insertmode or quickedit mode are set, make sure to set extended bit
    if {$mode & 0x60} {
        setbits mode 0x80;              # ENABLE_EXTENDED_FLAGS
    }

    SetConsoleMode $conh $mode
}
interp alias {} twapi::set_console_input_mode {} twapi::_do_console_proc twapi::_set_console_input_mode stdin

#
# Modify console input mode
proc twapi::_modify_console_input_mode {conh args} {
    set prev [GetConsoleMode $conh]
    set mode [_switches_to_bitmask $args twapi::_console_input_mode_syms $prev]
    # If insertmode or quickedit mode are set, make sure to set extended bit
    if {$mode & 0x60} {
        setbits mode 0x80;              # ENABLE_EXTENDED_FLAGS
    }

    SetConsoleMode $conh $mode
    # Returns the old modes
    return [_bitmask_to_switches $prev twapi::_console_input_mode_syms]
}
interp alias {} twapi::modify_console_input_mode {} twapi::_do_console_proc twapi::_modify_console_input_mode stdin

#
# Set console output mode
proc twapi::_set_console_output_mode {conh args} {
    set mode [_switches_to_bitmask $args twapi::_console_output_mode_syms]

    SetConsoleMode $conh $mode

}
interp alias {} twapi::set_console_output_mode {} twapi::_do_console_proc twapi::_set_console_output_mode stdout

#
# Set console output mode
proc twapi::_modify_console_output_mode {conh args} {
    set prev [GetConsoleMode $conh]
    set mode [_switches_to_bitmask $args twapi::_console_output_mode_syms $prev]

    SetConsoleMode $conh $mode
    # Returns the old modes
    return [_bitmask_to_switches $prev twapi::_console_output_mode_syms]
}
interp alias {} twapi::modify_console_output_mode {} twapi::_do_console_proc twapi::_modify_console_output_mode stdout


#
# Create and return a handle to a screen buffer
proc twapi::create_console_screen_buffer {args} {
    array set opts [parseargs args {
        {inherit.bool 0}
        {mode.arg readwrite {read write readwrite}}
        {secd.arg ""}
        {share.arg readwrite {none read write readwrite}}
    } -maxleftover 0]

    switch -exact -- $opts(mode) {
        read       { set mode [_access_rights_to_mask generic_read] }
        write      { set mode [_access_rights_to_mask generic_write] }
        readwrite  {
            set mode [_access_rights_to_mask {generic_read generic_write}]
        }
    }
    switch -exact -- $opts(share) {
        none {
            set share 0
        }
        read       {
            set share 1 ;# FILE_SHARE_READ
        }
        write      {
            set share 2 ;# FILE_SHARE_WRITE
        }
        readwrite  {
            set share 3
        }
    }
    
    return [CreateConsoleScreenBuffer \
                $mode \
                $share \
                [_make_secattr $opts(secd) $opts(inherit)] \
                1]
}


#
# Retrieve information about a console screen buffer
proc twapi::_get_console_screen_buffer_info {conh args} {
    array set opts [parseargs args {
        all
        textattr
        cursorpos
        maxwindowsize
        size
        windowpos
        windowsize
    } -maxleftover 0]

    foreach {size cursorpos textattr windowrect maxwindowsize} [GetConsoleScreenBufferInfo $conh] break

    set result [list ]
    foreach opt {size cursorpos maxwindowsize} {
        if {$opts($opt) || $opts(all)} {
            lappend result -$opt [set $opt]
        }
    }

    if {$opts(windowpos) || $opts(all)} {
        lappend result -windowpos [lrange $windowrect 0 1]
    }

    if {$opts(windowsize) || $opts(all)} {
        foreach {left top right bot} $windowrect break
        lappend result -windowsize [list [expr {$right-$left+1}] [expr {$bot-$top+1}]]
    }

    if {$opts(textattr) || $opts(all)} {
        set result [concat $result [_bitmask_to_switches $textattr twapi::_console_output_attr_syms]]
    }

    return $result
}
interp alias {} twapi::get_console_screen_buffer_info {} twapi::_do_console_proc twapi::_get_console_screen_buffer_info stdout

#
# Set the cursor position
proc twapi::_set_console_cursor_position {conh pos} {
    SetConsoleCursorPosition $conh $pos
}
interp alias {} twapi::set_console_cursor_position {} twapi::_do_console_proc twapi::_set_console_cursor_position stdout

#
# Write the specified string to the console
proc twapi::_write_console {conh s args} {
    # Note writes are always in raw mode, 
    # TBD - support for  scrolling
    # TBD - support for attributes

    array set opts [parseargs args {
        position.arg
        {newlinemode.arg column {line column}}
        {restoreposition.bool 0}
    } -maxleftover 0]

    # Get screen buffer info including cursor position
    array set csbi [get_console_screen_buffer_info $conh -cursorpos -size]

    # Get current console mode for later restoration
    # If console is in processed mode, set it to raw mode
    set oldmode [get_console_output_mode $conh]
    set processed_index [lsearch -exact $oldmode "processed"]
    if {$processed_index >= 0} {
        # Console was in processed mode. Set it to raw mode
        set newmode [lreplace $oldmode $processed_index $processed_index]
        set_console_output_mode $conh $newmode
    }
    
    try {
        # x,y are starting position to write
        if {[info exists opts(position)]} {
            foreach {x y} [_parse_integer_pair $opts(position)] break
        } else {
            # No position specified, get current cursor position
            foreach {x y} $csbi(-cursorpos) break
        }
        
        set startx [expr {$opts(newlinemode) == "column" ? $x : 0}]

        # Get screen buffer limits
        foreach {width height} $csbi(-size) break

        # Ensure line terminations are just \n
        set s [string map "\r\n \n" $s]

        # Write out each line at ($x,$y)
        # Either \r or \n is considered a newline
        foreach line [split $s \r\n] {
            if {$y >= $height} break

            if {$x < $width} {
                # Write the characters - do not write more than buffer width
                set num_chars [expr {$width-$x}]
                if {[string length $line] < $num_chars} {
                    set num_chars [string length $line]
                }
                WriteConsole $conh $line $num_chars
            }
            
            
            # Calculate starting position of next line
            incr y
            set x $startx
        }

    } finally {
        # Restore cursor if requested
        if {$opts(restoreposition)} {
            set_console_cursor_position $conh $csbi(-cursorpos)
        }
        # Restore output mode if changed
        if {[info exists newmode]} {
            set_console_output_mode $conh $oldmode
        }
    }

    return
}
interp alias {} twapi::write_console {} twapi::_do_console_proc twapi::_write_console stdout

#
# Fill an area of the console with the specified attribute
proc twapi::_fill_console {conh args} {
    array set opts [parseargs args {
        position.arg
        numlines.int
        numcols.int
        {mode.arg column {line column}}
        window.bool
        fillchar.arg
    } -ignoreunknown]

    # args will now contain attribute switches if any
    set attr [_switches_to_bitmask $args twapi::_console_output_attr_syms]

    # Get screen buffer info for window and size of buffer
    array set csbi [get_console_screen_buffer_info $conh -windowpos -windowsize -size]
    # Height and width of the console
    foreach {conx cony} $csbi(-size) break

    # Figure out what area we want to fill
    # startx,starty are starting position to write
    # sizex, sizey are the number of rows/lines
    if {[info exists opts(window)]} {
        if {[info exists opts(numlines)] || [info exists opts(numcols)]
            || [info exists opts(position)]} {
            error "Option -window cannot be used togther with options -position, -numlines or -numcols"
        }
        foreach {startx starty} [_parse_integer_pair $csbi(-windowpos)] break
        foreach {sizex sizey} [_parse_integer_pair $csbi(-windowsize)] break
    } else {
        if {[info exists opts(position)]} {
            foreach {startx starty} [_parse_integer_pair $opts(position)] break
        } else {
            set startx 0
            set starty 0
        }
        if {[info exists opts(numlines)]} {
            set sizey $opts(numlines)
        } else {
            set sizey $cony
        }
        if {[info exists opts(numcols)]} {
            set sizex $opts(numcols)
        } else {
            set sizex [expr {$conx - $startx}]
        }
    }
    
    set firstcol [expr {$opts(mode) == "column" ? $startx : 0}]

    # Fill attribute at ($x,$y)
    set x $startx
    set y $starty
    while {$y < $cony && $y < ($starty + $sizey)} {
        if {$x < $conx} {
            # Write the characters - do not write more than buffer width
            set max [expr {$conx-$x}]
            if {[info exists attr]} {
                FillConsoleOutputAttribute $conh $attr [expr {$sizex > $max ? $max : $sizex}] [list $x $y]
            }
            if {[info exists opts(fillchar)]} {
                FillConsoleOutputCharacter $conh $opts(fillchar) [expr {$sizex > $max ? $max : $sizex}] [list $x $y]
            }
        }
        
        # Calculate starting position of next line
        incr y
        set x $firstcol
    }
    
    return
}
interp alias {} twapi::fill_console {} twapi::_do_console_proc twapi::_fill_console stdout

#
# Clear the console
proc twapi::_clear_console {conh args} {
    # I support we could just call fill_console but this code was already
    # written and is faster
    array set opts [parseargs args {
        {fillchar.arg " "}
        {windowonly.bool 0}
    } -maxleftover 0]

    array set cinfo [get_console_screen_buffer_info $conh -size -windowpos -windowsize]
    foreach {width height} $cinfo(-size) break
    if {$opts(windowonly)} {
        # Only clear portion visible in the window. We have to do this
        # line by line since we do not want to erase text scrolled off
        # the window either in the vertical or horizontal direction
        foreach {x y} $cinfo(-windowpos) break
        foreach {w h} $cinfo(-windowsize) break
        for {set i 0} {$i < $h} {incr i} {
            FillConsoleOutputCharacter \
                $conh \
                $opts(fillchar)  \
                $w \
                [list $x [expr {$y+$i}]]
        }
    } else {
        FillConsoleOutputCharacter \
            $conh \
            $opts(fillchar)  \
            [expr {($width*$height) }] \
            [list 0 0]
    }
    return
}
interp alias {} twapi::clear_console {} twapi::_do_console_proc twapi::_clear_console stdout
#
# Flush console input
proc twapi::_flush_console_input {conh} {
    FlushConsoleInputBuffer $conh
}
interp alias {} twapi::flush_console_input {} twapi::_do_console_proc twapi::_flush_console_input stdin

#
# Return number of pending console input events
proc twapi::_get_console_pending_input_count {conh} {
    return [GetNumberOfConsoleInputEvents $conh]
}
interp alias {} twapi::get_console_pending_input_count {} twapi::_do_console_proc twapi::_get_console_pending_input_count stdin

#
# Generate a console control event
proc twapi::generate_console_control_event {event {procgrp 0}} {
    switch -exact -- $event {
        ctrl-c {set event 0}
        ctrl-break {set event 1}
        default {error "Invalid event definition '$event'"}
    }
    GenerateConsoleCtrlEvent $event $procgrp
}

#
# Get number of mouse buttons
proc twapi::num_console_mouse_buttons {} {
    return [GetNumberOfConsoleMouseButtons]
}

#
# Get console title text
proc twapi::get_console_title {} {
    return [GetConsoleTitle]
}

#
# Set console title text
proc twapi::set_console_title {title} {
    return [SetConsoleTitle $title]
}

#
# Get the handle to the console window
proc twapi::get_console_window {} {
    return [GetConsoleWindow]
}

#
# Get the largest console window size
proc twapi::_get_console_window_maxsize {conh} {
    return [GetLargestConsoleWindowSize $conh]
}
interp alias {} twapi::get_console_window_maxsize {} twapi::_do_console_proc twapi::_get_console_window_maxsize stdout
#
#
proc twapi::_set_console_active_screen_buffer {conh} {
    SetConsoleActiveScreenBuffer $conh
}
interp alias {} twapi::set_console_active_screen_buffer {} twapi::_do_console_proc twapi::_set_console_active_screen_buffer stdout

#
# Set the size of the console screen buffer
proc twapi::_set_console_screen_buffer_size {conh size} {
    SetConsoleScreenBufferSize $conh [_parse_integer_pair $size]
}
interp alias {} twapi::set_console_screen_buffer_size {} twapi::_do_console_proc twapi::_set_console_screen_buffer_size stdout

#
# Set the default text attribute
proc twapi::_set_console_default_attr {conh args} {
    SetConsoleTextAttribute $conh [_switches_to_bitmask $args twapi::_console_output_attr_syms]
}
interp alias {} twapi::set_console_default_attr {} twapi::_do_console_proc twapi::_set_console_default_attr stdout

#
# Set the console window position
proc twapi::_set_console_window_location {conh rect args} {
    array set opts [parseargs args {
        {absolute.bool true}
    } -maxleftover 0]

    SetConsoleWindowInfo $conh $opts(absolute) $rect
}
interp alias {} twapi::set_console_window_location {} twapi::_do_console_proc twapi::_set_console_window_location stdout

#
# Get the console code page
proc twapi::get_console_output_codepage {} {
    return [GetConsoleOutputCP]
}

#
# Set the console code page
proc twapi::set_console_output_codepage {cp} {
    SetConsoleOutputCP $cp
}

#
# Get the console input code page
proc twapi::get_console_input_codepage {} {
    return [GetConsoleCP]
}

#
# Set the console input code page
proc twapi::set_console_input_codepage {cp} {
    SetConsoleCP $cp
}

#
# Read a line of input
proc twapi::_console_read {conh args} {
    if {[llength $args]} {
        set oldmode \
            [eval modify_console_input_mode [list $conh] $args]
    }
    try {
        return [ReadConsole $conh 1024]
    } finally {
        if {[info exists oldmode]} {
            eval set_console_input_mode $conh $oldmode
        }
    }

}
interp alias {} twapi::console_gets {} twapi::_do_console_proc twapi::_console_gets stdin

#
# Set up a console handler
proc twapi::set_console_control_handler {script {timeout 100}} {
    if {[string length $script]} {
        RegisterConsoleEventNotifier $script $timeout
    } else {
        UnregisterConsoleEventNotifier
    }
}

# 
# Utilities
#

#
# Helper to call a proc after doing a stdin/stdout/stderr -> handle
# mapping. The handle is closed after calling the proc. The first
# arg in $args must be the console handle i $args is not an empty list
proc twapi::_do_console_proc {proc default args} {
    if {![llength $args]} {
        set args [list $default]
    }
    set conh [lindex $args 0]
    switch -exact -- [string tolower $conh] {
        stdin  -
        stdout -
        stderr {
            set real_handle [get_console_handle $conh]
            try {
                lset args 0 $real_handle
                return [eval [list $proc] $args]
            } finally {
                close_handles $real_handle
            }
        }
    }
    
    return [eval [list $proc] $args]
}
Added Binaries/Windows/twapi/desktop.tcl.








































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#
# Copyright (c) 2004, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

#
# Get the current process window station
proc twapi::get_current_window_station_handle {} {
    return [GetProcessWindowStation]
}

#
# Get the handle to a window station
proc twapi::get_window_station_handle {winsta args} {
    array set opts [parseargs args {
        inherit.bool
        {access.arg  GENERIC_READ}
    } -nulldefault]

    set access_rights [_access_rights_to_mask $opts(access)]
    
    return [OpenWindowStation $winsta $opts(inherit) $access_rights]
}


#
# Close a window station handle
proc twapi::close_window_station_handle {hwinsta} {
    # Trying to close our window station handle will generate an error
    if {$hwinsta != [get_current_window_station_handle]} {
        CloseWindowStation $hwinsta
    }
    return
}

#
# List all window stations
proc twapi::find_window_stations {} {
    return [EnumWindowStations]
}


#
# Enumerate desktops in a window station
proc twapi::find_desktops {args} {
    array set opts [parseargs args {winsta.arg}]

    if {[info exists opts(winsta)]} {
        set hwinsta [get_window_station_handle $opts(winsta)]
    } else {
        set hwinsta [get_current_window_station_handle]
    }

    try {
        return [EnumDesktops $hwinsta]
    } finally {
        # Note close_window_station_handle protects against
        # hwinsta being the current window station handle so 
        # we do not need to do that check here
        close_window_station_handle $hwinsta
    }
}


#
# Get the handle to a desktop
proc twapi::get_desktop_handle {desk args} {
    array set opts [parseargs args {
        inherit.bool
        allowhooks.bool
        {access.arg  GENERIC_READ}
    } -nulldefault]

    set access_mask [_access_rights_to_mask $opts(access)]
    
    # If certain access rights are specified, we must add certain other
    # access rights. See OpenDesktop SDK docs
    set access_rights [_access_mask_to_rights $access_mask]
    if {[lsearch -exact $access_rights read_control] >= 0 ||
        [lsearch -exact $access_rights write_dac] >= 0 ||
        [lsearch -exact $access_rights write_owner] >= 0} {
        lappend access_rights desktop_readobject desktop_writeobjects
        set access_mask [_access_rights_to_mask $opts(access)]
    }

    return [OpenDesktop $desk $opts(allowhooks) $opts(inherit) $access_mask]
}

#
# Close the desktop handle
proc twapi::close_desktop_handle {hdesk} {
    CloseDesktop $hdesk
}

#
# Set the process window station
proc twapi::set_process_window_station {hwinsta} {
    SetProcessWindowStation $hwinsta
}
Added Binaries/Windows/twapi/disk.tcl.




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
#
# Copyright (c) 2003, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

# TBD - convert file spec to drive root path

#
# Get info associated with a drive
proc twapi::get_volume_info {drive args} {
    variable windefs

    set drive [_drive_rootpath $drive]
    
    array set opts [parseargs args {
        all size freespace used useravail type serialnum label maxcomponentlen fstype attr device
    } -maxleftover 0]

    if {$opts(all)} {
        # -all option does not cover -type and -device
        set device_requested $opts(device)
        set type_requested   $opts(type)
        _array_set_all opts 1
        set opts(device) $device_requested
        set opts(type)   $type_requested
    }

    set result [list ]
    if {$opts(size) || $opts(freespace) || $opts(used) || $opts(useravail)} {
        foreach {useravail size freespace} [GetDiskFreeSpaceEx $drive] {break}
        foreach opt {size freespace useravail}  {
            if {$opts($opt)} {
                lappend result -$opt [set $opt]
            }
        }
        if {$opts(used)} {
            lappend result -used [expr {$size - $freespace}]
        }
    }

    if {$opts(type) || $opts(device)} {
        set drive_type [get_drive_type $drive]
        if {$opts(type)} {
            lappend result -type $drive_type
        }
        if {$opts(device)} {
            if {"remote" == $drive_type} {
                lappend result -device ""
            } else {
                lappend result -device [QueryDosDevice [string range $drive 0 1]]
            }
        }
    }

    if {$opts(serialnum) || $opts(label) || $opts(maxcomponentlen)
        || $opts(fstype) || $opts(attr)} {
        foreach {label serialnum maxcomponentlen attr fstype} \
            [GetVolumeInformation $drive] { break }
        foreach opt {label maxcomponentlen fstype}  {
            if {$opts($opt)} {
                lappend result -$opt [set $opt]
            }
        }
        if {$opts(serialnum)} {
            set low [expr {$serialnum & 0x0000ffff}]
            set high [expr {($serialnum >> 16) & 0x0000ffff}]
            lappend result -serialnum [format "%.4X-%.4X" $high $low]
        }
        if {$opts(attr)} {
            set attrs [list ]
            foreach val {
                case_preserved_names
                unicode_on_disk
                persistent_acls
                file_compression
                volume_quotas
                supports_sparse_files
                supports_reparse_points
                supports_remote_storage
                volume_is_compressed
                supports_object_ids
                supports_encryption
                named_streams
                read_only_volume
            } {
                # Coincidentally, the attribute values happen to match
                # the corresponding constant defines
                set cdef "FILE_[string toupper $val]"
                if {$attr & $windefs($cdef)} {
                    lappend attrs $val
                }
            }
            lappend result -attr $attrs
        }
    }

    return $result
}
interp alias {} twapi::get_drive_info {} twapi::get_volume_info


# Check if disk has at least n bytes available for the user (NOT total free)
proc twapi::user_drive_space_available {drv space} {
    return [expr {$space <= [lindex [get_drive_info $drv -useravail] 1]}]
}

# Get the drive type
proc twapi::get_drive_type {drive} {
    # set type [GetDriveType "[string trimright $drive :/\\]:\\"]
    set type [GetDriveType [_drive_rootpath $drive]]
    switch -exact -- $type {
        0 { return unknown}
        1 { return invalid}
        2 { return removable}
        3 { return fixed}
        4 { return remote}
        5 { return cdrom}
        6 { return ramdisk}
    }
}

#
# Get list of drives
proc twapi::find_logical_drives {args} {
    array set opts [parseargs args {type.arg}]

    set drives [list ]

    set i 0
    set drivebits [GetLogicalDrives]
    foreach drive {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} {
        if {[expr {$drivebits & (1 << $i)}]} {
            if {(![info exists opts(type)]) ||
                [lsearch -exact $opts(type) [get_drive_type $drive]] >= 0} {
                lappend drives $drive:
            }
        }
        incr i
    }
    return $drives
}
interp alias {} twapi::get_logical_drives {} twapi::find_logical_drives

#
# Set the drive label
proc twapi::set_drive_label {drive label} {
    SetVolumeLabel [_drive_rootpath $drive] $label
}

#
# Maps a drive letter to the given path
proc twapi::map_drive_local {drive path args} {
    array set opts [parseargs args {raw}]

    set drive [string range [_drive_rootpath $drive] 0 1]

    set flags [expr {$opts(raw) ? 0x1 : 0}]
    DefineDosDevice $flags $drive [file nativename $path]
}


#
# Unmaps a drive letter
proc twapi::unmap_drive_local {drive args} {
    array set opts [parseargs args {
        path.arg
        raw
    }]

    set drive [string range [_drive_rootpath $drive] 0 1]

    set flags [expr {$opts(raw) ? 0x1 : 0}]
    setbits flags 0x2;                  # DDD_REMOVE_DEFINITION
    if {[info exists opts(path)]} {
        setbits flags 0x4;              # DDD_EXACT_MATCH_ON_REMOVE
    }
    DefineDosDevice $flags $drive [file nativename $opts(path)]
}

#
# Monitor file changes
proc twapi::begin_filesystem_monitor {path script args} {
    array set opts [parseargs args {
        {subtree.bool false}
        filename.bool
        dirname.bool
        attr.bool
        size.bool
        write.bool
        access.bool
        create.bool
        secd.bool
    } -maxleftover 0]

    set have_opts 0
    set flags 0
    foreach {opt val} {
        filename 0x1
        dirname  0x2
        attr     0x4
        size     0x8
        write 0x10
        access 0x20
        create  0x40
        secd      0x100
    } {
        if {[info exists opts($opt)]} {
            if {$opts($opt)} {
                setbits flags $val
            }
            set have_opts 1
        }
    }

    if {! $have_opts} {
        # If no options specified, default to all
        set flags 0x17f
    }

    return [RegisterDirChangeNotifier $path $opts(subtree) $flags $script]
}

#
# Stop monitoring of files
proc twapi::cancel_filesystem_monitor {id} {
    UnregisterDirChangeNotifier $id
}


#
# Get list of volumes
proc twapi::find_volumes {} {
    set vols [list ]
    set found 1
    # Assumes there has to be at least one volume
    foreach {handle vol} [FindFirstVolume] break
    while {$found} {
        lappend vols $vol
        foreach {found vol} [FindNextVolume $handle] break
    }
    FindVolumeClose $handle
    return $vols
}

#
# Get list of volumes
proc twapi::find_volumes {} {
    set vols [list ]
    set found 1
    # Assumes there has to be at least one volume
    foreach {handle vol} [FindFirstVolume] break
    while {$found} {
        lappend vols $vol
        foreach {found vol} [FindNextVolume $handle] break
    }
    FindVolumeClose $handle
    return $vols
}

#
# Get list of volume mount points
proc twapi::find_volume_mount_points {vol} {
    set mntpts [list ]
    set found 1
    try {
        foreach {handle mntpt} [FindFirstVolumeMountPoint $vol] break
    } onerror {TWAPI_WIN32 18} {
        # ERROR_NO_MORE_FILES
        # No volume mount points
        return [list ]
    } onerror {TWAPI_WIN32 3} {
        # Volume does not support them
        return [list ]
    }

    # At least one volume found
    while {$found} {
        lappend mntpts $mntpt
        foreach {found mntpt} [FindNextVolumeMountPoint $handle] break
    }
    FindVolumeMountPointClose $handle
    return $mntpts
}

#
# Set volume mount point
proc twapi::mount_volume {volpt volname} {
    # Note we don't use _drive_rootpath for trimming since may not be root path
    SetVolumeMountPoint "[string trimright $volpt /\\]\\" "[string trimright $volname /\\]\\"
}

#
# Delete volume mount point
proc twapi::unmount_volume {volpt} {
    # Note we don't use _drive_rootpath for trimming since may not be root path
    DeleteVolumeMountPoint "[string trimright $volpt /\\]\\"
}

#
# Get the volume mounted at a volume mount point
proc twapi::get_mounted_volume_name {volpt} {
    # Note we don't use _drive_rootpath for trimming since may not be root path
    return [GetVolumeNameForVolumeMountPoint "[string trimright $volpt /\\]\\"]
}

#
# Get the mount point corresponding to a given path
proc twapi::get_volume_mount_point_for_path {path} {
    return [GetVolumePathName [file nativename $path]]
}

#
# Show property dialog for a volume
proc twapi::volume_properties_dialog {name args} {
    array set opts [parseargs args {
        {hwin.int 0}
        {page.arg ""}
    } -maxleftover 0]
    
    shell_object_properties_dialog $name -type volume -hwin $opts(hwin) -page $opts(page)
}

#
# Show property dialog for a file
proc twapi::file_properties_dialog {name args} {
    array set opts [parseargs args {
        {hwin.int 0}
        {page.arg ""}
    } -maxleftover 0]
    
    shell_object_properties_dialog $name -type file -hwin $opts(hwin) -page $opts(page)
}

#
# Retrieve version info for a file
proc twapi::get_file_version_resource {path args} {
    # TBD add -datetime opt to return date and time from fixed version struct
    array set opts [parseargs args {
        all
        signature
        structversion
        fileversion
        productversion
        flags
        fileos
        filetype
        langid.arg
        codepage.arg
    }]

    set ver [Twapi_GetFileVersionInfo $path]

    try {
        array set verinfo [Twapi_VerQueryValue_FIXEDFILEINFO $ver]

        set result [list ]
        if {$opts(all) || $opts(signature)} {
            lappend result -signature [format 0x%x $verinfo(dwSignature)]
        }

        if {$opts(all) || $opts(structversion)} {
            lappend result -structversion "[expr {0xffff & ($verinfo(dwStrucVersion) >> 16)}].[expr {0xffff & $verinfo(dwStrucVersion)}]"
        }

        if {$opts(all) || $opts(fileversion)} {
            lappend result -fileversion "[expr {0xffff & ($verinfo(dwFileVersionMS) >> 16)}].[expr {0xffff & $verinfo(dwFileVersionMS)}].[expr {0xffff & ($verinfo(dwFileVersionLS) >> 16)}].[expr {0xffff & $verinfo(dwFileVersionLS)}]"
        }

        if {$opts(all) || $opts(productversion)} {
            lappend result -productversion "[expr {0xffff & ($verinfo(dwProductVersionMS) >> 16)}].[expr {0xffff & $verinfo(dwProductVersionMS)}].[expr {0xffff & ($verinfo(dwProductVersionLS) >> 16)}].[expr {0xffff & $verinfo(dwProductVersionLS)}]"
        }

        if {$opts(all) || $opts(flags)} {
            set flags [expr {$verinfo(dwFileFlags) & $verinfo(dwFileFlagsMask)}]
            lappend result -flags \
                [_make_symbolic_bitmask \
                     [expr {$verinfo(dwFileFlags) & $verinfo(dwFileFlagsMask)}] \
                     {
                         debug 1
                         prerelease 2
                         patched 4
                         privatebuild 8
                         infoinferred 16
                         specialbuild 32
                     } \
                     ]
        }
            
        if {$opts(all) || $opts(fileos)} {
            switch -exact -- [format %08x $verinfo(dwFileOS)] {
                00010000 {set os dos}
                00020000 {set os os216}
                00030000 {set os os232}
                00040000 {set os nt}
                00050000 {set os wince}
                00000001 {set os windows16}
                00000002 {set os pm16}
                00000003 {set os pm32}
                00000004 {set os windows32}
                00010001 {set os dos_windows16}
                00010004 {set os dos_windows32}
                00020002 {set os os216_pm16}
                00030003 {set os os232_pm32}
                00040004 {set os nt_windows32}
                default {set os $verinfo(dwFileOS)}
            }
            lappend result -fileos $os
        }

        if {$opts(all) || $opts(filetype)} {
            switch -exact -- [expr {0+$verinfo(dwFileType)}] {
                1 {set type application}
                2 {set type dll}
                3 {
                    set type "driver."
                    switch -exact -- [expr {0+$verinfo(dwFileSubtype)}] {
                        1 {append type printer}
                        2 {append type keyboard}
                        3 {append type language}
                        4 {append type display}
                        5 {append type mouse}
                        6 {append type network}
                        7 {append type system}
                        8 {append type installable}
                        9  {append type sound}
                        10 {append type comm}
                        11 {append type inputmethod}
                        12 {append type versionedprinter}
                        default {append type $verinfo(dwFileSubtype)}
                    }
                }
                4 {
                    set type "font."
                    switch -exact -- [expr {0+$verinfo(dwFileSubtype)}] {
                        1 {append type raster}
                        2 {append type vector}
                        3 {append type truetype}
                        default {append type $verinfo(dwFileSubtype)}
                    }
                }
                5 { set type "vxd.$verinfo(dwFileSubtype)" }
                7 {set type staticlib}
                default {
                    set type "$verinfo(dwFileType).$verinfo(dwFileSubtype)"
                }
            }
            lappend result -filetype $type
        }

        # Any remaining arguments are treated as string names

        if {[llength $args]} {
            # Find list of langid's and codepages and do closest match
            set langid [expr {[info exists opts(langid)] ? $opts(langid) : [get_user_ui_langid]}]
            set primary_langid [extract_primary_langid $langid]
            set sub_langid     [extract_sublanguage_langid $langid]
            set cp [expr {[info exists opts(codepage)] ? $opts(codepage) : 0}]
            
            # Find a match in the following order:
            # 0 Exact match for both langid and codepage
            # 1 Exact match for langid
            # 2 Primary langid matches (sublang does not) and exact codepage
            # 3 Primary langid matches (sublang does not)
            # 4 Language neutral
            # 5 English
            # 6 First langcp in list or "00000000"
            set match(7) "00000000";    # In case list is empty
            foreach langcp [Twapi_VerQueryValue_TRANSLATIONS $ver] {
                set verlangid 0x[string range $langcp 0 3]
                set vercp 0x[string range $langcp 4 7]
                if {$verlangid == $langid && $vercp == $cp} {
                    set match(0) $langcp
                    break;              # No need to look further
                }
                if {[info exists match(1)]} continue
                if {$verlangid == $langid} {
                    set match(1) $langcp
                    continue;           # Continue to look for match(0)
                }
                if {[info exists match(2)]} continue
                set verprimary [extract_primary_langid $verlangid]
                if {$verprimary == $primary_langid && $vercp == $cp} {
                    set match(2) $langcp
                    continue;       # Continue to look for match(1) or better
                }
                if {[info exists match(3)]} continue
                if {$verprimary == $primary_langid} {
                    set match(3) $langcp
                    continue;       # Continue to look for match(2) or better
                }
                if {[info exists match(4)]} continue
                if {$verprimary == 0} {
                    set match(4) $langcp; # LANG_NEUTRAL
                    continue;       # Continue to look for match(3) or better
                }
                if {[info exists match(5)]} continue
                if {$verprimary == 9} {
                    set match(5) $langcp; # English
                    continue;       # Continue to look for match(4) or better
                }
                if {![info exists match(6)]} {
                    set match(6) $langcp
                }
            }

            # Figure out what is the best match we have
            for {set i 0} {$i <= 7} {incr i} {
                if {[info exists match($i)]} {
                    break
                }
            }

            foreach sname $args {
                lappend result $sname [Twapi_VerQueryValue_STRING $ver $match($i) $sname]
            }
        }

    } finally {
        Twapi_FreeFileVersionInfo $ver
    }

    return $result
}

#
# Return the times associated with a file
proc twapi::get_file_times {fd args} {
    variable windefs

    array set opts [parseargs args {
        all
        mtime
        ctime
        atime
    } -maxleftover 0]

    # Figure out if fd is a file path, Tcl channel or a handle
    set close_handle false
    if {[file exists $fd]} {
        # It's a file name
        set close_handle true
        set h  [CreateFile $fd \
                    $windefs(GENERIC_READ) \
                    [expr {$windefs(FILE_SHARE_READ) | $windefs(FILE_SHARE_WRITE)}] \
                    {{} 1} \
                    $windefs(OPEN_EXISTING) \
                    0 \
                    NULL]
        set h [CastToHANDLE $h]
    } elseif {[catch {fconfigure $fd}]} {
        # Not a Tcl channel, assume a handle
        set h $fd
    } else {
        # Tcl channel
        set h [get_tcl_channel_handle $fd read]
    }

    set result [list ]

    foreach opt {ctime atime mtime} time [GetFileTime $h] {
        if {$opts(all) || $opts($opt)} {
            lappend result -$opt $time
        }
    }

    if {$close_handle} {
        close_handles $h
    }

    return $result
}


#
# Set the times associated with a file
proc twapi::set_file_times {fd args} {
    variable windefs

    array set opts [parseargs args {
        mtime.arg
        ctime.arg
        atime.arg
        preserveatime
    } -maxleftover 0 -nulldefault]

    if {$opts(atime) ne "" && $opts(preserveatime)} {
        win32_error 87 "Cannot specify -atime and -preserveatime at the same time."
    }
    if {$opts(preserveatime)} {
        set opts(atime) -1;             # Meaning preserve access to original
    }

    # Figure out if fd is a file path, Tcl channel or a handle
    set close_handle false
    if {[file exists $fd]} {
        if {$opts(preserveatime)} {
            win32_error 87 "Cannot specify -preserveatime unless file is specified as a Tcl channel or a Win32 handle."
        }

        # It's a file name
        set close_handle true
        set h  [CreateFile $fd \
                    $windefs(GENERIC_WRITE) \
                    [expr {$windefs(FILE_SHARE_READ) | $windefs(FILE_SHARE_WRITE)}] \
                    {{} 1} \
                    $windefs(OPEN_EXISTING) \
                    0 \
                    NULL]
        set h [CastToHANDLE $h]
    } elseif {[catch {fconfigure $fd}]} {
        # Not a Tcl channel, assume a handle
        set h $fd
    } else {
        # Tcl channel
        set h [get_tcl_channel_handle $fd read]
    }

    SetFileTime $h $opts(ctime) $opts(atime) $opts(mtime)

    if {$close_handle} {
        close_handles $h
    }

    return
}

#
# Utility functions

proc twapi::_drive_rootpath {drive} {
    if {[_is_unc $drive]} {
        # UNC
        return "[string trimright $drive ]\\"
    } else {
        return "[string trimright $drive :/\\]:\\"
    }
}

proc twapi::_is_unc {path} {
    return [expr {[string match {\\\\*} $path] || [string match //* $path]}]
}
Added Binaries/Windows/twapi/eventlog.tcl.




































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
#
# Copyright (c) 2004, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

namespace eval twapi {
    # Keep track of event log handles - values are "r" or "w"
    variable eventlog_handles
    array set eventlog_handles {}
}

#
# Open an eventlog for reading or writing
proc twapi::eventlog_open {args} {
    variable eventlog_handles

    array set opts [parseargs args {
        system.arg
        source.arg
        file.arg
        write
    } -nulldefault]
    if {$opts(source) == ""} {
        # Source not specified
        if {$opts(file) == ""} {
            # No source or file specified, default to current event log 
            # using executable name as source
            set opts(source) [file rootname [file tail [info nameofexecutable]]]
        } else {
            if {$opts(write)} {
                error "Option -file may not be used with -write"
            }
        }
    } else {
        # Source explicitly specified
        if {$opts(file) != ""} {
            error "Option -file may not be used with -source"
        }
    }

    if {$opts(write)} {
        set handle [RegisterEventSource $opts(system) $opts(source)]
        set mode write
    } else {
        if {$opts(source) != ""} {
            set handle [OpenEventLog $opts(system) $opts(source)]
        } else {
            set handle [OpenBackupEventLog $opts(system) $opts(file)]
        }
        set mode read
    }

    set eventlog_handles($handle) $mode
    return $handle
}

#
# Close an event log opened for writing
proc twapi::eventlog_close {hevl} {
    variable eventlog_handles

    if {[_eventlog_valid_handle $hevl read]} {
        CloseEventLog $hevl
    } else {
        DeregisterEventSource $hevl
    }

    unset eventlog_handles($hevl)
}


#
# Log an event
proc twapi::eventlog_write {hevl id args} {
    _eventlog_valid_handle $hevl write raise

    array set opts [parseargs args {
        {type.arg information {success error warning information auditsuccess auditfailure}}
        {category.int 1}
        loguser
        params.arg
        data.arg
    } -nulldefault]


    switch -exact -- $opts(type) {
        success          {set opts(type) 0}
        error            {set opts(type) 1}
        warning          {set opts(type) 2}
        information      {set opts(type) 4}
        auditsuccess     {set opts(type) 8}
        auditfailure     {set opts(type) 16}
        default {error "Invalid value '$opts(type)' for option -type"}
    }
    
    if {$opts(loguser)} {
        set user [get_current_user -sid]
    } else {
        set user ""
    }

    ReportEvent $hevl $opts(type) $opts(category) $id \
        $user $opts(params) $opts(data)
}


#
# Log a message 
proc twapi::eventlog_log {message args} {
    array set opts [parseargs args {
        system.arg
        source.arg
        {type.arg information}
        {category.int 1}
    } -nulldefault]

    set hevl [eventlog_open -write -source $opts(source) -system $opts(system)]

    try {
        eventlog_write $hevl 1 -params [list $message] -type $opts(type) -category $opts(category)
    } finally {
        eventlog_close $hevl
    }
    return
}


#
# Read the event log
proc twapi::eventlog_read {hevl args} {
    _eventlog_valid_handle $hevl read raise

    array set opts [parseargs args {
        seek.int
        {direction.arg forward}
    }]

    if {[info exists opts(seek)]} {
        set flags 2;                    # Seek
        set offset $opts(seek)
    } else {
        set flags 1;                    # Sequential read
        set offset 0
    }

    switch -glob -- $opts(direction) {
        ""    -
        forw* {
            setbits flags 4
        }
        back* {
            setbits flags 8
        }
        default {
            error "Invalid value '$opts(direction)' for -direction option"
        }
    }

    set results [list ]

    try {
        set recs [ReadEventLog $hevl $flags $offset]
    } onerror {TWAPI_WIN32 38} {
        set recs [list ]
    }
    foreach rec $recs {
        foreach {fld index} {
            -source 0 -system 1 -recordnum 3 -timegenerated 4 -timewritten 5
            -eventid 6 -type 7 -category 8 -params 11 -sid 12 -data 13
        } {
            set event($fld) [lindex $rec $index]
        }
        set event(-type) [string map {0 success 1 error 2 warning 4 information 8 auditsuccess 16 auditfailure} $event(-type)]
        lappend results [array get event]
    }

    return $results
}


#
# Get the oldest event log record index. $hevl must be read handle
proc twapi::eventlog_oldest {hevl} {
    _eventlog_valid_handle $hevl read raise
    return [GetOldestEventLogRecord $hevl]
}

#
# Get the event log record count. $hevl must be read handle
proc twapi::eventlog_count {hevl} {
    _eventlog_valid_handle $hevl read raise
    return [GetNumberOfEventLogRecords $hevl]
}

#
# Check if the event log is full. $hevl may be either read or write handle
# (only win2k plus)
proc twapi::eventlog_is_full {hevl} {
    # Does not matter if $hevl is read or write, but verify it is a handle
    _eventlog_valid_handle $hevl read
    return [Twapi_IsEventLogFull $hevl]
}

#
# Backup the event log
proc twapi::eventlog_backup {hevl file} {
    _eventlog_valid_handle $hevl read raise
    BackupEventLog $hevl $file
}

#
# Clear the event log
proc twapi::eventlog_clear {hevl args} {
    _eventlog_valid_handle $hevl read raise
    array set opts [parseargs args {backup.arg} -nulldefault]
    ClearEventLog $hevl $opts(backup)
}


#
# Formats the given event log record message
# 
proc twapi::eventlog_format_message {event_record args} {
    package require registry

    array set opts [parseargs args {
        width.int
        langid.int
    } -nulldefault]

    array set rec $event_record

    set regkey [_find_eventlog_regkey $rec(-source)]

    # Get the message file, if there is one
    set found 0
    if {! [catch {registry get $regkey "EventMessageFile"} path]} {
        # Try each file listed in turn
        foreach dll [split $path \;] {
            set dll [expand_environment_strings $dll]
            if {! [catch {
                format_message -module $dll -messageid $rec(-eventid) -params $rec(-params) -width $opts(width) -langid $opts(langid)
            } msg]} {
                set found 1
                break
            }
        }
    }
    if {$found} {
        # Now fill in the message parameters if any
        # TBD
    } else {
        set fmt "The message file or event definition for event id $rec(-eventid) from source $rec(-source) was not found. The following information was part of the event: "
        set flds [list ]
        for {set i 1} {$i <= [llength $rec(-params)]} {incr i} {
            lappend flds %$i
        }
        append fmt [join $flds ", "]
        set msg [format_message -fmtstring $fmt  \
                     -params $rec(-params) -width $opts(width)]
    }
    
    return $msg
}

# Format the category
proc twapi::eventlog_format_category {event_record args} {
    package require registry

    array set opts [parseargs args {
        width.int
        langid.int
    } -nulldefault]

    array set rec $event_record
    if {$rec(-category) == 0} {
        return ""
    }

    set regkey [_find_eventlog_regkey $rec(-source)]

    # Get the message file, if there is one
    set found 0
    if {! [catch {registry get $regkey "CategoryMessageFile"} path]} {
        # Try each file listed in turn
        foreach dll [split $path \;] {
            set dll [expand_environment_strings $dll]
            if {! [catch {
                format_message -module $dll -messageid $rec(-category) -params $rec(-params) -width $opts(width) -langid $opts(langid)
            } msg]} {
                return $msg
            }
        }
    }

    return "Category $rec(-category)"
}

#
# Utility procs
#

# Validate a handle for a mode. Always raises error if handle is invalid
# If handle valid but not for that mode, will raise error iff $raise_error
# is non-empty. Returns 1 if valid, 0 otherwise
proc twapi::_eventlog_valid_handle {hevl mode {raise_error ""}} {
    variable eventlog_handles
    if {![info exists eventlog_handles($hevl)]} {
        error "Invalid event log handle '$hevl'"
    }

    if {[string compare $eventlog_handles($hevl) $mode]} {
        if {$raise_error != ""} {
            error "Eventlog handle '$hevl' not valid for $mode"
        }
        return 0
    } else {
        return 1
    }
}

#
# Find the registry key corresponding the given event log source
proc twapi::_find_eventlog_regkey {source} {
    set topkey {HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog}
    # Get all keys under this key and look for a source under that
    foreach key [registry keys $topkey] {
        foreach srckey [registry keys "${topkey}\\$key"] {
            if {[string equal -nocase $srckey $source]} {
                return "${topkey}\\${key}\\$srckey"
            }
        }
    }

    # Default to Application - TBD
    return "${topkey}\\Application"
}
Added Binaries/Windows/twapi/mstask.tcl.










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
#
# Copyright (c) 2006 Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

# Task scheduler API

namespace eval twapi {
    variable CLSID_ITaskScheduler {{148BD52A-A2AB-11CE-B11F-00AA00530503}}
    variable CLSID_ITask          {{148BD520-A2AB-11CE-B11F-00AA00530503}}
}

#
# Return an instance of the task scheduler
proc twapi::itaskscheduler_new {args} {
    array set opts [parseargs args {
        system.arg
    } -maxleftover 0]

    # Get ITaskScheduler interface
    set its [Twapi_CoCreateInstance $twapi::CLSID_ITaskScheduler NULL 1 [name_to_iid ITaskScheduler] ITaskScheduler]
    if {![info exists opts(system)]} {
        return $its
    }
    try {
        itaskscheduler_set_target_system $its $opts(system)
    } onerror {} {
        iunknown_release $its
        # Rethrow the original error
        error $errorResult $errorInfo $errorCode
    }
    return $its
}

interp alias {} ::twapi::itaskscheduler_release {} ::twapi::iunknown_release

# Return a new task interface
proc twapi::itaskscheduler_new_itask {its taskname} {
    set iid_itask [name_to_iid ITask]
    set iunk [ITaskScheduler_NewWorkItem $its $taskname $twapi::CLSID_ITask $iid_itask]
    try {
        set itask [IUnknown_QueryInterface $iunk $iid_itask ITask]
    } finally {
        iunknown_release $iunk
    }
    return $itask
}

#
# Get an existing task
proc twapi::itaskscheduler_get_itask {its taskname} {
    set iid_itask [name_to_iid ITask]
    set iunk [ITaskScheduler_Activate $its $taskname $iid_itask]
    try {
        set itask [IUnknown_QueryInterface $iunk $iid_itask ITask]
    } finally {
        iunknown_release $iunk
    }
    return $itask
}

#
# Deletes an existing task
interp alias {} ::twapi::itaskscheduler_delete_task {} ::twapi::ITaskScheduler_Delete

#
# Check if an itask exists
proc twapi::itaskscheduler_task_exists {its taskname} {
    return [expr {[ITaskScheduler_IsOfType $its $taskname [name_to_iid ITask]] == 0 ? true : false}]
}

#
# Set the target computer for a task
interp alias {} ::twapi::itaskscheduler_set_target_system {} ::twapi::ITaskScheduler_SetTargetComputer

# Get the target computer for a task
interp alias {} ::twapi::itaskscheduler_get_target_system {} ::twapi::ITaskScheduler_GetTargetComputer

#
# Return list of tasks
proc twapi::itaskscheduler_get_tasks {its} {
    set ienum [ITaskScheduler_Enum $its]
    try {
        set result [list ]
        set more 1
        while {$more} {
            foreach {more items} [IEnumWorkItems_Next $ienum 20] break
            set result [concat $result $items]
        }
    } finally {
        iunknown_release $ienum
    }
    return $result
}

# Sets the specified properties of the ITask
proc twapi::itask_configure {itask args} {

    array set opts [parseargs args {
        application.arg
        maxruntime.int
        params.arg
        priority.arg
        workingdir.arg
        account.arg
        password.arg
        comment.arg
        creator.arg
        data.arg
        idlewait.int
        idlewaitdeadline.int
        interactive.bool
        deletewhendone.bool
        disabled.bool
        hidden.bool
        runonlyifloggedon.bool
        startonlyifidle.bool
        resumesystem.bool
        killonidleend.bool
        restartonidleresume.bool
        donstartonbatteries.bool
        killifonbatteries.bool
    } -maxleftover 0]

    if {[info exists opts(priority)]} {
        switch -exact -- $opts(priority) {
            normal      {set opts(priority) 0x00000020}
            abovenormal {set opts(priority) 0x00008000}
            belownormal {set opts(priority) 0x00004000}
            high        {set opts(priority) 0x00000080}
            realtime    {set opts(priority) 0x00000100}
            idle        {set opts(priority) 0x00000040}
            default     {error "Unknown priority '$opts(priority)'. Must be one of 'normal', 'high', 'idle' or 'realtime'"}
        }
    }

    foreach {opt fn} {
        application ITask_SetApplicationName
        maxruntime  ITask_SetMaxRunTime
        params      ITask_SetParameters
        workingdir  ITask_SetWorkingDirectory
        priority    ITask_SetPriority
        comment            IScheduledWorkItem_SetComment
        creator            IScheduledWorkItem_SetCreator
        data               IScheduledWorkItem_SetWorkItemData
        errorretrycount    IScheduledWorkItem_SetErrorRetryCount
        errorretryinterval IScheduledWorkItem_SetErrorRetryInterval
    } {
        if {[info exists opts($opt)]} {
            $fn  $itask $opts($opt)
        }
    }

    if {[info exists opts(account)]} {
        if {$opts(account) ne ""} {
            if {![info exists opts(password)]} {
                error "Option -password must be specified if -account is specified"
            }
        } else {
            # System account. Set password to NULL pointer indicated
            # by magic null pointer
            set opts(password) $::twapi::nullptr
        }
        IScheduledWorkItem_SetAccountInformation $itask $opts(account) $opts(password)
    }

    if {[info exists opts(idlewait)] || [info exists opts(idlewaitdeadline)]} {
        # If either one is not specified, get the current settings
        if {! ([info exists opts(idlewait)] &&
               [info exists opts(idlewaitdeadline)]) } {
            foreach {idle dead} [IScheduledWorkItem_GetIdleWait $itask] break
            if {![info exists opts(idlewait)]} {
                set opts(idlewait) $idle
            }
            if {![info exists opts(idlewaitdeadline)]} {
                set opts(idlewaitdeadline) $dead
            }
        }
        IScheduledWorkItem_SetIdleWait $itask $opts(idlewait) $opts(idlewaitdeadline)
    }

    # Finally figure out and set the flags if needed
    if {[info exists opts(interactive)] ||
        [info exists opts(deletewhendone)] ||
        [info exists opts(disabled)] ||
        [info exists opts(hidden)] ||
        [info exists opts(runonlyifloggedon)] ||
        [info exists opts(startonlyifidle)] ||
        [info exists opts(resumesystem)] ||
        [info exists opts(killonidleend)] ||
        [info exists opts(restartonidleresume)] ||
        [info exists opts(donstartonbatteries)] ||
        [info exists opts(killifonbatteries)]} {

        # First, get the current flags
        set flags [IScheduledWorkItem_GetFlags $itask]
        foreach {opt val} {
            interactive         0x1
            deletewhendone      0x2
            disabled            0x4
            startonlyifidle     0x10
            hidden              0x200
            runonlyifloggedon   0x2000
            resumesystem        0x1000
            killonidleend       0x20
            restartonidleresume 0x800
            donstartonbatteries 0x40
            killifonbatteries   0x80
        } {
            # Set / reset the bit if specified
            if {[info exists opts($opt)]} {
                if {$opts($opt)} {
                    setbits flags $opts($opt)
                } else {
                    resetbits flags $opts($opt)
                }
            }
        }

        # Now set the new value of flags
        IScheduledWorkItem_SetFlags $itask $flags
    }


    return
}

proc twapi::itask_get_info {itask args} {
    # Note options errorretrycount and errorretryinterval are not implemented
    # by the OS so left out
    array set opts [parseargs args {
        all
        application
        maxruntime
        params
        priority
        workingdir
        account
        comment
        creator
        data
        idlewait
        idlewaitdeadline
        interactive
        deletewhendone
        disabled
        hidden
        runonlyifloggedon
        startonlyifidle
        resumesystem
        killonidleend
        restartonidleresume
        donstartonbatteries
        killifonbatteries
        lastruntime
        nextruntime
        status
    } -maxleftover 0]

    set result [list ]
    if {$opts(all) || $opts(priority)} {
        switch -exact -- [twapi::ITask_GetPriority $itask] {
            32    { set priority normal }
            64    { set priority idle }
            128   { set priority high }
            256   { set priority realtime }
            16384 { set priority belownormal }
            32768 { set priority abovenormal }
            default { set priority unknown }
        }
        lappend result -priority $priority
    }

    foreach {opt fn} {
        application ITask_GetApplicationName
        maxruntime  ITask_GetMaxRunTime
        params      ITask_GetParameters
        workingdir  ITask_GetWorkingDirectory
        account            IScheduledWorkItem_GetAccountInformation
        comment            IScheduledWorkItem_GetComment
        creator            IScheduledWorkItem_GetCreator
        data               IScheduledWorkItem_GetWorkItemData
    } {
        if {$opts(all) || $opts($opt)} {
            lappend result -$opt [$fn  $itask]
        }
    }
    
    if {$opts(all) || $opts(lastruntime)} {
        try {
            lappend result -lastruntime [_timelist_to_timestring [IScheduledWorkItem_GetMostRecentRunTime $itask]]
        } onerror {TWAPI_WIN32 267011} {
            # Not run yet at all
            lappend result -lastruntime {}
        }
    }

    if {$opts(all) || $opts(nextruntime)} {
        try {
            lappend result -nextruntime [_timelist_to_timestring [IScheduledWorkItem_GetNextRunTime $itask]]
        } onerror {TWAPI_WIN32 267010} {
            # Task is disabled
            lappend result -nextruntime disabled
        } onerror {TWAPI_WIN32 267015} {
            # No triggers set
            lappend result -nextruntime notriggers
        } onerror {TWAPI_WIN32 267016} {
            # No triggers set
            lappend result -nextruntime oneventonly
        }
    }

    if {$opts(all) || $opts(status)} {
        set status [IScheduledWorkItem_GetStatus $itask]
        if {$status == 0x41300} {
            set status ready
        } elseif {$status == 0x41301} {
            set status running
        } elseif {$status == 0x41302} {
            set status disabled
        } elseif {$status == 0x41305} {
            set status partiallydefined
        } else {
            set status unknown
        }
        lappend result -status $status
    }


    if {$opts(idlewait) || $opts(idlewaitdeadline)} {
        foreach {idle dead} [IScheduledWorkItem_GetIdleWait $itask] break
        if {$opts(idlewait)} {
            lappend result -idlewait $idle
        }
        if {$opts(idlewaitdeadline)} {
            lappend result -idlewaitdeadline $dead
        }
    }

    # Finally figure out and set the flags if needed
    if {$opts(interactive) ||
        $opts(deletewhendone) ||
        $opts(disabled) ||
        $opts(hidden) ||
        $opts(runonlyifloggedon) ||
        $opts(startonlyifidle) ||
        $opts(resumesystem) ||
        $opts(killonidleend) ||
        $opts(restartonidleresume) ||
        $opts(donstartonbatteries) ||
        $opts(killifonbatteries)} {

        # First, get the current flags
        set flags [IScheduledWorkItem_GetFlags $itask]
        foreach {opt val} {
            interactive         0x1
            deletewhendone      0x2
            disabled            0x4
            startonlyifidle     0x10
            hidden              0x200
            runonlyifloggedon   0x2000
            resumesystem        0x1000
            killonidleend       0x20
            restartonidleresume 0x800
            donstartonbatteries 0x40
            killifonbatteries   0x80
        } {
            if {$opts($opt)} {
                lappend result $opt [expr {($flags & $val) ? true : false}]
            }
        }
    }


    return $result
}

#
# Get the runtimes for a task within an interval
proc twapi::itask_get_runtimes_within_interval {itask args} {
    array set opts [parseargs args {
        start.arg
        end.arg
        {count.int 1}
        statusvar.arg
    } -maxleftover 0]

    if {[info exists opts(start)]} {
        set start [_timestring_to_timelist $opts(start)]
    } else {
        set start [_seconds_to_timelist [clock seconds]]
    }
    if {[info exists opts(end)]} {
        set end [_timestring_to_timelist $opts(end)]
    } else {
        set end {2038 1 1 0 0 0 0}
    }
    
    set result [list ]
    if {[info exists opts(statusvar)]} {
        upvar $opts(statusvar) status
    }
    foreach {status timelist} [IScheduledWorkItem_GetRunTimes $itask $start $end $opts(count)] break

    foreach time $timelist {
        lappend result [_timelist_to_timestring $time]
    }


    return $result
}

#
# Run a task
interp alias {} ::twapi::itask_run {} ::twapi::IScheduledWorkItem_Run

#
# Terminate a task
interp alias {} ::twapi::itask_end {} ::twapi::IScheduledWorkItem_Terminate

#
# Saves the specified ITask
proc twapi::itask_save {itask} {
    set ipersist [iunknown_query_interface $itask IPersistFile]
    try {
        IPersistFile_Save $ipersist "" 1
    } finally {
        iunknown_release $ipersist
    }
    return
}

#
# Show property editor for a task
proc twapi::itask_edit_dialog {itask args} {
    array set opts [parseargs args {
        {hwin.arg 0}
    } -maxleftover 0]

    return [twapi::IScheduledWorkItem_EditWorkItem $itask $opts(hwin)]
}


#
# Create a new trigger. Returns {index interfaceptr}
interp alias {} ::twapi::itask_new_itasktrigger {} ::twapi::IScheduledWorkItem_CreateTrigger

#
# Delete a trigger
interp alias {} ::twapi::itask_delete_itasktrigger {} ::twapi::IScheduledWorkItem_DeleteTrigger

interp alias {} ::twapi::itask_release {} ::twapi::iunknown_release

#
# Get an existing trigger for the task
proc twapi::itask_get_itasktrigger {itask index} {
    return [IScheduledWorkItem_GetTrigger $itask $index]
}

#
# Get number of triggers in a task
proc twapi::itask_get_itasktrigger_count {itask} {
    return [IScheduledWorkItem_GetTriggerCount $itask]
}

#
# Get the trigger string description
interp alias {} ::twapi::twapi::itask_get_itasktrigger_string {} ::twapi::IScheduledWorkItem_GetTriggerString

#
# Get information about a trigger
proc twapi::itasktrigger_get_info {itt} {
    array set data [ITaskTrigger_GetTrigger $itt]

    set result(-begindate) "$data(wBeginYear)-$data(wBeginMonth)-$data(wBeginDay)"

    set result(-starttime) "$data(wStartHour):$data(wStartMinute)"

    if {$data(rgFlags) & 1} {
        set result(-enddate) "$data(wEndYear)-$data(wEndMonth)-$data(wEndDay)"
    } else {
        set result(-enddate) ""
    }

    set result(-duration) $data(MinutesDuration)
    set result(-interval) $data(MinutesInterval)
    if {$data(rgFlags) & 2} {
        set result(-killatdurationend) true
    } else {
        set result(-killatdurationend) false
    }

    if {$data(rgFlags) & 4} {
        set result(-disabled) true
    } else {
        set result(-disabled) false
    }

    switch -exact -- [lindex $data(type) 0] {
        0 {
            set result(-type) once
        }
        1 {
            set result(-type) daily
            set result(-period) [lindex $data(type) 1]
        }
        2 {
            set result(-type) weekly
            set result(-period) [lindex $data(type) 1]
            set result(-weekdays) [format 0x%x [lindex $data(type) 2]]
        }
        3 {
            set result(-type) monthlydate
            set result(-daysofmonth) [format 0x%x [lindex $data(type) 1]]
            set result(-months) [format 0x%x [lindex $data(type) 2]]
        }
        4 {
            set result(-type) monthlydow
            set result(-weekofmonth) [lindex {first second third fourth last} [lindex $data(type) 2]]
            set result(-weekdays) [format 0x%x [lindex $data(type) 2]]
            set result(-months) [format 0x%x [lindex $data(type) 3]]
        }
        5 {
            set result(-type) onidle
        }
        6 {
            set result(-type) atsystemstart
        }
        7 {
            set result(-type) atlogon
        }
    }
    return [array get result]
}


#
# Configure a task trigger
proc twapi::itasktrigger_configure {itt args} {
    array set opts [parseargs args {
        begindate.arg
        enddate.arg
        starttime.arg
        interval.int
        duration.int
        killatdurationend.bool
        disabled.bool
        type.arg
        weekofmonth.int
        {period.int 1}
        {weekdays.int 0x7f}
        {daysofmonth.int 0x7fffffff}
        {months.int 0xfff}
    } -maxleftover 0]


    array set data [ITaskTrigger_GetTrigger $itt]

    if {[info exists opts(begindate)]} {
        foreach {year month day} [split $opts(begindate) -] break
        # Note we trim leading zeroes else Tcl thinks its octal
        set data(wBeginYear) [scan $year %d]
        set data(wBeginMonth) [scan $month %d]
        set data(wBeginDay) [scan $day %d]
    }

    if {[info exists opts(starttime)]} {
        foreach {hour minute} [split $opts(starttime) :] break
        # Note we trim leading zeroes else Tcl thinks its octal
        set data(wStartHour) [scan $hour %d]
        set data(wStartMinute) [scan $minute %d]
    }

    if {[info exists opts(enddate)]} {
        if {$opts(enddate) ne ""} {
            setbits data(rgFlags) 1;        # Indicate end date is present
            foreach {year month day} [split $opts(enddate) -] break
            # Note we trim leading zeroes else Tcl thinks its octal
            set data(wEndYear) [scan $year %d]
            set data(wEndMonth) [scan $month %d]
            set data(wEndDay) [scan $day %d]
        } else {
            resetbits data(rgFlags) 1;  # Indicate no end date
        }
    }
        

    if {[info exists opts(duration)]} {
        set data(MinutesDuration) $opts(duration)
    }

    if {[info exists opts(interval)]} {
        set data(MinutesInterval) $opts(interval)
    }

    if {[info exists opts(killatdurationend)]} {
        if {$opts(killatdurationend)} {
            setbits data(rgFlags) 2
        } else {
            resetbits data(rgFlags) 2
        }
    }

    if {[info exists opts(disabled)]} {
        if {$opts(disabled)} {
            setbits data(rgFlags) 4
        } else {
            resetbits data(rgFlags) 4
        }
    }

    # Note the type specific options are only used if -type is specified
    if {[info exists opts(type)]} {
        switch -exact -- $opts(type) {
            once {
                set data(type) [list 0]
            }
            daily {
                set data(type) [list 1 $opts(period)]
            }
            weekly {
                set data(type) [list 2 $opts(period) $opts(weekdays)]
            }
            monthlydate {
                set data(type) [list 3 $opts(daysofmonth) $opts(months)]
            }
            monthlydow {
                set data(type) [list 4 $opts(weekofmonth) $opts(weekdays) $opts(months)]
            }
            onidle {
                set data(type) [list 5]
            }
            atsystemstart {
                set data(type) [list 6]
            }
            atlogon {
                set data(type) [list 7]
            }
        }
    }

    ITaskTrigger_SetTrigger $itt [array get data]
    return
}

interp alias {} ::twapi::itasktrigger_release {} ::twapi::iunknown_release

#
# Create a new task from scratch. Basically a wrapper around the
# corresponding itaskscheduler, itask and itasktrigger calls
proc twapi::mstask_create {taskname args} {
    
    # The options are a combination of itask_configure and
    # itasktrigger_configure
    array set opts [parseargs args {
        system.arg
        application.arg
        maxruntime.int
        params.arg
        priority.arg
        workingdir.arg
        account.arg
        password.arg
        comment.arg
        creator.arg
        data.arg
        idlewait.int
        idlewaitdeadline.int
        interactive.bool
        deletewhendone.bool
        disabled.bool
        hidden.bool
        runonlyifloggedon.bool
        startonlyifidle.bool
        resumesystem.bool
        killonidleend.bool
        restartonidleresume.bool
        donstartonbatteries.bool
        killifonbatteries.bool
        begindate.arg
        enddate.arg
        starttime.arg
        interval.int
        duration.int
        killatdurationend.bool
        type.arg
        period.int
        weekdays.int
        daysofmonth.int
        months.int
    } -maxleftover 0]

    set its [itaskscheduler_new]
    try {
        if {[info exists opts(system)]} {
            itaskscheduler_set_target_system $opts(system)
        }

        set itask [itaskscheduler_new_itask $its $taskname]
        # Construct the command line for configuring the task
        set cmd [list itask_configure $itask]
        foreach opt {
            application
            maxruntime
            params
            priority
            workingdir
            account
            password
            comment
            creator
            data
            idlewait
            idlewaitdeadline
            interactive
            deletewhendone
            disabled
            hidden
            runonlyifloggedon
            startonlyifidle
            resumesystem
            killonidleend
            restartonidleresume
            donstartonbatteries
            killifonbatteries
        } {
            if {[info exists opts($opt)]} {
                lappend cmd -$opt $opts($opt)
            }
        }        
        eval $cmd

        # Now get a trigger and configure it
        set itt [lindex [itask_new_itasktrigger $itask] 1]
        set cmd [list itasktrigger_configure $itt -disabled false]
        foreach opt {
            begindate
            enddate
            interval
            starttime
            duration
            killatdurationend
            type
            period
            weekdays
            daysofmonth
            months
        } {
            if {[info exists opts($opt)]} {
                lappend cmd -$opt $opts($opt)
            }
        }
        eval $cmd

        # Save the task
        itask_save $itask

    } finally {
        iunknown_release $its
        if {[info exists itask]} {
            iunknown_release $itask
        }
        if {[info exists $itt]} {
            iunknown_release $itt
        }
    }
    return
}

#
# Delete a task
proc twapi::mstask_delete {taskname args} {
    # The options are a combination of itask_configure and
    # itasktrigger_configure
    array set opts [parseargs args {
        system.arg
    } -maxleftover 0]
    set its [itaskscheduler_new]
    try {
        if {[info exists opts(system)]} {
            itaskscheduler_set_target_system $opts(system)
        }
        itaskscheduler_delete_task $its $taskname
    } finally {
        iunknown_release $its
    }    
    return
}
Added Binaries/Windows/twapi/network.tcl.










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
#
# Copyright (c) 2004, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

# TBD _ maybe more information is available through PDH? Perhaps even on NT?

namespace eval twapi {

    array set IfTypeTokens {
        1  other
        6  ethernet
        9  tokenring
        15 fddi
        23 ppp
        24 loopback
        28 slip
    }

    array set IfOperStatusTokens {
        0 nonoperational
        1 wanunreachable
        2 disconnected
        3 wanconnecting
        4 wanconnected
        5 operational
    }

    # Various pieces of information come from different sources. Moreover,
    # the same information may be available from multiple APIs. In addition
    # older versions of Windows may not have all the APIs. So we try
    # to first get information from older API's whenever we have a choice
    # These tables map fields to positions in the corresponding API result.
    # -1 means rerieving is not as simple as simply indexing into a list

    # GetIfEntry is available from NT4 SP4 onwards
    array set GetIfEntry_opts {
        type                2
        mtu                 3
        speed               4
        physicaladdress     5
        adminstatus         6
        operstatus          7
        laststatuschange    8
        inbytes             9
        inunicastpkts      10
        innonunicastpkts   11
        indiscards         12
        inerrors           13
        inunknownprotocols 14
        outbytes           15
        outunicastpkts     16
        outnonunicastpkts  17
        outdiscards        18
        outerrors          19
        outqlen            20
        description        21
    }
    
    # GetIpAddrTable also exists in NT4 SP4+
    array set GetIpAddrTable_opts {
        ipaddresses -1
        ifindex     -1
        reassemblysize -1 
    }

    # Win2K and up
    array set GetAdaptersInfo_opts {
        adaptername     0
        adapterdescription     1
        adapterindex    3
        dhcpenabled     5
        defaultgateway  7
        dhcpserver      8
        havewins        9
        primarywins    10
        secondarywins  11
        dhcpleasestart 12
        dhcpleaseend   13
    }

    # Win2K and up
    array set GetPerAdapterInfo_opts {
        autoconfigenabled 0
        autoconfigactive  1
        dnsservers        2
    }

    # Win2K and up
    array set GetInterfaceInfo_opts {
        ifname  -1
    }

}

#
# Get the list of local IP addresses
proc twapi::get_ip_addresses {} {
    set addrs [list ]
    foreach entry [GetIpAddrTable] {
        set addr [lindex $entry 0]
        if {[string compare $addr "0.0.0.0"]} {
            lappend addrs $addr
        }
    }
    return $addrs
}

#
# Get the list of interfaces
proc twapi::get_netif_indices {} {
    # Win2K+ only - return [lindex [get_network_info -interfaces] 1]

    # NT4 SP4+
    set indices [list ]
    foreach entry [GetIpAddrTable] {
        lappend indices [lindex $entry 1]
    }
    return $indices
}

#
# Get network related information
proc twapi::get_network_info {args} {
    # Map options into the positions in result of GetNetworkParams
    array set getnetworkparams_opts {
        hostname     0
        domain       1
        dnsservers   2
        dhcpscopeid  4
        routingenabled  5
        arpproxyenabled 6
        dnsenabled      7
    }

    array set opts [parseargs args \
                        [concat [list all ipaddresses interfaces] \
                             [array names getnetworkparams_opts]]]
    set result [list ]
    foreach opt [array names getnetworkparams_opts] {
        if {!$opts(all) && !$opts($opt)} continue
        if {![info exists netparams]} {
            set netparams [GetNetworkParams]
        }
        lappend result -$opt [lindex $netparams $getnetworkparams_opts($opt)]
    }

    if {$opts(all) || $opts(ipaddresses) || $opts(interfaces)} {
        set addrs     [list ]
        set interfaces [list ]
        foreach entry [GetIpAddrTable] {
            set addr [lindex $entry 0]
            if {[string compare $addr "0.0.0.0"]} {
                lappend addrs $addr
            }
            lappend interfaces [lindex $entry 1]
        }
        if {$opts(all) || $opts(ipaddresses)} {
            lappend result -ipaddresses $addrs
        }
        if {$opts(all) || $opts(interfaces)} {
            lappend result -interfaces $interfaces
        }
    }

    return $result
}

proc twapi::get_netif_info {interface args} {
    variable IfTypeTokens
    variable GetIfEntry_opts
    variable GetIpAddrTable_opts
    variable GetAdaptersInfo_opts
    variable GetPerAdapterInfo_opts
    variable GetInterfaceInfo_opts
    
    array set opts [parseargs args \
                        [concat [list all unknownvalue.arg] \
                             [array names GetIfEntry_opts] \
                             [array names GetIpAddrTable_opts] \
                             [array names GetAdaptersInfo_opts] \
                             [array names GetPerAdapterInfo_opts] \
                             [array names GetInterfaceInfo_opts]]]

    array set result [list ]

    # If NT4.0 SP4 or before, NONE of this is available
    # If we don't want errors, just return unknown placeholder
    if {![min_os_version 4 0 4]} {
        if {[string length $opts(unknownvalue)]} {
            foreach opt [array names opts] {
                if {$opt == "all" || $opt == "unknownvalue"} continue
                if {$opts($opt) || $opts(all)} {
                    set result(-$opt) $opts(unknownvalue)
                }
            }
            return [array get result]
        }
        # Else we will just go on and barf when a function is not available
    }

    set nif $interface
    if {![string is integer $nif]} {
        if {![min_os_version 5]} {
            error "Interfaces must be identified by integer index values on Windows NT 4.0"
        }
        set nif [GetAdapterIndex $nif]
    }

    if {$opts(all) || $opts(ifindex)} {
        # This really is only useful if $interface had been specified as a name
        set result(-ifindex) $nif
    }

    if {$opts(all) ||
        [_array_non_zero_entry opts [array names GetIfEntry_opts]]} {
        set values [GetIfEntry $nif]
        foreach opt [array names GetIfEntry_opts] {
            if {$opts(all) || $opts($opt)} {
                set result(-$opt) [lindex $values $GetIfEntry_opts($opt)]
            }
        }
    }
    
    if {$opts(all) ||
        [_array_non_zero_entry opts [array names GetIpAddrTable_opts]]} {
        # Collect all the entries, sort by index, then pick out what
        # we want. This assumes there may be multiple entries with the
        # same ifindex
        foreach entry [GetIpAddrTable] {
            foreach {addr ifindex netmask broadcast reasmsize} $entry break
            lappend ipaddresses($ifindex) [list $addr $netmask $broadcast]
            set reassemblysize($ifindex) $reasmsize
        }
        foreach opt {ipaddresses reassemblysize} {
            if {$opts(all) || $opts($opt)} {
                if {![info exists ${opt}($nif)]} {
                    error "No interface exists with index $nif"
                }
                set result(-$opt) [set ${opt}($nif)]
            }
        }
    }

    # Remaining options only available on Win2K and up
    if {![min_os_version 5]} {
        if {[string length $opts(unknownvalue)]} {
            set win2kopts [concat [array names GetAdaptersInfo_opts] \
                               [array names GetPerAdapterInfo_opts] \
                               [array names GetInterfaceInfo_opts]]
            foreach opt $win2kopts {
                if {$opts($opt) || $opts(all)} {
                    set result(-$opt) $opts(unknownvalue)
                }
            }
            return [array get result]
        }
        # Else we will just go on and barf when a function is not available
    }

    # Proceed with win2k and above
    if {$opts(all) ||
        [_array_non_zero_entry opts [array names GetAdaptersInfo_opts]]} {
        foreach entry [GetAdaptersInfo] {
            if {$nif != [lindex $entry 3]} continue; # Different interface
            foreach opt [array names GetAdaptersInfo_opts] {
                if {$opts(all) || $opts($opt)} {
                    set result(-$opt) [lindex $entry $GetAdaptersInfo_opts($opt)]
                }
            }
        }
    }

    if {$opts(all) ||
        [_array_non_zero_entry opts [array names GetPerAdapterInfo_opts]]} {
        if {$result(-type) == 24} {
            # Loopback - we have to make this info up
            set values {0 0 {}}
        } else {
            set values [GetPerAdapterInfo $nif]
        }
        foreach opt [array names GetPerAdapterInfo_opts] {
            if {$opts(all) || $opts($opt)} {
                set result(-$opt) [lindex $values $GetPerAdapterInfo_opts($opt)]
            }
        }
    }

    if {$opts(all) || $opts(ifname)} {
        array set ifnames [eval concat [GetInterfaceInfo]]
        if {$result(-type) == 24} {
            set result(-ifname) "loopback"
        } else {
            if {![info exists ifnames($nif)]} {
                error "No interface exists with index $nif"
            }
            set result(-ifname) $ifnames($nif)
        }
    }

    # Some fields need to be translated to more mnemonic names
    if {[info exists result(-type)]} {
        if {[info exists IfTypeTokens($result(-type))]} {
            set result(-type) $IfTypeTokens($result(-type))
        } else {
            set result(-type) "other"
        }
    }
    if {[info exists result(-physicaladdress)]} {
        set result(-physicaladdress) [_hwaddr_binary_to_string $result(-physicaladdress)]
    }
    foreach opt {-primarywins -secondarywins} {
        if {[info exists result($opt)]} {
            if {[string equal $result($opt) "0.0.0.0"]} {
                set result($opt) ""
            }
        }
    }
    if {[info exists result(-operstatus)] &&
        [info exists twapi::IfOperStatusTokens($result(-operstatus))]} {
        set result(-operstatus) $twapi::IfOperStatusTokens($result(-operstatus))
    }

    return [array get result]
}

#
# Get the number of network interfaces
proc twapi::get_netif_count {} {
    return [GetNumberOfInterfaces]
}

#
# Get the address->h/w address table
proc twapi::get_arp_table {args} {
    array set opts [parseargs args {
        sort
        ifindex.int
        validonly
    }]

    set arps [list ]

    foreach arp [GetIpNetTable $opts(sort)] {
        foreach {ifindex hwaddr ipaddr type} $arp break
        if {$opts(validonly) && $type == 2} continue
        if {[info exists opts(ifindex)] && $opts(ifindex) != $ifindex} continue
        # Token for enry   0     1      2      3        4
        set type [lindex {other other invalid dynamic static} $type]
        if {$type == ""} {
            set type other
        }
        lappend arps [list $ifindex [_hwaddr_binary_to_string $hwaddr] $ipaddr $type]
    }
    return $arps
}

#
# Return IP address for a hw address
proc twapi::ipaddr_to_hwaddr {ipaddr {varname ""}} {
    foreach arp [GetIpNetTable] {
        if {[lindex $arp 3] == 2} continue;       # Invalid entry type
        if {[string equal $ipaddr [lindex $arp 2]]} {
            set result [_hwaddr_binary_to_string [lindex $arp 1]]
            break
        }
    }

    # If could not get from ARP table, see if it is one of our own
    # Ignore errors
    if {![info exists result]} {
        foreach ifindex [get_netif_indices] {
            catch {
                array set netifinfo [get_netif_info $ifindex -ipaddresses -physicaladdress]
                # Search list of ipaddresses
                foreach elem $netifinfo(-ipaddresses) {
                    if {[lindex $elem 0] eq $ipaddr} {
                        set result $netifinfo(-physicaladdress)
                        break
                    }
                }
            }
            if {[info exists result]} {
                break
            }
        }
    }

    if {[info exists result]} {
        if {$varname == ""} {
            return $result
        }
        upvar $varname var
        set var $result
        return 1
    } else {
        if {$varname == ""} {
            error "Could not map IP address $ipaddr to a hardware address"
        }
        return 0
    }
}

#
# Return hw address for a IP address
proc twapi::hwaddr_to_ipaddr {hwaddr {varname ""}} {
    set hwaddr [string map {- "" : ""} $hwaddr]
    foreach arp [GetIpNetTable] {
        if {[lindex $arp 3] == 2} continue;       # Invalid entry type
        if {[string equal $hwaddr [_hwaddr_binary_to_string [lindex $arp 1] ""]]} {
            set result [lindex $arp 2]
            break
        }
    }

    # If could not get from ARP table, see if it is one of our own
    # Ignore errors
    if {![info exists result]} {
        foreach ifindex [get_netif_indices] {
            catch {
                array set netifinfo [get_netif_info $ifindex -ipaddresses -physicaladdress]
                # Search list of ipaddresses
                set ifhwaddr [string map {- ""} $netifinfo(-physicaladdress)]
                if {[string equal -nocase $hwaddr $ifhwaddr]} {
                    set result [lindex [lindex $netifinfo(-ipaddresses) 0] 0]
                    break
                }
            }
            if {[info exists result]} {
                break
            }
        }
    }

    if {[info exists result]} {
        if {$varname == ""} {
            return $result
        }
        upvar $varname var
        set var $result
        return 1
    } else {
        if {$varname == ""} {
            error "Could not map hardware address $hwaddr to an IP address"
        }
        return 0
    }
}



#
# Flush the arp table for a given interface
proc twapi::flush_arp_table {if_index} {
    FlushIpNetTable $if_index
}


#
# Return the list of TCP connections
proc twapi::get_tcp_connections {args} {
    variable tcp_statenames
    variable tcp_statevalues
    if {![info exists tcp_statevalues]} {
        array set tcp_statevalues {
            closed            1
            listen            2
            syn_sent          3
            syn_rcvd          4
            estab             5
            fin_wait1         6
            fin_wait2         7
            close_wait        8
            closing           9
            last_ack         10
            time_wait        11
            delete_tcb       12
        }
        foreach {name val} [array get tcp_statevalues] {
            set tcp_statenames($val) $name
        }
    }
    array set opts [parseargs args {
        state
        localaddr
        remoteaddr
        localport
        remoteport
        pid
        all
        matchstate.arg 
        matchlocaladdr.arg
        matchremoteaddr.arg
        matchlocalport.int
        matchremoteport.int
        matchpid.int
    } -maxleftover 0]

    if {! ($opts(state) || $opts(localaddr) || $opts(remoteaddr) || $opts(localport) || $opts(remoteport) || $opts(pid))} {
        set opts(all) 1
    }

    # Convert state to appropriate symbol if necessary
    if {[info exists opts(matchstate)]} {
        set matchstates [list ]
        foreach stateval $opts(matchstate) {
            if {[info exists tcp_statevalues($stateval)]} {
                lappend matchstates $stateval
                continue
            }
            if {[info exists tcp_statenames($stateval)]} {
                lappend matchstates $tcp_statenames($stateval)
                continue
            }
            error "Unrecognized connection state '$stateval' specified for option -matchstate"
        }
    }

    foreach opt {matchlocaladdr matchremoteaddr} {
        if {[info exists opts($opt)]} {
            # TBD - also allow DNS addresses
            # TBD - validate IP address
        }
    }

    # Get the complete list of connections
    set conns [list ]
    foreach entry [AllocateAndGetTcpExTableFromStack 0 0] {
        foreach {state localaddr localport remoteaddr remoteport pid} $entry {
            break
        }
        if {[string equal $remoteaddr 0.0.0.0]} {
            # Socket not connected. WIndows passes some random value 
            # for remote port in this case. Set it to 0
            set remoteport 0
        }
        if {[info exists opts(matchpid)]} {
            # See if this platform even returns the PID
            if {$pid == ""} {
                error "Connection process id not available on this system."
            }
            if {$pid != $opts(matchpid)} {
                continue
            }
        }
        if {[info exists opts(matchlocaladdr)] &&
            $opts(matchlocaladdr) != $localaddr} {
            continue
        }
        if {[info exists opts(matchremoteaddr)] &&
            $opts(matchremoteaddr) != $remoteaddr} {
            continue
        }
        if {[info exists opts(matchlocalport)] &&
            $opts(matchlocalport) != $localport} {
            continue
        }
        if {[info exists opts(matchremoteport)] &&
            $opts(matchremoteport) != $remoteport} {
            continue
        }
        if {[info exists tcp_statenames($state)]} {
            set state $tcp_statenames($state)
        }
        if {[info exists matchstates] && [lsearch -exact $matchstates $state] < 0} {
            continue
        }

        # OK, now we have matched. Include specified fields in the result
        set conn [list ]
        foreach opt {localaddr localport remoteaddr remoteport state pid} {
            if {$opts(all) || $opts($opt)} {
                lappend conn -$opt [set $opt]
            }
        }
        lappend conns $conn
    }
    return $conns
}


#
# Return the list of UDP connections
proc twapi::get_udp_connections {args} {
    array set opts [parseargs args {
        localaddr
        localport
        pid
        all
        matchlocaladdr.arg
        matchlocalport.int
        matchpid.int
    } -maxleftover 0]

    if {! ($opts(localaddr) || $opts(localport) || $opts(pid))} {
        set opts(all) 1
    }

    if {[info exists opts(matchlocaladdr)]} {
        # TBD - also allow DNS addresses
        # TBD - validate IP address
    }

    # Get the complete list of connections
    set conns [list ]
    foreach entry [AllocateAndGetUdpExTableFromStack 0 0] {
        foreach {localaddr localport pid} $entry {
            break
        }
        if {[info exists opts(matchpid)]} {
            # See if this platform even returns the PID
            if {$pid == ""} {
                error "Connection process id not available on this system."
            }
            if {$pid != $opts(matchpid)} {
                continue
            }
        }
        if {[info exists opts(matchlocaladdr)] &&
            $opts(matchlocaladdr) != $localaddr} {
            continue
        }
        if {[info exists opts(matchlocalport)] &&
            $opts(matchlocalport) != $localport} {
            continue
        }

        # OK, now we have matched. Include specified fields in the result
        set conn [list ]
        foreach opt {localaddr localport pid} {
            if {$opts(all) || $opts($opt)} {
                lappend conn -$opt [set $opt]
            }
        }
        lappend conns $conn
    }
    return $conns
}

#
# Terminates a TCP connection. Does not generate an error if connection
# does not exist
proc twapi::terminate_tcp_connections {args} {
    array set opts [parseargs args {
        matchstate.int
        matchlocaladdr.arg
        matchremoteaddr.arg
        matchlocalport.int
        matchremoteport.int
        matchpid.int
    } -maxleftover 0]    

    # TBD - ignore 'no such connection' errors

    # If local and remote endpoints fully specified, just directly call
    # SetTcpEntry. Note pid must NOT be specified since we must then
    # fall through and check for that pid
    if {[info exists opts(matchlocaladdr)] && [info exists opts(matchlocalport)] &&
        [info exists opts(matchremoteaddr)] && [info exists opts(matchremoteport)] &&
        ! [info exists opts(matchpid)]} {
        # 12 is "delete" code
        SetTcpEntry [list 12 $opts(matchlocaladdr) $opts(matchlocalport) $opts(matchremoteaddr) $opts(matchremoteport)]
        return
    }

    # Get connection list and go through matching on each
    foreach conn [eval get_tcp_connections [get_array_as_options opts]] {
        array set aconn $conn
        # TBD - should we handle integer values of opts(state) ?
        if {[info exists opts(matchstate)] &&
            $opts(matchstate) != $aconn(-state)} {
            continue
        }
        if {[info exists opts(matchlocaladdr)] &&
            $opts(matchlocaladdr) != $aconn(-localaddr)} {
            continue
        }
        if {[info exists opts(matchlocalport)] &&
            $opts(matchlocalport) != $aconn(-localport)} {
            continue
        }
        if {[info exists opts(matchremoteaddr)] &&
            $opts(matchremoteaddr) != $aconn(-remoteaddr)} {
            continue
        }
        if {[info exists opts(remoteport)] &&
            $opts(matchremoteport) != $aconn(-remoteport)} {
            continue
        }
        if {[info exists opts(matchpid)] &&
            $opts(matchpid) != $aconn(-pid)} {
            continue
        }
        # Matching conditions fulfilled
        # 12 is "delete" code
        SetTcpEntry [list 12 $aconn(-localaddr) $aconn(-localport) $aconn(-remoteaddr) $aconn(-remoteport)]
    }
}


#
# Flush cache of host names and ports.
proc twapi::flush_network_name_cache {} {
    array unset ::twapi::port2name
    array unset ::twapi::addr2name
    array unset ::twapi::name2port
    array unset ::twapi::name2addr
}

#
# IP addr -> hostname
proc twapi::address_to_hostname {addr args} {
    variable addr2name

    array set opts [parseargs args {
        flushcache
        async.arg
    } -maxleftover 0]

    # Note as a special case, we treat 0.0.0.0 explicitly since
    # win32 getnameinfo translates this to the local host name which
    # is completely bogus.
    if {$addr eq "0.0.0.0"} {
        set addr2name($addr) $addr
        set opts(flushcache) 0
        # Now just fall thru to deal with async option etc.
    }


    if {[info exists addr2name($addr)]} {
        if {$opts(flushcache)} {
            unset addr2name($addr)
        } else {
            if {[info exists opts(async)]} {
                after idle [list after 0 $opts(async) [list $addr success $addr2name($addr)]]
                return ""
            } else {
                return $addr2name($addr)
            }
        }
    }

    # If async option, we will call back our internal function which
    # will update the cache and then invoke the caller's script
    if {[info exists opts(async)]} {
        Twapi_ResolveAddressAsync $addr "::twapi::_ResolveAddress_handler [list $opts(async)]"
        return ""
    }

    # Synchronous
    set name [lindex [twapi::getnameinfo [list $addr] 8] 0]
    if {$name eq $addr} {
        # Could not resolve.
        set name ""
    }

    set addr2name($addr) $name
    return $name
}

#
# host name -> IP addresses
proc twapi::hostname_to_address {name args} {
    variable name2addr

    set name [string tolower $name]

    array set opts [parseargs args {
        flushcache
        async.arg
    } -maxleftover 0]

    if {[info exists name2addr($name)]} {
        if {$opts(flushcache)} {
            unset name2addr($name)
        } else {
            if {[info exists opts(async)]} {
                after idle [list after 0 $opts(async) [list $name success $name2addr($name)]]
                return ""
            } else {
                return $name2addr($name)
            }
        }
    }

    # Do not have resolved name

    # If async option, we will call back our internal function which
    # will update the cache and then invoke the caller's script
    if {[info exists opts(async)]} {
        Twapi_ResolveHostnameAsync $name "::twapi::_ResolveHostname_handler [list $opts(async)]"
        return ""
    }

    # Resolve address synchronously
    set addrs [list ]
    catch {
        foreach endpt [twapi::getaddrinfo $name 0 0] {
            foreach {addr port} $endpt break
            lappend addrs $addr
        }
    }

    set name2addr($name) $addrs
    return $addrs
}

#
# Look up a port name
proc twapi::port_to_service {port} {
    variable port2name

    if {[info exists port2name($port)]} {
        return $port2name($port)
    }

    try {
        set name [lindex [twapi::getnameinfo [list 0.0.0.0 $port] 2] 1]
    } onerror {TWAPI_WIN32 11004} {
        # Lookup failed
        set name ""
    }

    # If we did not get a name back, check for some well known names
    # that windows does not translate. Note some of these are names
    # that windows does translate in the reverse direction!
    if {$name eq ""} {
        foreach {p n} {
            123 ntp
            137 netbios-ns
            138 netbios-dgm
            500 isakmp
            1900 ssdp
            4500 ipsec-nat-t
        } {
            if {$port == $p} {
                set name $n
                break
            }
        }
    }
        
    set port2name($port) $name
    return $name
}


#
# Port name -> number
proc twapi::service_to_port {name} {
    variable name2port

    # TBD - add option for specifying protocol
    set protocol 0

    if {[info exists name2port($name)]} {
        return $name2port($name)
    }

    if {[string is integer $name]} {
        return $name
    }

    if {[catch {
        # Return the first port
        set port [lindex [lindex [twapi::getaddrinfo "" $name $protocol] 0] 1]
    }]} {
        set port ""
    }
    set name2port($name) $port
    return $port
}


################################################################
# Utility procs

# Convert binary hardware address to string format
proc twapi::_hwaddr_binary_to_string {b {joiner -}} {
    if {[binary scan $b H* str]} {
        set s ""
        foreach {x y} [split $str ""] {
            lappend s $x$y
        }
        return [join $s $joiner]
    } else {
        error "Could not convert binary hardware address"
    }
}

# Callback for address resolution
proc twapi::_ResolveAddress_handler {script addr status hostname} {
    # Before invoking the callback, store result if available
    if {$status eq "success"} {
        set ::twapi::addr2name($addr) $hostname
    }
    eval $script [list $addr $status $hostname]
    return
}

# Callback for hostname resolution
proc twapi::_ResolveHostname_handler {script name status addrs} {
    # Before invoking the callback, store result if available
    if {$status eq "success"} {
        set ::twapi::name2addr($name) $addrs
    } elseif {$addrs == 11001} {
        # For compatibility with the sync version and address resolution,
        # We return an success if empty list if in fact the failure was
        # that no name->address mapping exists
        set status success
        set addrs [list ]
    }

    eval $script [list $name $status $addrs]
    return
}
Added Binaries/Windows/twapi/nls.tcl.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
#
# Copyright (c) 2003, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

namespace eval twapi {
}


#
# Get the default system/user lcid/langid 
proc twapi::get_user_default_lcid {} {return [GetUserDefaultLCID]}
proc twapi::get_system_default_lcid {} {return [GetSystemDefaultLCID]}
proc twapi::get_user_langid {} {return [GetUserDefaultLangID]}
# Compatibility alias
interp alias {} twapi::get_user_default_langid {} twapi::get_user_langid
proc twapi::get_system_langid {} {return [GetSystemDefaultLangID]}
# Compatibility alias
interp alias {} twapi::get_system_default_langid {} twapi::get_system_langid
proc twapi::get_user_ui_langid {} {
    # GetUserDefaultUILanguage does not exist on NT 4
    try {
        return [GetUserDefaultUILanguage]
    } onerror {TWAPI_WIN32 127} {
        return [get_user_langid]
    }
}
proc twapi::get_system_ui_langid {} {
    # GetSystemDefaultUILanguage does not exist on NT 4
    try {
        return [GetSystemDefaultUILanguage]
    } onerror {TWAPI_WIN32 127} {
        return [get_system_langid]
    }
}

proc twapi::get_lcid {} {
    return [GetThreadLocale]
}

#
# Format a number
proc twapi::format_number {number lcid args} {

    set number [_verify_number_format $number]

    set lcid [_map_default_lcid_token $lcid]

    # If no options specified, format according to the passed locale
    if {[llength $args] == 0} {
        return [GetNumberFormat 1 $lcid 0 $number 0 0 0 . "" 0]
    }

    array set opts [parseargs args {
        idigits.int
        ilzero.bool
        sgrouping.int
        sdecimal.arg
        sthousand.arg
        inegnumber.int
    }]

    # Check the locale for unspecified options
    foreach opt {idigits ilzero sgrouping sdecimal sthousand inegnumber} {
        if {![info exists opts($opt)]} {
            set opts($opt) [lindex [get_locale_info $lcid -$opt] 1]
        }
    }
        
    # If number of decimals is -1, see how many decimal places
    # in passed string
    if {$opts(idigits) == -1} {
        foreach {whole frac} [split $number .] break
        set opts(idigits) [string length $frac]
    }

    # Convert Locale format for grouping to integer calue
    if {![string is integer $opts(sgrouping)]} {
        # Format assumed to be of the form "N;M;....;0"
        set grouping 0
        foreach n [split $opts(sgrouping) {;}] {
            if {$n == 0} break
            set grouping [expr {$n + 10*$grouping}]
        }
        set opts(sgrouping) $grouping
    }

    set flags 0
    if {[info exists opts(nouseroverride)] && $opts(nouseroverride)} {
        setbits flags 0x80000000
    }
    return [GetNumberFormat 0 $lcid $flags $number $opts(idigits) \
                $opts(ilzero) $opts(sgrouping) $opts(sdecimal) \
                $opts(sthousand) $opts(inegnumber)]
}


#
# Format currency
proc twapi::format_currency {number lcid args} {

    set number [_verify_number_format $number]

    # Get semi-canonical form (get rid of preceding "+" etc.)
    # Also verifies number syntax
    set number [expr {$number+0}];

    set lcid [_map_default_lcid_token $lcid]

    # If no options specified, format according to the passed locale
    if {[llength $args] == 0} {
        return [GetCurrencyFormat 1 $lcid 0 $number 0 0 0 . "" 0 0 ""]
    }

    array set opts [parseargs args {
        idigits.int
        ilzero.bool
        sgrouping.int
        sdecimal.arg
        sthousand.arg
        inegcurr.int
        icurrency.int
        scurrency.arg
    }]

    # Check the locale for unspecified options
    foreach opt {idigits ilzero sgrouping sdecimal sthousand inegcurr icurrency scurrency} {
        if {![info exists opts($opt)]} {
            set opts($opt) [lindex [get_locale_info $lcid -$opt] 1]
        }
    }

    # If number of decimals is -1, see how many decimal places
    # in passed string
    if {$opts(idigits) == -1} {
        foreach {whole frac} [split $number .] break
        set opts(idigits) [string length $frac]
    }

    # Convert Locale format for grouping to integer calue
    if {![string is integer $opts(sgrouping)]} {
        # Format assumed to be of the form "N;M;....;0"
        set grouping 0
        foreach n [split $opts(sgrouping) {;}] {
            if {$n == 0} break
            set grouping [expr {$n + 10*$grouping}]
        }
        set opts(sgrouping) $grouping
    }

    set flags 0
    if {[info exists opts(nouseroverride)] && $opts(nouseroverride)} {
        setbits flags 0x80000000
    }

    return [GetCurrencyFormat 0 $lcid $flags $number $opts(idigits) \
                $opts(ilzero) $opts(sgrouping) $opts(sdecimal) \
                $opts(sthousand) $opts(inegcurr) \
                $opts(icurrency) $opts(scurrency)]
}


#
# Get various info about a locale
proc twapi::get_locale_info {lcid args} {

    set lcid [_map_default_lcid_token $lcid]

    variable locale_info_class_map
    if {![info exists locale_info_class_map]} {
        array set locale_info_class_map {
            ilanguage              0x00000001
            slanguage              0x00000002
            senglanguage           0x00001001
            sabbrevlangname        0x00000003
            snativelangname        0x00000004
            icountry               0x00000005
            scountry               0x00000006
            sengcountry            0x00001002
            sabbrevctryname        0x00000007
            snativectryname        0x00000008
            idefaultlanguage       0x00000009
            idefaultcountry        0x0000000A
            idefaultcodepage       0x0000000B
            idefaultansicodepage   0x00001004
            idefaultmaccodepage    0x00001011
            slist                  0x0000000C
            imeasure               0x0000000D
            sdecimal               0x0000000E
            sthousand              0x0000000F
            sgrouping              0x00000010
            idigits                0x00000011
            ilzero                 0x00000012
            inegnumber             0x00001010
            snativedigits          0x00000013
            scurrency              0x00000014
            sintlsymbol            0x00000015
            smondecimalsep         0x00000016
            smonthousandsep        0x00000017
            smongrouping           0x00000018
            icurrdigits            0x00000019
            iintlcurrdigits        0x0000001A
            icurrency              0x0000001B
            inegcurr               0x0000001C
            sdate                  0x0000001D
            stime                  0x0000001E
            sshortdate             0x0000001F
            slongdate              0x00000020
            stimeformat            0x00001003
            idate                  0x00000021
            ildate                 0x00000022
            itime                  0x00000023
            itimemarkposn          0x00001005
            icentury               0x00000024
            itlzero                0x00000025
            idaylzero              0x00000026
            imonlzero              0x00000027
            s1159                  0x00000028
            s2359                  0x00000029
            icalendartype          0x00001009
            ioptionalcalendar      0x0000100B
            ifirstdayofweek        0x0000100C
            ifirstweekofyear       0x0000100D
            sdayname1              0x0000002A
            sdayname2              0x0000002B
            sdayname3              0x0000002C
            sdayname4              0x0000002D
            sdayname5              0x0000002E
            sdayname6              0x0000002F
            sdayname7              0x00000030
            sabbrevdayname1        0x00000031
            sabbrevdayname2        0x00000032
            sabbrevdayname3        0x00000033
            sabbrevdayname4        0x00000034
            sabbrevdayname5        0x00000035
            sabbrevdayname6        0x00000036
            sabbrevdayname7        0x00000037
            smonthname1            0x00000038
            smonthname2            0x00000039
            smonthname3            0x0000003A
            smonthname4            0x0000003B
            smonthname5            0x0000003C
            smonthname6            0x0000003D
            smonthname7            0x0000003E
            smonthname8            0x0000003F
            smonthname9            0x00000040
            smonthname10           0x00000041
            smonthname11           0x00000042
            smonthname12           0x00000043
            smonthname13           0x0000100E
            sabbrevmonthname1      0x00000044
            sabbrevmonthname2      0x00000045
            sabbrevmonthname3      0x00000046
            sabbrevmonthname4      0x00000047
            sabbrevmonthname5      0x00000048
            sabbrevmonthname6      0x00000049
            sabbrevmonthname7      0x0000004A
            sabbrevmonthname8      0x0000004B
            sabbrevmonthname9      0x0000004C
            sabbrevmonthname10     0x0000004D
            sabbrevmonthname11     0x0000004E
            sabbrevmonthname12     0x0000004F
            sabbrevmonthname13     0x0000100F
            spositivesign          0x00000050
            snegativesign          0x00000051
            ipossignposn           0x00000052
            inegsignposn           0x00000053
            ipossymprecedes        0x00000054
            ipossepbyspace         0x00000055
            inegsymprecedes        0x00000056
            inegsepbyspace         0x00000057
            fontsignature          0x00000058
            siso639langname        0x00000059
            siso3166ctryname       0x0000005A
            idefaultebcdiccodepage 0x00001012
            ipapersize             0x0000100A
            sengcurrname           0x00001007
            snativecurrname        0x00001008
            syearmonth             0x00001006
            ssortname              0x00001013
            idigitsubstitution     0x00001014
        }
    }

    array set opts [parseargs args [array names locale_info_class_map]]

    set result [list ]
    foreach opt [array names opts] {
        if {$opts($opt)} {
            lappend result -$opt [GetLocaleInfo $lcid $locale_info_class_map($opt)]
        }
    }
    return $result
}


proc twapi::map_code_page_to_name {cp} {
    variable code_page_names
    if {![info exists code_page_names]} {
        array set code_page_names {
            0   "System ANSI default"
            1   "System OEM default"
            37 "IBM EBCDIC - U.S./Canada"
            437 "OEM - United States"
            500 "IBM EBCDIC - International"
            708 "Arabic - ASMO 708"
            709 "Arabic - ASMO 449+, BCON V4"
            710 "Arabic - Transparent Arabic"
            720 "Arabic - Transparent ASMO"
            737 "OEM - Greek (formerly 437G)"
            775 "OEM - Baltic"
            850 "OEM - Multilingual Latin I"
            852 "OEM - Latin II"
            855 "OEM - Cyrillic (primarily Russian)"
            857 "OEM - Turkish"
            858 "OEM - Multlingual Latin I + Euro symbol"
            860 "OEM - Portuguese"
            861 "OEM - Icelandic"
            862 "OEM - Hebrew"
            863 "OEM - Canadian-French"
            864 "OEM - Arabic"
            865 "OEM - Nordic"
            866 "OEM - Russian"
            869 "OEM - Modern Greek"
            870 "IBM EBCDIC - Multilingual/ROECE (Latin-2)"
            874 "ANSI/OEM - Thai (same as 28605, ISO 8859-15)"
            875 "IBM EBCDIC - Modern Greek"
            932 "ANSI/OEM - Japanese, Shift-JIS"
            936 "ANSI/OEM - Simplified Chinese (PRC, Singapore)"
            949 "ANSI/OEM - Korean (Unified Hangeul Code)"
            950 "ANSI/OEM - Traditional Chinese (Taiwan; Hong Kong SAR, PRC)"
            1026 "IBM EBCDIC - Turkish (Latin-5)"
            1047 "IBM EBCDIC - Latin 1/Open System"
            1140 "IBM EBCDIC - U.S./Canada (037 + Euro symbol)"
            1141 "IBM EBCDIC - Germany (20273 + Euro symbol)"
            1142 "IBM EBCDIC - Denmark/Norway (20277 + Euro symbol)"
            1143 "IBM EBCDIC - Finland/Sweden (20278 + Euro symbol)"
            1144 "IBM EBCDIC - Italy (20280 + Euro symbol)"
            1145 "IBM EBCDIC - Latin America/Spain (20284 + Euro symbol)"
            1146 "IBM EBCDIC - United Kingdom (20285 + Euro symbol)"
            1147 "IBM EBCDIC - France (20297 + Euro symbol)"
            1148 "IBM EBCDIC - International (500 + Euro symbol)"
            1149 "IBM EBCDIC - Icelandic (20871 + Euro symbol)"
            1200 "Unicode UCS-2 Little-Endian (BMP of ISO 10646)"
            1201 "Unicode UCS-2 Big-Endian"
            1250 "ANSI - Central European"
            1251 "ANSI - Cyrillic"
            1252 "ANSI - Latin I"
            1253 "ANSI - Greek"
            1254 "ANSI - Turkish"
            1255 "ANSI - Hebrew"
            1256 "ANSI - Arabic"
            1257 "ANSI - Baltic"
            1258 "ANSI/OEM - Vietnamese"
            1361 "Korean (Johab)"
            10000 "MAC - Roman"
            10001 "MAC - Japanese"
            10002 "MAC - Traditional Chinese (Big5)"
            10003 "MAC - Korean"
            10004 "MAC - Arabic"
            10005 "MAC - Hebrew"
            10006 "MAC - Greek I"
            10007 "MAC - Cyrillic"
            10008 "MAC - Simplified Chinese (GB 2312)"
            10010 "MAC - Romania"
            10017 "MAC - Ukraine"
            10021 "MAC - Thai"
            10029 "MAC - Latin II"
            10079 "MAC - Icelandic"
            10081 "MAC - Turkish"
            10082 "MAC - Croatia"
            12000 "Unicode UCS-4 Little-Endian"
            12001 "Unicode UCS-4 Big-Endian"
            20000 "CNS - Taiwan"
            20001 "TCA - Taiwan"
            20002 "Eten - Taiwan"
            20003 "IBM5550 - Taiwan"
            20004 "TeleText - Taiwan"
            20005 "Wang - Taiwan"
            20105 "IA5 IRV International Alphabet No. 5 (7-bit)"
            20106 "IA5 German (7-bit)"
            20107 "IA5 Swedish (7-bit)"
            20108 "IA5 Norwegian (7-bit)"
            20127 "US-ASCII (7-bit)"
            20261 "T.61"
            20269 "ISO 6937 Non-Spacing Accent"
            20273 "IBM EBCDIC - Germany"
            20277 "IBM EBCDIC - Denmark/Norway"
            20278 "IBM EBCDIC - Finland/Sweden"
            20280 "IBM EBCDIC - Italy"
            20284 "IBM EBCDIC - Latin America/Spain"
            20285 "IBM EBCDIC - United Kingdom"
            20290 "IBM EBCDIC - Japanese Katakana Extended"
            20297 "IBM EBCDIC - France"
            20420 "IBM EBCDIC - Arabic"
            20423 "IBM EBCDIC - Greek"
            20424 "IBM EBCDIC - Hebrew"
            20833 "IBM EBCDIC - Korean Extended"
            20838 "IBM EBCDIC - Thai"
            20866 "Russian - KOI8-R"
            20871 "IBM EBCDIC - Icelandic"
            20880 "IBM EBCDIC - Cyrillic (Russian)"
            20905 "IBM EBCDIC - Turkish"
            20924 "IBM EBCDIC - Latin-1/Open System (1047 + Euro symbol)"
            20932 "JIS X 0208-1990 & 0121-1990"
            20936 "Simplified Chinese (GB2312)"
            21025 "IBM EBCDIC - Cyrillic (Serbian, Bulgarian)"
            21027 "Extended Alpha Lowercase"
            21866 "Ukrainian (KOI8-U)"
            28591 "ISO 8859-1 Latin I"
            28592 "ISO 8859-2 Central Europe"
            28593 "ISO 8859-3 Latin 3"
            28594 "ISO 8859-4 Baltic"
            28595 "ISO 8859-5 Cyrillic"
            28596 "ISO 8859-6 Arabic"
            28597 "ISO 8859-7 Greek"
            28598 "ISO 8859-8 Hebrew"
            28599 "ISO 8859-9 Latin 5"
            28605 "ISO 8859-15 Latin 9"
            29001 "Europa 3"
            38598 "ISO 8859-8 Hebrew"
            50220 "ISO 2022 Japanese with no halfwidth Katakana"
            50221 "ISO 2022 Japanese with halfwidth Katakana"
            50222 "ISO 2022 Japanese JIS X 0201-1989"
            50225 "ISO 2022 Korean"
            50227 "ISO 2022 Simplified Chinese"
            50229 "ISO 2022 Traditional Chinese"
            50930 "Japanese (Katakana) Extended"
            50931 "US/Canada and Japanese"
            50933 "Korean Extended and Korean"
            50935 "Simplified Chinese Extended and Simplified Chinese"
            50936 "Simplified Chinese"
            50937 "US/Canada and Traditional Chinese"
            50939 "Japanese (Latin) Extended and Japanese"
            51932 "EUC - Japanese"
            51936 "EUC - Simplified Chinese"
            51949 "EUC - Korean"
            51950 "EUC - Traditional Chinese"
            52936 "HZ-GB2312 Simplified Chinese"
            54936 "Windows XP: GB18030 Simplified Chinese (4 Byte)"
            57002 "ISCII Devanagari"
            57003 "ISCII Bengali"
            57004 "ISCII Tamil"
            57005 "ISCII Telugu"
            57006 "ISCII Assamese"
            57007 "ISCII Oriya"
            57008 "ISCII Kannada"
            57009 "ISCII Malayalam"
            57010 "ISCII Gujarati"
            57011 "ISCII Punjabi"
            65000 "Unicode UTF-7"
            65001 "Unicode UTF-8"
        }
    }
    set cp [expr {0+$cp}]
    if {[info exists code_page_names($cp)]} {
        return $code_page_names($cp)
    } else {
        return "Code page $cp"
    }
}

#
# Get the name of a language
proc twapi::map_langid_to_name {langid} {
    return [VerLanguageName $langid]
}

#
# Extract language and sublanguage values
proc twapi::extract_primary_langid {langid} {
    return [expr {$langid & 0x3ff}]
}
proc twapi::extract_sublanguage_langid {langid} {
    return [expr {($langid >> 10) & 0x3f}]
}

#
# Utility functions

proc twapi::_map_default_lcid_token {lcid} {
    if {$lcid == "systemdefault"} {
        return 2048
    } elseif {$lcid == "userdefault"} {
        return 1024
    }
    return $lcid
}

proc twapi::_verify_number_format {n} {
    set n [string trimleft $n 0]
    if {[regexp {^[+-]?[[:digit:]]*(\.)?[[:digit:]]*$} $n]} {
        return $n
    } else {
        error "Invalid numeric format. Must be of a sequence of digits with an optional decimal point and leading plus/minus sign"
    }
}


Added Binaries/Windows/twapi/osinfo.tcl.


































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
#
# Copyright (c) 2003-2007, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

#package require twapi

namespace eval twapi {
}

#
# Returns an keyed list with the following elements:
#   os_major_version
#   os_minor_version
#   os_build_number
#   platform - currently always NT
#   sp_major_version
#   sp_minor_version
#   suites - one or more from backoffice, blade, datacenter, enterprise, 
#            smallbusiness, smallbusiness_restricted, terminal, personal
#   system_type - workstation, server
proc twapi::get_os_info {} {
    variable windefs

    # Allocate block to hold extended information
    set vers_info [new_OSVERSIONINFOEXW]

    # First try getting extended information and if that fails, try
    # the older form
    set info_sz             276
    set extended_info_sz    284
    set have_extended_info  1
    $vers_info configure -dwOSVersionInfoSize $extended_info_sz
    if {[catch {GetVersionEx $vers_info}]} {
        $vers_info configure -dwOSVersionInfoSize $info_sz
        GetVersionEx $vers_info
        set have_extended_info 0
    }

    set osinfo(os_major_version) [$vers_info cget -dwMajorVersion]
    set osinfo(os_minor_version) [$vers_info cget -dwMinorVersion]
    set osinfo(os_build_number)  [$vers_info cget -dwBuildNumber]
    set osinfo(platform)         "NT"
    
    if {$have_extended_info} {
        set osinfo(sp_major_version) [$vers_info cget -wServicePackMajor]
        set osinfo(sp_minor_version) [$vers_info cget -wServicePackMinor]

        set osinfo(suites) [list ]
        set suites [$vers_info cget -wSuiteMask]
        foreach suite {
            backoffice blade datacenter enterprise smallbusiness
            smallbusiness_restricted terminal personal
        } {
            set def "VER_SUITE_[string toupper $suite]"
            if {$suites & $windefs($def)} {
                lappend osinfo(suites) $suite
            }
        }
        
        set system_type [$vers_info cget -wProductType]
        if {$system_type == $windefs(VER_NT_WORKSTATION)} {
            set osinfo(system_type) "workstation"
        } elseif {$system_type == $windefs(VER_NT_SERVER)} {
            set osinfo(system_type) "server"
        } elseif {$system_type == $windefs(VER_NT_DOMAIN_CONTROLLER)} {
            set osinfo(system_type) "domain_controller"
        } else {
            set osinfo(system_type) "unknown"
        }

    } else {
        # Older OS versions. Only have basic info. Figure out the rest
        # based on registry settings
        package require registry
        
        set osinfo(suites) [list ]
        set product_type [registry get "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions" "ProductType"]
        switch -exact -- [string toupper $product_type] {
            "WINNT" {
                set osinfo(system_type) "workstation"
            }
            "LANMANNT" {
                set osinfo(system_type) "server"
            }
            "SERVERNT" {
                set osinfo(system_type) "server"
                lappend osinfo(suites)  "enterprise"
            }
        }

        # Figure out service pack
        set sp_text [registry get "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" "CSDVersion"]
        set sp_major 0
        regexp -nocase {Service Pack ([0-9]+)} $sp_text dummy sp_major
        set osinfo(sp_major_version) $sp_major
        set osinfo(sp_minor_version) 0; # Always 0
        
        # Terminal server?
        if {[catch {
            registry get "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ProductOptions" "ProductSuite"
        } ts] == 0} {
            if {[string equal -nocase $ts "Terminal Server"]} {
                lappend osinfo(suites) "terminal"
            }
        }
    }

    return [array get osinfo]
}

#
# Return a text string describing the OS version and options
# If specified, osinfo should be a keyed list containing 
# data returned by get_os_info
#
proc twapi::get_os_description {} {

    array set osinfo [get_os_info]

    # Assume not terminal server
    set tserver ""

    # Version
    set osversion "$osinfo(os_major_version).$osinfo(os_minor_version)"

    # Base OS name
    if {$osinfo(os_major_version) < 5} {
        set osname "Windows NT"
        if {[string equal $osinfo(system_type) "workstation"]} {
            set systype "Workstation"
        } else {
            if {[lsearch -exact $osinfo(suites) "terminal"] >= 0} {
                set systype "Terminal Server Edition"
            } elseif {[lsearch -exact $osinfo(suites) "enterprise"] >= 0} {
                set systype "Advanced Server"
            } else {
                set systype "Server"
            }
        }
    } else {
        switch -exact -- $osversion {
            "5.0" {
                set osname "Windows 2000"
                if {[string equal $osinfo(system_type) "workstation"]} {
                    set systype "Professional"
                } else {
                    if {[lsearch -exact $osinfo(suites) "datacenter"] >= 0} {
                        set systype "Datacenter Server"
                    } elseif {[lsearch -exact $osinfo(suites) "enterprise"] >= 0} {
                        set systype "Advanced Server"
                    } else {
                        set systype "Server"
                    }
                }
            }
            "5.1" {
                set osname "Windows XP"
                if {[lsearch -exact $osinfo(suites) "personal"] >= 0} {
                    set systype "Home Edition"
                } else {
                    set systype "Professional"
                }
            }
            "5.2" {
                set osname "Windows Server 2003"
                if {[string equal $osinfo(system_type) "workstation"]} {
                    set systype "Professional"
                } else {
                    if {[lsearch -exact $osinfo(suites) "datacenter"] >= 0} {
                        set systype "Datacenter Edition"
                    } elseif {[lsearch -exact $osinfo(suites) "enterprise"] >= 0} {
                        set systype "Enterprise Edition"
                    } elseif {[lsearch -exact $osinfo(suites) "blade"] >= 0} {
                        set systype "Web Edition"
                    } else {
                        set systype "Standard Edition"
                    }
                }
            }
            default {
                # Future release - can't really name, just make something up
                set osname "Windows"
                if {[string equal $osinfo(system_type) "workstation"]} {
                    set systype "Professional"
                } else {
                    set systype "Server"
                }
            }
        }
        if {[lsearch -exact $osinfo(suites) "terminal"] >= 0} {
            set tserver " with Terminal Services"
        }
    }

    # Service pack
    if {$osinfo(sp_major_version) != 0} {
        set spver " Service Pack $osinfo(sp_major_version)"
    } else {
        set spver ""
    }
    
    return "$osname $systype ${osversion} (Build $osinfo(os_build_number))${spver}${tserver}"
}

#
# Return major minor servicepack as a quad list
proc twapi::get_os_version {} {
    if {[info exists ::twapi::_osversion]} {
        return $::twapi::_osversion
    }

    array set osinfo [get_os_info]
    set ::twapi::_osversion \
        [list $osinfo(os_major_version) $osinfo(os_minor_version) \
             $osinfo(sp_major_version) $osinfo(sp_minor_version)]
    return $::twapi::_osversion
}

# Returns true if the OS version is at least $major.$minor.$sp
proc twapi::min_os_version {major {minor 0} {spmajor 0} {spminor 0}} {
    foreach {osmajor osminor osspmajor osspminor} [twapi::get_os_version] {break}

    if {$osmajor > $major} {return 1}
    if {$osmajor < $major} {return 0}
    if {$osminor > $minor} {return 1}
    if {$osminor < $minor} {return 0}
    if {$osspmajor > $spmajor} {return 1}
    if {$osspmajor < $spmajor} {return 0}
    if {$osspminor > $spminor} {return 1}
    if {$osspminor < $spminor} {return 0}

    # Same version, ok
    return 1
}

#
# Returns proc information
#  $processor should be processor number or "" for "total"
proc twapi::get_processor_info {processor args} {

    if {![info exists ::twapi::get_processor_info_base_opts]} {
        array set ::twapi::get_processor_info_base_opts {
            idletime    IdleTime
            privilegedtime  KernelTime
            usertime    UserTime
            dpctime     DpcTime
            interrupttime InterruptTime
            interrupts    InterruptCount
        }
    }

    # Note the PDH options match those of 
    # twapi::get_processor_perf_counter_paths
    set pdh_opts {
        dpcutilization
        interruptutilization
        privilegedutilization
        processorutilization
        userutilization
        dpcrate
        dpcqueuerate
        interruptrate
    }
    # apcbypassrate - does not exist on XP
    # dpcbypassrate - does not exist on XP

    set sysinfo_opts {
        arch
        processorlevel
        processorrev
        processorname
        processormodel
        processorspeed
    }

    array set opts [parseargs args \
                        [concat [list all \
                                     currentprocessorspeed \
                                     [list interval.int 100]] \
                             [array names ::twapi::get_processor_info_base_opts] \
                             $pdh_opts $sysinfo_opts]]

    # Registry lookup for processor description
    # If no processor specified, use 0 under the assumption all processors
    # are the same
    set reg_hwkey "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\[expr {$processor == "" ? 0 : $processor}]"

    set results [list ]

    set processordata [Twapi_SystemProcessorTimes]
    if {$processor ne ""} {
        if {[llength $processordata] <= $processor} {
            error "Invalid processor number '$processor'"
        }
        array set times [lindex $processordata $processor]
        foreach {opt field} [array get ::twapi::get_processor_info_base_opts] {
            if {$opts(all) || $opts($opt)} {
                lappend results -$opt $times($field)
            }
        }
    } else {
        # Need information across all processors
        foreach instancedata $processordata {
            foreach {opt field} [array get ::twapi::get_processor_info_base_opts] {
                if {[info exists times($field)]} {
                    # We use expr, and not incr here so as to deal with wides
                    set times($field) [expr {wide($times($field)) + [kl_get $instancedata $field]}]
                } else {
                    set times($field) [kl_get $instancedata $field]
                }
            }
            foreach {opt field} [array get ::twapi::get_processor_info_base_opts] {
                if {$opts(all) || $opts($opt)} {
                    lappend results -$opt $times($field)
                }
            }
        }
    }

    if {$opts(all) || $opts(currentprocessorspeed)} {
        # This might fail if counter is not present. We return
        # the rated setting in that case
        if {[catch {
            set ctr_path [make_perf_counter_path ProcessorPerformance "Processor Frequency" -instance Processor_Number_$processor -localize true]
            lappend results -currentprocessorspeed [get_counter_path_value $ctr_path -interval $opts(interval)]
        }]} {
            if {[catch {registry get $reg_hwkey "~MHz"} val]} {
                set val "unknown"
            }
            lappend results -currentprocessorspeed $val
        }
    }
    # Now retrieve each PDH counter
    set requested_opts [list ]
    foreach pdh_opt $pdh_opts {
        if {$opts(all) || $opts($pdh_opt)} {
            lappend requested_opts "-$pdh_opt"
        }
    }
    
        
    if {[llength $requested_opts]} {
        set counter_list [eval [list get_perf_processor_counter_paths $processor] \
                          $requested_opts]
        foreach {opt processor value} [get_perf_values_from_metacounter_info $counter_list -interval $opts(interval)] {
            lappend results -$opt $value
        }

    }

    if {$opts(all) || $opts(arch) || $opts(processorlevel) || $opts(processorrev)} {
        set sysinfo [GetSystemInfo]
        if {$opts(all) || $opts(arch)} {
            switch -exact -- [lindex $sysinfo 0] {
                0 {set arch intel}
                6 {set arch ia64}
                9 {set arch amd64}
                10 {set arch ia32_win64}
                default {set arch unknown}
            }
            lappend results -arch $arch
        }

        if {$opts(all) || $opts(processorlevel)} {
            lappend results -processorlevel [lindex $sysinfo 8]
        }

        if {$opts(all) || $opts(processorrev)} {
            lappend results -processorrev [format %x [lindex $sysinfo 9]]
        }
    }

    if {$opts(all) || $opts(processorname)} {
        if {[catch {registry get $reg_hwkey "ProcessorNameString"} val]} {
            set val "unknown"
        }
        lappend results -processorname $val
    }

    if {$opts(all) || $opts(processormodel)} {
        if {[catch {registry get $reg_hwkey "Identifier"} val]} {
            set val "unknown"
        }
        lappend results -processormodel $val
    }

    if {$opts(all) || $opts(processorspeed)} {
        if {[catch {registry get $reg_hwkey "~MHz"} val]} {
            set val "unknown"
        }
        lappend results -processorspeed $val
    }

    return $results
}

#
# Get number of active processors
proc twapi::get_processor_count {} {
    return [lindex [GetSystemInfo] 5]
}

#
# Get mask of active processors
proc twapi::get_active_processor_mask {} {
    return [format 0x%x [lindex [GetSystemInfo] 4]]
}

#
# Get system memory information
proc twapi::get_memory_info {args} {
    array set opts [parseargs args {
        all
        allocationgranularity
        availcommit
        availphysical
        minappaddr
        maxappaddr
        pagesize
        swapfiles
        swapfiledetail
        totalcommit
        totalphysical
    }]

    set results [list ]
    if {$opts(all) || $opts(totalphysical) || $opts(availphysical) ||
        $opts(totalcommit) || $opts(availcommit)} {
        foreach {totalphysical availphysical totalcommit availcommit} [GlobalMemoryStatus] break
        foreach opt {totalphysical availphysical totalcommit availcommit} {
            if {$opts(all) || $opts($opt)} {
                lappend results -$opt [set $opt]
            }
        }
    }

    if {$opts(all) || $opts(swapfiles) || $opts(swapfiledetail)} {
        set swapfiles [list ]
        set swapdetail [list ]

        foreach item [Twapi_SystemPagefileInformation] {
            array set swap $item
            set swap(FileName) [_normalize_path $swap(FileName)]
            lappend swapfiles $swap(FileName)
            lappend swapdetail $swap(FileName) [list $swap(CurrentSize) $swap(TotalUsed) $swap(PeakUsed)]
        }
        if {$opts(all) || $opts(swapfiles)} {
            lappend results -swapfiles $swapfiles
        }
        if {$opts(all) || $opts(swapfiledetail)} {
            lappend results -swapfiledetail $swapdetail
        }
    }

    if {$opts(all) || $opts(allocationgranularity) ||
        $opts(minappaddr) || $opts(maxappaddr) || $opts(pagesize)} {
        set sysinfo [twapi::GetSystemInfo]
        foreach {opt fmt index} {
            pagesize %u 1 minappaddr 0x%x 2 maxappaddr 0x%x 3 allocationgranularity %u 7} {
            if {$opts(all) || $opts($opt)} {
                lappend results -$opt [format $fmt [lindex $sysinfo $index]]
            }
        }
    }

    return $results
}

#
# Get the netbios name
proc twapi::get_computer_netbios_name {} {
    return [GetComputerName]
}

#
# Get the computer name
proc twapi::get_computer_name {{typename netbios}} {
    if {[string is integer $typename]} {
        set type $typename
    } else {
        set type [lsearch -exact {netbios dnshostname dnsdomain dnsfullyqualified physicalnetbios physicaldnshostname physicaldnsdomain physicaldnsfullyqualified} $typename]
        if {$type < 0} {
            error "Unknown computer name type '$typename' specified"
        }
    }
    return [GetComputerNameEx $type]
}

#
# Shut down the system
proc twapi::shutdown_system {args} {
    array set opts [parseargs args {
        system.arg
        {message.arg "System shutdown has been initiated"}
        {timeout.int 60}
        force
        restart
    } -nulldefault]

    eval_with_privileges {
        InitiateSystemShutdown $opts(system) $opts(message) \
            $opts(timeout) $opts(force) $opts(restart)
    } SeShutdownPrivilege
}

# Abort a system shutdown
proc twapi::abort_system_shutdown {args} {
    array set opts [parseargs args {system.arg} -nulldefault]
    eval_with_privileges {
        AbortSystemShutdown $opts(system)
    } SeShutdownPrivilege
}

#
# Suspend system
proc twapi::suspend_system {args} {
    array set opts [parseargs args {
        {state.arg standby {standby hibernate}}
        force.bool
        disablewakeevents.bool
    } -maxleftover 0 -nulldefault]

    eval_with_privileges {
        SetSuspendState [expr {$opts(state) eq "hibernate"}] $opts(force) $opts(disablewakeevents)
    } SeShutdownPrivilege
}

#
# Get system uptime
proc twapi::get_system_uptime {} {
    set ctr_path [make_perf_counter_path System "System Up Time" -localize true]
    return [get_counter_path_value $ctr_path -interval 0]
}

#
# Get system information
proc twapi::get_system_info {args} {
    array set opts [parseargs args {
        all
        sid
        uptime
        handlecount
        eventcount
        mutexcount
        processcount
        sectioncount
        semaphorecount
        threadcount
    } -maxleftover 0]

    set result [list ]
    if {$opts(all) || $opts(uptime)} {
        lappend result -uptime [get_system_uptime]
    }

    if {$opts(all) || $opts(sid)} {
        set lsah [get_lsa_policy_handle -access policy_view_local_information]
        try {
            lappend result -sid [lindex [Twapi_LsaQueryInformationPolicy $lsah 5] 1]
        } finally {
            close_lsa_policy_handle $lsah
        }
    }

    # If we don't need any PDH based values, return
    if {! ($opts(all) || $opts(handlecount) || $opts(processcount) || $opts(threadcount) || $opts(eventcount) || $opts(mutexcount) || $opts(sectioncount) || $opts(semaphorecount))} {
        return $result
    }

    set hquery [open_perf_query]
    try {
        # Create the counters
        if {$opts(all) || $opts(handlecount)} {
            set handlecount_ctr [add_perf_counter $hquery [make_perf_counter_path Process "Handle Count" -instance _Total -localize true]]
        }
        foreach {opt ctrname} {
            eventcount   Events
            mutexcount   Mutexes
            processcount Processes
            sectioncount Sections
            semaphorecount Semaphores
            threadcount  Threads
        } {
            if {$opts(all) || $opts($opt)} {
                set ${opt}_ctr [add_perf_counter $hquery [make_perf_counter_path Objects $ctrname -localize true]]
            }
        }
        # Collect the data
        collect_perf_query_data $hquery

        foreach opt {
            handlecount
            eventcount
            mutexcount
            processcount
            sectioncount
            semaphorecount
            threadcount
        } {
            if {[info exists ${opt}_ctr]} {
                lappend result -$opt [get_hcounter_value [set ${opt}_ctr] -format long -scale "" -full 0]
            }
        }
    } finally {
        foreach opt {
            handlecount
            eventcount
            mutexcount
            processcount
            sectioncount
            semaphorecount
            threadcount
        } {
            if {[info exists ${opt}_ctr]} {
                remove_perf_counter [set ${opt}_ctr]
            }
        }
        close_perf_query $hquery
    }
    return $result
}

# Get list of open handles - unsupported - crashes on some systems
proc twapi::XXXget_open_handles {args} {
    variable handle_type_names

    array set opts [parseargs args {
        {pid.int  -1}
        {type.arg -1}
        {ignoreerrors.bool 1}
    }]

    if {![info exists handle_type_values]} {
        if {[min_os_version 5 1]} {
            array set handle_type_values {
                desktop       18
                directory     2
                event         9
                file          28
                iocompletion  27
                key           20
                keyedevent    16
                mutant        11
                port          21
                process       5
                section       19
                semaphore     13
                thread        6
                timer         14
                token         4
                windowstation 17
                wmiguid       29
            }
        } else {
            array set handle_type_values {
                desktop       16
                directory     2
                event         8
                file          26
                iocompletion  25
                key           18
                mutant        10
                port          19
                process       5
                section       17
                semaphore     12
                thread        6
                timer         13
                token         4
                windowstation 15
            }
        }
    }

    # TBD - need to update this table for XP, Win2k3
    if {![string is integer -strict $opts(type)]} {
        set opts(type) $handle_type_values($opts(type))
    }

    set result [list ]
    eval_with_privileges {
        foreach hl [Twapi_GetHandleInformation $opts(pid) $opts(ignoreerrors) 10 $opts(type)] {
            lappend result [list \
                                -handle [lindex $hl 0] \
                                -pid    [lindex $hl 1] \
                                -name   [lindex $hl 7] \
                                -type   [string tolower [lindex $hl 9]] \
                               ]
        }
    } [list SeDebugPrivilege] -besteffort

    return $result
}

#
# Get list of processes that have an open handle to a resource
proc twapi::XXXget_open_handle_pids {pat args} {
    array set opts [parseargs args {
        {type.arg file}
        {match.arg string}
    }]

    switch -exact -- $opts(match) {
        string {set op equal}
        glob   {set op match}
        default {error "Invalid value '$opts(match)' specified for option -match"}
    }

    # Get all handles of the specified type
    array set names {}
    foreach elem [XXXget_open_handles -type $opts(type)] {
        array set handleinfo $elem
        lappend names($handleinfo(-name)) $handleinfo(-pid)
    }

    # Now try matching the specified names against the entries in the names
    # array. This is complicated by the fact that for files the drive
    # may be specified in a variety of forms or may even be missing
    # in the list returned by the get_open_handles function

    set matches [list ]

    # First, get any exact matches
    if {$op == "equal" && [info exists names($pat)]} {
        lappend matches $pat [lsort -unique $names($pat)]
        unset names($pat);              # So we don't include it again
    }

    # Next, try a case-insensitive match
    foreach {index val} [array get names] {
        if {[string $op -nocase $pat $index]} {
            lappend matches $index [lsort -unique $val]
            unset names($index);              # So we don't include it again
        }
    }

    # Now try futzing around with path separators, relative names etc.
    # This only applies to files and directories
    # TBD - should also handle registry by mapping HKEY_USERS etc.
    switch -exact -- $opts(type) {
        file -
        directory {
            # NOTE: type "directory" is NOT A FILE SYSTEM DIRECTORY!
            # It is a directory as in the NT object table! But it also
            # uses \ as separator. 
            # Convert / to \ for matching against the array
            set native_name      [file nativename $pat]
            set norm_name        [file nativename [file normalize $pat]]
            set volrelative_name [lrange [file split $norm_name] 1 end]
            set volrelative_name [eval [list file join /] $volrelative_name]
            set volrelative_name [file nativename $volrelative_name]
        }
        default {
            return $matches
        }
    }

    # Try to match using various forms. For glob matches we always
    # collect multiple matches without a "priority". For string matches
    # we prioritize as match against native name, match against
    # normalized name and match against relative name
    foreach {index val} [array get names] {

        # Now try the native form for an exact match
        if {[string $op -nocase $native_name $index]} {
            # Sort to remove duplicates
            lappend matches $index [lsort -unique $val]
            continue
        }

        # Now try with normalized form of the name
        if {[string $op -nocase $norm_name $index]} {
            #lappend norm_index $index
            lappend matches $index [lsort -unique $val]
            continue
        }
        
        # Now try to match just the relative name
        if {[string $op -nocase $volrelative_name $index]} {
            #lappend volrelative_name_index $index
            lappend matches $index [lsort -unique $val]
            continue
        }
    }
    
    return $matches

    if {0} {
        Old code
        # If a normalized match occurs, return it
        if {[info exists norm_index]} {
            # Sort to remove duplicates
            return [list $norm_index [lsort -unique $names($norm_index)]]
        }
        
        # If a volume relative match occurs, return it
        if {[info exists volrelative_name_index]} {
            # Sort to remove duplicates
            return [list $volrelative_name_index [lsort -unique $names($volrelative_name_index)]]
        }

        return [list ]
    }
}


#
# Map a Windows error code to a string
proc twapi::map_windows_error {code} {
    # Trim trailing CR/LF
    return [string trimright [twapi::Twapi_MapWindowsErrorToString $code] "\r\n"]
}

#
# Return $s with all environment strings expanded
proc twapi::expand_environment_strings {s} {
    return [ExpandEnvironmentStrings $s]
}

#
# Load given library
proc twapi::load_library {path args} {
    array set opts [parseargs args {
        dontresolverefs
        datafile
        alteredpath
    }]

    set flags 0
    if {$opts(dontresolverefs)} {
        setbits flags 1;                # DONT_RESOLVE_DLL_REFERENCES
    }
    if {$opts(datafile)} {
        setbits flags 2;                # LOAD_LIBRARY_AS_DATAFILE
    }
    if {$opts(alteredpath)} {
        setbits flags 8;                # LOAD_WITH_ALTERED_SEARCH_PATH
    }

    # LoadLibrary always wants backslashes
    set path [file nativename $path]
    return [LoadLibraryEx $path $flags]
}

#
# Free library opened with load_library
proc twapi::free_library {libh} {
    FreeLibrary $libh
}


#
# Format message string
proc twapi::format_message {args} {
    if {[catch {eval _unsafe_format_message $args} result]} {
        set erinfo $::errorInfo
        set ercode $::errorCode
        if {[lindex $ercode 0] == "POSIX" && [lindex $ercode 1] == "EFAULT"} {
            # Number of string params do not match % specifiers
            # Retry without replacing % specifiers
            return [eval _unsafe_format_message -ignoreinserts $args]
        } else {
            error $result $erinfo $ercode
        }
    }

    return $result
}


#
# Read an ini file int
proc twapi::read_inifile_key {section key args} {
    array set opts [parseargs args {
        {default.arg ""}
        inifile.arg
    } -maxleftover 0]

    if {[info exists opts(inifile)]} {
        return [GetPrivateProfileString $section $key $opts(default) $opts(inifile)]
    } else {
        return [GetProfileString $section $key $opts(default)]
    }
}

#
# Write an ini file string
proc twapi::write_inifile_key {section key value args} {
    array set opts [parseargs args {
        inifile.arg
    } -maxleftover 0]

    if {[info exists opts(inifile)]} {
        WritePrivateProfileString $section $key $value $opts(inifile)
    } else {
        WriteProfileString $section $key $value
    }
}

#
# Delete an ini file string
proc twapi::delete_inifile_key {section key args} {
    array set opts [parseargs args {
        inifile.arg
    } -maxleftover 0]

    if {[info exists opts(inifile)]} {
        WritePrivateProfileString $section $key $twapi::nullptr $opts(inifile)
    } else {
        WriteProfileString $section $key $twapi::nullptr
    }
}

#
# Get names of the sections in an inifile
proc twapi::read_inifile_section_names {args} {
    array set opts [parseargs args {
        inifile.arg
    } -nulldefault -maxleftover 0]

    return [GetPrivateProfileSectionNames $opts(inifile)]
}

#
# Get names of the sections in an inifile
proc twapi::read_inifile_section {section args} {
    array set opts [parseargs args {
        inifile.arg
    } -nulldefault -maxleftover 0]

    set result [list ]
    foreach line [GetPrivateProfileSection $section $opts(inifile)] {
        set pos [string first "=" $line]
        if {$pos >= 0} {
            lappend result [string range $line 0 [expr {$pos-1}]] [string range $line [incr pos] end]
        }
    }
    return $result
}


#
# Delete an ini file section
proc twapi::delete_inifile_section {section args} {
    variable nullptr

    array set opts [parseargs args {
        inifile.arg
    }]

    if {[info exists opts(inifile)]} {
        WritePrivateProfileString $section $nullptr $nullptr $opts(inifile)
    } else {
        WriteProfileString $section $nullptr $nullptr
    }
}


#
# Get the primary domain controller
proc twapi::get_primary_domain_controller {args} {
    array set opts [parseargs args {system.arg domain.arg} -nulldefault -maxleftover 0]
    if {[string length $opts(system)]} {
        # Win NT requires \\ preceding the name
        set opts(system) "\\\\[string trimleft \\]"
    }
    return [NetGetDCName $opts(system) $opts(domain)]
}

#
# Get a domain controller for a domain
proc twapi::find_domain_controller {args} {
    array set opts [parseargs args {
        system.arg
        avoidself.bool
        domain.arg
        domainguid.arg
        site.arg
        rediscover.bool
        allowstale.bool
        require.arg
        prefer.arg
        justldap.bool
        {inputnameformat.arg any {dns flat any}}
        {outputnameformat.arg any {dns flat any}}
        {outputaddrformat.arg any {ip netbios any}}
        getdetails
    } -maxleftover 0 -nulldefault]


    set flags 0
    
    if {$opts(outputaddrformat) eq "ip"} {
        setbits flags 0x200
    }

    # Set required bits.
    foreach req $opts(require) {
        if {[string is integer $req]} {
            setbits flags $req
        } else {
            switch -exact -- $req {
                directoryservice { setbits flags 0x10 }
                globalcatalog    { setbits flags 0x40 }
                pdc              { setbits flags 0x80 }
                kdc              { setbits flags 0x400 }
                timeserver       { setbits flags 0x800 }
                writable         { setbits flags 0x1000 }
                default {
                    error "Invalid token '$req' specified in value for option '-require'"
                }
            }
        }
    }

    # Set preferred bits.
    foreach req $opts(prefer) {
        if {[string is integer $req]} {
            setbits flags $req
        } else {
            switch -exact -- $req {
                directoryservice {
                    # If required flag is already set, don't set this
                    if {! ($flags & 0x10)} {
                        setbits flags 0x20
                    }
                }
                timeserver {
                    # If required flag is already set, don't set this
                    if {! ($flags & 0x800)} {
                        setbits flags 0x2000
                    }
                }
                default {
                    error "Invalid token '$req' specified in value for option '-prefer'"
                }
            }
        }
    }

    if {$opts(rediscover)} {
        setbits flags 0x1
    } else {
        # Only look at this option if rediscover is not set
        if {$opts(allowstale)} {
            setbits flags 0x100
        }
    }

    if {$opts(avoidself)} {
        setbits flags 0x4000
    }

    if {$opts(justldap)} {
        setbits flags 0x8000
    }

    switch -exact -- $opts(inputnameformat) {
        any  { }
        flat { setbits flags 0x10000 }
        dns  { setbits flags 0x20000 }
        default {
            error "Invalid value '$opts(inputnameformat)' for option '-inputnameformat'"
        }
    }

    switch -exact -- $opts(outputnameformat) {
        any  { }
        flat { setbits flags 0x80000000 }
        dns  { setbits flags 0x40000000 }
        default {
            error "Invalid value '$opts(outputnameformat)' for option '-outputnameformat'"
        }
    }

    array set dcinfo [DsGetDcName $opts(system) $opts(domain) $opts(domainguid) $opts(site) $flags]

    if {! $opts(getdetails)} {
        return $dcinfo(DomainControllerName)
    }

    set result [list \
                    -dcname $dcinfo(DomainControllerName) \
                    -dcaddr [string trimleft $dcinfo(DomainControllerAddress) \\] \
                    -domainguid $dcinfo(DomainGuid) \
                    -domain $dcinfo(DomainName) \
                    -dnsforest $dcinfo(DnsForestName) \
                    -dcsite $dcinfo(DcSiteName) \
                    -clientsite $dcinfo(ClientSiteName) \
                   ]


    if {$dcinfo(DomainControllerAddressType) == 1} {
        lappend result -dcaddrformat ip
    } else {
        lappend result -dcaddrformat netbios
    }

    if {$dcinfo(Flags) & 0x20000000} {
        lappend result -dcnameformat dns
    } else {
        lappend result -dcnameformat netbios
    }
    
    if {$dcinfo(Flags) & 0x40000000} {
        lappend result -domainformat dns
    } else {
        lappend result -domainformat netbios
    }
    
    if {$dcinfo(Flags) & 0x80000000} {
        lappend result -dnsforestformat dns
    } else {
        lappend result -dnsforestformat netbios
    }
    
    set features [list ]
    foreach {flag feature} {
        0x1    pdc
        0x4    globalcatalog
        0x8    ldap
        0x10   directoryservice
        0x20   kdc
        0x40   timeserver
        0x80   closest
        0x100  writable
        0x200  goodtimeserver
    } {
        if {$dcinfo(Flags) & $flag} {
            lappend features $feature
        }
    }

    lappend result -features $features

    return $result
}



#
# Get the primary domain info
proc twapi::get_primary_domain_info {args} {
    array set opts [parseargs args {
        all
        name
        dnsdomainname
        dnsforestname
        domainguid
        sid
        type
    } -maxleftover 0]

    set result [list ]
    set lsah [get_lsa_policy_handle -access policy_view_local_information]
    try {
        foreach {name dnsdomainname dnsforestname domainguid sid} [Twapi_LsaQueryInformationPolicy $lsah 12] break
        if {[string length $sid] == 0} {
            set type workgroup
            set domainguid ""
        } else {
            set type domain
        }
        foreach opt {name dnsdomainname dnsforestname domainguid sid type} {
            if {$opts(all) || $opts($opt)} {
                lappend result -$opt [set $opt]
            }
        }
    } finally {
        close_lsa_policy_handle $lsah
    }

    return $result
}

#
# Get the handle for a Tcl channel
proc twapi::get_tcl_channel_handle {chan direction} {
    set direction [expr {[string equal $direction "write"] ? 1 : 0}]
    return [Tcl_GetChannelHandle $chan $direction]
}


#
# Duplicate a OS handle
proc twapi::duplicate_handle {h args} {
    variable my_process_handle

    array set opts [parseargs args {
        sourcepid.int
        targetpid.int
        access.arg
        inherit
        closesource
    } -maxleftover 0]

    # Assume source and target processes are us
    set source_ph $my_process_handle
    set target_ph $my_process_handle
    
    if {![string is integer $h]} {
        set h [HANDLE2ADDRESS_LITERAL $h]
    }

    try {
        set me [pid]
        # If source pid specified and is not us, get a handle to the process
        if {[info exists opts(sourcepid)] && $opts(sourcepid) != $me} {
            set source_ph [get_process_handle $opts(sourcepid) -access process_dup_handle]
        }

        # Ditto for target process...
        if {[info exists opts(targetpid)] && $opts(targetpid) != $me} {
            set target_ph [get_process_handle $opts(targetpid) -access process_dup_handle]
        }

        # Do we want to close the original handle (DUPLICATE_CLOSE_SOURCE)
        set flags [expr {$opts(closesource) ? 0x1: 0}]

        if {[info exists opts(access)]} {
            set access [_access_rights_to_mask $opts(access)]
        } else {
            # If no desired access is indicated, we want the same access as
            # the original handle
            set access 0
            set flags [expr {$flags | 0x2}]; # DUPLICATE_SAME_ACCESS
        }


        set dup [DuplicateHandle $source_ph $h $target_ph $access $opts(inherit) $flags]

        # IF targetpid specified, return handle else literal
        # (even if targetpid is us)
        if {![info exists opts(targetpid)]} {
            set dup [ADDRESS_LITERAL2HANDLE $dup]
        }
    } finally {
        if {$source_ph != $my_process_handle} {
            close_handles $source_ph
        }
        if {$target_ph != $my_process_handle} {
            close_handles $source_ph
        }
    }
    
    return $dup
}




#
# Get a element from SystemParametersInfo
proc twapi::get_system_parameters_info {uiaction} {
    variable SystemParametersInfo_uiactions_get
    # Format of an element is
    #  uiaction_indexvalue uiparam binaryscanstring malloc_size modifiers
    # uiparam may be an int or "sz" in which case the malloc size
    # is substribnuted for it.
    # If modifiers contains "cbsize" the first dword is initialized
    # with malloc_size
    if {![info exists SystemParametersInfo_uiactions_get]} {
        array set SystemParametersInfo_uiactions_get {
            SPI_GETDESKWALLPAPER {0x0073 2048 unicode 4096}
            SPI_GETBEEP  {0x0001 0 i 4}
            SPI_GETMOUSE {0x0003 0 i3 12}
            SPI_GETBORDER {0x0005 0 i 4}
            SPI_GETKEYBOARDSPEED {0x000A 0 i 4}
            SPI_ICONHORIZONTALSPACING {0x000D 0 i 4}
            SPI_GETSCREENSAVETIMEOUT {0x000E 0 i 4}
            SPI_GETSCREENSAVEACTIVE {0x0010 0 i 4}
            SPI_GETKEYBOARDDELAY {0x0016 0 i 4}
            SPI_ICONVERTICALSPACING {0x0018 0 i 4}
            SPI_GETICONTITLEWRAP {0x0019 0 i 4}
            SPI_GETMENUDROPALIGNMENT {0x001B 0 i 4}
            SPI_GETDRAGFULLWINDOWS {0x0026 0 i 4}
            SPI_GETMINIMIZEDMETRICS {0x002B sz i5 20 cbsize}
            SPI_GETWORKAREA {0x0030 0 i4 16}
            SPI_GETKEYBOARDPREF {0x0044 0 i 4 }
            SPI_GETSCREENREADER {0x0046 0 i 4}
            SPI_GETANIMATION {0x0048 sz i2 8 cbsize}
            SPI_GETFONTSMOOTHING {0x004A 0 i 4}
            SPI_GETLOWPOWERTIMEOUT {0x004F 0 i 4}
            SPI_GETPOWEROFFTIMEOUT {0x0050 0 i 4}
            SPI_GETLOWPOWERACTIVE {0x0053 0 i 4}
            SPI_GETPOWEROFFACTIVE {0x0054 0 i 4}
            SPI_GETMOUSETRAILS {0x005E 0 i 4}
            SPI_GETSCREENSAVERRUNNING {0x0072 0 i 4}
            SPI_GETFILTERKEYS {0x0032 sz i6 24 cbsize}
            SPI_GETTOGGLEKEYS {0x0034 sz i2 8 cbsize}
            SPI_GETMOUSEKEYS {0x0036 sz i7 28 cbsize}
            SPI_GETSHOWSOUNDS {0x0038 0 i 4}
            SPI_GETSTICKYKEYS {0x003A sz i2 8 cbsize}
            SPI_GETACCESSTIMEOUT {0x003C 12 i3 12 cbsize}
            SPI_GETSNAPTODEFBUTTON {0x005F 0 i 4}
            SPI_GETMOUSEHOVERWIDTH {0x0062 0 i 4}
            SPI_GETMOUSEHOVERHEIGHT {0x0064 0 i 4 }
            SPI_GETMOUSEHOVERTIME {0x0066 0 i 4}
            SPI_GETWHEELSCROLLLINES {0x0068 0 i 4}
            SPI_GETMENUSHOWDELAY {0x006A 0 i 4}
            SPI_GETSHOWIMEUI {0x006E 0 i 4}
            SPI_GETMOUSESPEED {0x0070 0 i 4}
            SPI_GETACTIVEWINDOWTRACKING {0x1000 0 i 4}
            SPI_GETMENUANIMATION {0x1002 0 i 4}
            SPI_GETCOMBOBOXANIMATION {0x1004 0 i 4}
            SPI_GETLISTBOXSMOOTHSCROLLING {0x1006 0 i 4}
            SPI_GETGRADIENTCAPTIONS {0x1008 0 i 4}
            SPI_GETKEYBOARDCUES {0x100A 0 i 4}
            SPI_GETMENUUNDERLINES            {0x100A 0 i 4}
            SPI_GETACTIVEWNDTRKZORDER {0x100C 0 i 4}
            SPI_GETHOTTRACKING {0x100E 0 i 4}
            SPI_GETMENUFADE {0x1012 0 i 4}
            SPI_GETSELECTIONFADE {0x1014 0 i 4}
            SPI_GETTOOLTIPANIMATION {0x1016 0 i 4}
            SPI_GETTOOLTIPFADE {0x1018 0 i 4}
            SPI_GETCURSORSHADOW {0x101A 0 i 4}
            SPI_GETMOUSESONAR {0x101C 0 i 4 }
            SPI_GETMOUSECLICKLOCK {0x101E 0 i 4}
            SPI_GETMOUSEVANISH {0x1020 0 i 4}
            SPI_GETFLATMENU {0x1022 0 i 4}
            SPI_GETDROPSHADOW {0x1024 0 i 4}
            SPI_GETBLOCKSENDINPUTRESETS {0x1026 0 i 4}
            SPI_GETUIEFFECTS {0x103E 0 i 4}
            SPI_GETFOREGROUNDLOCKTIMEOUT {0x2000 0 i 4}
            SPI_GETACTIVEWNDTRKTIMEOUT {0x2002 0 i 4}
            SPI_GETFOREGROUNDFLASHCOUNT {0x2004 0 i 4}
            SPI_GETCARETWIDTH {0x2006 0 i 4}
            SPI_GETMOUSECLICKLOCKTIME {0x2008 0 i 4}
            SPI_GETFONTSMOOTHINGTYPE {0x200A 0 i 4}
            SPI_GETFONTSMOOTHINGCONTRAST {0x200C 0 i 4}
            SPI_GETFOCUSBORDERWIDTH {0x200E 0 i 4}
            SPI_GETFOCUSBORDERHEIGHT {0x2010 0 i 4}
        }
    }

    set key [string toupper $uiaction]

    # TBD - 
    # SPI_GETHIGHCONTRAST {0x0042 }
    # SPI_GETSOUNDSENTRY {0x0040 }
    # SPI_GETICONMETRICS {0x002D }
    # SPI_GETICONTITLELOGFONT {0x001F }
    # SPI_GETDEFAULTINPUTLANG {0x0059 }
    # SPI_GETNONCLIENTMETRICS {0x0029 }
    # SPI_GETFONTSMOOTHINGORIENTATION {0x2012}

    if {![info exists SystemParametersInfo_uiactions_get($key)]} {
        set key SPI_$key
        if {![info exists SystemParametersInfo_uiactions_get($key)]} {
            error "Unknown SystemParametersInfo index symbol '$uiaction'"
        }
    }

    foreach {index uiparam fmt sz modifiers} $SystemParametersInfo_uiactions_get($key) break
    if {$uiparam eq "sz"} {
        set uiparam $sz
    }
    set mem [malloc $sz]
    try {
        if {[lsearch -exact $modifiers cbsize] >= 0} {
            # A structure that needs first field set to its size
            Twapi_WriteMemoryBinary $mem 0 $sz [binary format i $sz]
        }
        SystemParametersInfo $index $uiparam $mem 0
        if {$fmt eq "unicode"} {
            set val [Twapi_ReadMemoryUnicode $mem 0]
        } else {
            binary scan [Twapi_ReadMemoryBinary $mem 0 $sz] $fmt val
        }
    } finally {
        free $mem
    }
    return $val
}

#
proc twapi::set_system_parameters_info {uiaction val args} {
    variable SystemParametersInfo_uiactions_set

    # Format of an element is
    #  uiaction_indexvalue uiparam binaryscanstring malloc_size modifiers
    # uiparam may be an int or "sz" in which case the malloc size
    # is substribnuted for it.
    # If modifiers contains "cbsize" the first dword is initialized
    # with malloc_size
    if {![info exists SystemParametersInfo_uiactions_set]} {
        array set SystemParametersInfo_uiactions_set {
            SPI_SETBEEP                 {0x0002 bool}
            SPI_SETMOUSE                {0x0004 unsupported}
            SPI_SETBORDER               {0x0006 int}
            SPI_SETKEYBOARDSPEED        {0x000B int}
            SPI_ICONHORIZONTALSPACING   {0x000D int}
            SPI_SETSCREENSAVETIMEOUT    {0x000F int}
            SPI_SETSCREENSAVEACTIVE     {0x0011 bool}
            SPI_SETDESKWALLPAPER        {0x0014 unsupported}
            SPI_SETDESKPATTERN          {0x0015 int}
            SPI_SETKEYBOARDDELAY        {0x0017 int}
            SPI_ICONVERTICALSPACING     {0x0018 int}
            SPI_SETICONTITLEWRAP        {0x001A bool}
            SPI_SETMENUDROPALIGNMENT    {0x001C bool}
            SPI_SETDOUBLECLKWIDTH       {0x001D int}
            SPI_SETDOUBLECLKHEIGHT      {0x001E int}
            SPI_SETDOUBLECLICKTIME      {0x0020 int}
            SPI_SETMOUSEBUTTONSWAP      {0x0021 bool}
            SPI_SETICONTITLELOGFONT     {0x0022 LOGFONT}
            SPI_SETDRAGFULLWINDOWS      {0x0025 bool}
            SPI_SETNONCLIENTMETRICS     {0x002A NONCLIENTMETRICS}
            SPI_SETMINIMIZEDMETRICS     {0x002C MINIMIZEDMETRICS}
            SPI_SETICONMETRICS          {0x002E ICONMETRICS}
            SPI_SETWORKAREA             {0x002F RECT}
            SPI_SETPENWINDOWS           {0x0031}
            SPI_SETHIGHCONTRAST         {0x0043 HIGHCONTRAST}
            SPI_SETKEYBOARDPREF         {0x0045 bool}
            SPI_SETSCREENREADER         {0x0047 bool}
            SPI_SETANIMATION            {0x0049 ANIMATIONINFO}
            SPI_SETFONTSMOOTHING        {0x004B bool}
            SPI_SETDRAGWIDTH            {0x004C int}
            SPI_SETDRAGHEIGHT           {0x004D int}
            SPI_SETHANDHELD             {0x004E}
            SPI_SETLOWPOWERTIMEOUT      {0x0051 int}
            SPI_SETPOWEROFFTIMEOUT      {0x0052 int}
            SPI_SETLOWPOWERACTIVE       {0x0055 bool}
            SPI_SETPOWEROFFACTIVE       {0x0056 bool}
            SPI_SETCURSORS              {0x0057 int}
            SPI_SETICONS                {0x0058 int}
            SPI_SETDEFAULTINPUTLANG     {0x005A HKL}
            SPI_SETLANGTOGGLE           {0x005B int}
            SPI_SETMOUSETRAILS          {0x005D int}
            SPI_SETFILTERKEYS          {0x0033 FILTERKEYS}
            SPI_SETTOGGLEKEYS          {0x0035 TOGGLEKEYS}
            SPI_SETMOUSEKEYS           {0x0037 MOUSEKEYS}
            SPI_SETSHOWSOUNDS          {0x0039 bool}
            SPI_SETSTICKYKEYS          {0x003B STICKYKEYS}
            SPI_SETACCESSTIMEOUT       {0x003D ACCESSTIMEOUT}
            SPI_SETSERIALKEYS          {0x003F SERIALKEYS}
            SPI_SETSOUNDSENTRY         {0x0041 SOUNDSENTRY}
            SPI_SETSNAPTODEFBUTTON     {0x0060 bool}
            SPI_SETMOUSEHOVERWIDTH     {0x0063 int}
            SPI_SETMOUSEHOVERHEIGHT    {0x0065 int}
            SPI_SETMOUSEHOVERTIME      {0x0067 int}
            SPI_SETWHEELSCROLLLINES    {0x0069 int}
            SPI_SETMENUSHOWDELAY       {0x006B int}
            SPI_SETSHOWIMEUI          {0x006F bool}
            SPI_SETMOUSESPEED         {0x0071 castint}
            SPI_SETACTIVEWINDOWTRACKING         {0x1001 castbool}
            SPI_SETMENUANIMATION                {0x1003 castbool}
            SPI_SETCOMBOBOXANIMATION            {0x1005 castbool}
            SPI_SETLISTBOXSMOOTHSCROLLING       {0x1007 castbool}
            SPI_SETGRADIENTCAPTIONS             {0x1009 castbool}
            SPI_SETKEYBOARDCUES                 {0x100B castbool}
            SPI_SETMENUUNDERLINES               {0x100B castbool}
            SPI_SETACTIVEWNDTRKZORDER           {0x100D castbool}
            SPI_SETHOTTRACKING                  {0x100F castbool}
            SPI_SETMENUFADE                     {0x1013 castbool}
            SPI_SETSELECTIONFADE                {0x1015 castbool}
            SPI_SETTOOLTIPANIMATION             {0x1017 castbool}
            SPI_SETTOOLTIPFADE                  {0x1019 castbool}
            SPI_SETCURSORSHADOW                 {0x101B castbool}
            SPI_SETMOUSESONAR                   {0x101D castbool}
            SPI_SETMOUSECLICKLOCK               {0x101F bool}
            SPI_SETMOUSEVANISH                  {0x1021 castbool}
            SPI_SETFLATMENU                     {0x1023 castbool}
            SPI_SETDROPSHADOW                   {0x1025 castbool}
            SPI_SETBLOCKSENDINPUTRESETS         {0x1027 bool}
            SPI_SETUIEFFECTS                    {0x103F castbool}
            SPI_SETFOREGROUNDLOCKTIMEOUT        {0x2001 castint}
            SPI_SETACTIVEWNDTRKTIMEOUT          {0x2003 castint}
            SPI_SETFOREGROUNDFLASHCOUNT         {0x2005 castint}
            SPI_SETCARETWIDTH                   {0x2007 castint}
            SPI_SETMOUSECLICKLOCKTIME           {0x2009 int}
            SPI_SETFONTSMOOTHINGTYPE            {0x200B castint}
            SPI_SETFONTSMOOTHINGCONTRAST        {0x200D unsupported}
            SPI_SETFOCUSBORDERWIDTH             {0x200F castint}
            SPI_SETFOCUSBORDERHEIGHT            {0x2011 castint}
        }
    }    

    
    array set opts [parseargs args {
        persist
        notify
    } -nulldefault]

    set flags 0
    if {$opts(persist)} {
        setbits flags 1
    }

    if {$opts(notify)} {
        # Note that actually the notify flag has no effect if persist
        # is not set.
        setbits flags 2
    }

    set key [string toupper $uiaction]

    if {![info exists SystemParametersInfo_uiactions_set($key)]} {
        set key SPI_$key
        if {![info exists SystemParametersInfo_uiactions_set($key)]} {
            error "Unknown SystemParametersInfo index symbol '$uiaction'"
        }
    }

    foreach {index fmt} $SystemParametersInfo_uiactions_set($key) break

    switch -exact -- $fmt {
        int  { SystemParametersInfo $index $val NULL $flags }
        bool {
            set val [expr {$val ? 1 : 0}]
            SystemParametersInfo $index $val NULL $flags
        }
        castint {
            # We have to pass the value as a cast pointer
            SystemParametersInfo $index 0 [Twapi_AddressToPointer $val] $flags
        }
        castbool {
            # We have to pass the value as a cast pointer
            set val [expr {$val ? 1 : 0}]
            SystemParametersInfo $index 0 [Twapi_AddressToPointer $val] $flags
        }
        default {
            error "The data format for $uiaction is not currently supported"
        }
    }

    return
}

################################################################
#
# Utility procs
#

#
# Format message string - will raise exception if insufficient number
# of arguments
proc twapi::_unsafe_format_message {args} {
    array set opts [parseargs args {
        module.arg
        fmtstring.arg
        messageid.arg
        langid.arg
        params.arg
        includesystem
        ignoreinserts
        width.int
    } -nulldefault]

    set flags 0

    if {$opts(module) == ""} {
        if {$opts(fmtstring) == ""} {
            # If neither -module nor -fmtstring specified, message is formatted
            # from the system
            set opts(module) null
            setbits flags 0x1000;       # FORMAT_MESSAGE_FROM_SYSTEM
        } else {
            setbits flags 0x400;        # FORMAT_MESSAGE_FROM_STRING
            if {$opts(includesystem) || $opts(messageid) != "" || $opts(langid) != ""} {
                error "Options -includesystem, -messageid and -langid cannot be used with -fmtstring"
            }
        }
    } else {
        if {$opts(fmtstring) != ""} {
            error "Options -fmtstring and -module cannot be used together"
        }
        setbits flags 0x800;        # FORMAT_MESSAGE_FROM_HMODULE
        if {$opts(includesystem)} {
            # Also include system in search
            setbits flags 0x1000;       # FORMAT_MESSAGE_FROM_SYSTEM
        }
    }

    if {$opts(ignoreinserts)} {
        setbits flags 0x200;            # FORMAT_MESSAGE_IGNORE_INSERTS
    }
    
    if {$opts(width) > 254} {
        error "Invalid value for option -width. Must be -1, 0, or a positive integer less than 255"
    }
    if {$opts(width) < 0} {
        # Negative width means no width restrictions
        set opts(width) 255;                  # 255 -> no restrictions
    }
    incr flags $opts(width);                  # Width goes in low byte of flags
    
    if {$opts(fmtstring) != ""} {
        return [FormatMessageFromString $flags $opts(fmtstring) $opts(params)]
    } else {
        if {![string is integer -strict $opts(messageid)]} {
            error "Unspecified or invalid value for -messageid option. Must be an integer value"
        }
        if {$opts(langid) == ""} { set opts(langid) 0 }
        if {![string is integer -strict $opts(langid)]} {
            error "Unspecfied or invalid value for -langid option. Must be an integer value"
        }

        # Check if $opts(module) is a file
        if {[_is_swig_ptr $opts(module)]} {
            return  [FormatMessageFromModule $flags $opts(module) \
                         $opts(messageid) $opts(langid) $opts(params)]
        } else {
            set hmod [load_library $opts(module) -datafile]
            try {
                set message  [FormatMessageFromModule $flags $hmod \
                                  $opts(messageid) $opts(langid) $opts(params)]
            } finally {
                free_library $hmod
            }
            return $message
        }
    }
}


Added Binaries/Windows/twapi/pdh.tcl.






















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
#
# Copyright (c) 2003, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

namespace eval twapi {
}

# TBD - how do we know when to refresh items
# - have a begin/end explicitly done by applications
# - have a standard -refresh option
# - distinguish between internal and external routines


#
# Return list of toplevel performance objects
proc twapi::get_perf_objects {args} {
    variable windefs

    array set opts [parseargs args {
        datasource.arg
        machine.arg
        {detail.arg wizard}
        refresh
    } -nulldefault]
    
    # NT 4.0 requires datasource to be null
    if {[string length $opts(datasource)] && ![min_os_version 5 0]} {
        error "Option -datasource is invalid on Windows NT 4.0 platforms"
    }

    set detail_index "PERF_DETAIL_[string toupper $opts(detail)]"
    if {![info exists windefs($detail_index)]} {
        error "Invalid value '$opts(detail)' specified for -detail option"
    }

    # TBD - PdhEnumObjects enables the SeDebugPrivilege the first time it
    # is called. Should we reset it if it was not already enabled?
    # This seems to only happen on the first call

    return [PdhEnumObjects $opts(datasource) $opts(machine) \
                $windefs($detail_index) $opts(refresh)]
}

#
# Return list of items within a performance object
proc twapi::get_perf_object_items {objname args} {
    variable windefs

    array set opts [parseargs args {
        datasource.arg
        machine.arg
        {detail.arg wizard}
        refresh
    } -nulldefault]
    
    # NT 4.0 requires datasource to be null
    if {[string length $opts(datasource)] && ![min_os_version 5 0]} {
        error "Option -datasource is invalid on Windows NT 4.0 platforms"
    }

    set detail_index "PERF_DETAIL_[string toupper $opts(detail)]"
    if {![info exists windefs($detail_index)]} {
        error "Invalid value '$opts(detail)' specified for -detail option"
    }

    if {$opts(refresh)} {
        _refresh_perf_objects $opts(machine) $opts(datasource)
    }

    return [PdhEnumObjectItems $opts(datasource) $opts(machine) \
                $objname $windefs($detail_index) 0]
}

#
# Connect to the specified machine
proc twapi::connect_perf {machine} {
    PdhConnectMachine($machine)
}

#
# Construct a counter path
proc twapi::make_perf_counter_path {object counter args} {
    array set opts [parseargs args {
        machine.arg
        instance.arg
        parent.arg
        instanceindex.int
        {localize.bool false}
    } -nulldefault]
    
    if {$opts(instanceindex) < -1} {
        # Note -1 allowed for instance index
        error "Invalid value '$opts(instanceindex)' specified for -instanceindex option"
    }

    if {$opts(localize)} {
        # Need to localize the counter names
        set object [_localize_perf_counter $object]
        set counter [_localize_perf_counter $counter]
        # TBD - not sure we need to localize parent
        set opts(parent) [_localize_perf_counter $opts(parent)]
    }

    return [PdhMakeCounterPath $opts(machine) $object $opts(instance) \
                $opts(parent) $opts(instanceindex) $counter 0]

}

#
# Parse a counter path and return the individual elements
proc twapi::parse_perf_counter_path {counter_path} {
    array set counter_elems [PdhParseCounterPath $counter_path 0]

    lappend result machine       $counter_elems(szMachineName)
    lappend result object        $counter_elems(szObjectName)
    lappend result instance      $counter_elems(szInstanceName)
    lappend result instanceindex $counter_elems(dwInstanceIndex)
    lappend result parent        $counter_elems(szParentInstance)
    lappend result counter       $counter_elems(szCounterName)

    return $result
}

#
# Validate a counter path - error if invalid
proc twapi::validate_perf_counter_path {counter_path} {
    PdhValidatePath $counter_path
}

#
# Open a query that will be used as a container for counters
proc twapi::open_perf_query {args} {

    array set opts [parseargs args {
        datasource.arg
        cookie.int
    } -nulldefault]
    
    # NT 4.0 requires datasource to be null
    if {[string length $opts(datasource)] && ![min_os_version 5 0]} {
        error "Option -datasource is invalid on Windows NT 4.0 platforms"
    }
    
    if {! [string is integer -strict $opts(cookie)]} {
        error "Non-integer value '$opts(cookie)' specified for -cookie option"
    }
    
    return [PdhOpenQuery $opts(datasource) $opts(cookie)]
}

#
# Close a query - all related counter handles will also be closed
proc twapi::close_perf_query {hquery} {
    PdhCloseQuery $hquery
}

#
# Add a counter to a query
proc twapi::add_perf_counter {hquery counter_path args} {
    array set opts [parseargs args {
        cookie.int
    } -nulldefault]
    
    set hcounter [PdhAddCounter $hquery $counter_path $opts(cookie)]
    return $hcounter
}

#
# Remove a counter
proc twapi::remove_perf_counter {hcounter} {
    PdhRemoveCounter $hcounter
}


#
# Get snapshot of counters in a query
proc twapi::collect_perf_query_data {hquery} {
    PdhCollectQueryData $hquery
}

#
# Get the value of a counter in a query
# TBD - add some way of getting the cookie associated with the counter
proc twapi::get_hcounter_value {hcounter args} {
    variable windefs

    #puts "$hcounter"
    array set opts [parseargs args {
        {format.arg long {long large double}}
        scale.arg
        var.arg
        full.bool
    } -nulldefault]
    
    set format $windefs(PDH_FMT_[string toupper $opts(format)])

    switch -exact -- $opts(scale) {
        ""        { set scale 0 }
        none      { set scale $windefs(PDH_FMT_NOSCALE) }
        nocap     { set scale $windefs(PDH_FMT_NOCAP) }
        x1000     { set scale $windefs(PDH_FMT_1000) }
        default {
            error "Invalid value '$opts(scale)' specified for -scale option"
        }
    }

    set flags [expr {$format | $scale}]

    set status 1
    set result ""
    try {
        set result [PdhGetFormattedCounterValue $hcounter $flags]
    } onerror {TWAPI_WIN32 0x800007d1} {
        # Error is that no such instance exists.
        # If result is being returned in a variable, then
        # we will not generate an error but pass back a return value
        # of 0
        if {[string length $opts(var)] == 0} {
            # Pass on the error
            error $errorResult $errorInfo $errorCode
        }
        set status 0
    }
    if {! $opts(full)} {
        # Only care about the value, not type
        set result [lindex $result 0]
    }
    
    if {[string length $opts(var)]} {
        uplevel [list set $opts(var) $result]
        return $status
    } else {
        return $result
    }
}


#
# Get the value of a counter identified by the path
proc twapi::get_counter_path_value {counter_path args} {
    variable windefs

    array set opts [parseargs args {
        interval.int
        {format.arg long}
        scale.arg
        datasource.arg
        var.arg
        full.bool
    } -nulldefault]
    
    if {$opts(interval) < 0} {
        error "Negative value '$opts(interval)' specified for option -interval"
    }

    # Open the query
    set hquery [open_perf_query -datasource $opts(datasource)]
    try {
        set hcounter [add_perf_counter $hquery $counter_path]
        collect_perf_query_data $hquery
        if {$opts(interval)} {
            after $opts(interval)
            collect_perf_query_data $hquery
        }
        if {[string length $opts(var)]} {
            # Need to pass up value in a variable if so requested
            upvar $opts(var) myvar
            set opts(var) myvar
        }
        set value [get_hcounter_value $hcounter -format $opts(format) \
                       -scale $opts(scale) -full $opts(full) \
                       -var $opts(var)]
    } finally {
        if {[info exists hcounter]} {
            remove_perf_counter $hcounter
        }
        close_perf_query $hquery
    }

    return $value
}


#
# Constructs one or more counter paths for getting process information. 
# Returned as a list of sublists. Each sublist corresponds to a counter path 
# and has the form {counteroptionname datatype counterpath rate}
# datatype is the recommended format when retrieving counter value (eg. double)
# rate is 0 or 1 depending on whether the counter is a rate based counter or 
# not (requires at least two readings when getting the value)
proc twapi::get_perf_process_counter_paths {pids args} {
    variable _process_counter_opt_map

    if {![info exists _counter_opt_map]} {
        #  "descriptive string" format rate
        array set _process_counter_opt_map {
            privilegedutilization {"% Privileged Time"   double 1}
            processorutilization  {"% Processor Time"    double 1}
            userutilization       {"% User Time"         double 1}
            parent                {"Creating Process ID" long   0}
            elapsedtime           {"Elapsed Time"        large  0}
            handlecount           {"Handle Count"        long   0}
            pid                   {"ID Process"          long   0}
            iodatabytesrate       {"IO Data Bytes/sec"   large  1}
            iodataopsrate         {"IO Data Operations/sec"  large 1}
            iootherbytesrate      {"IO Other Bytes/sec"      large 1}
            iootheropsrate        {"IO Other Operations/sec" large 1}
            ioreadbytesrate       {"IO Read Bytes/sec"       large 1}
            ioreadopsrate         {"IO Read Operations/sec"  large 1}
            iowritebytesrate      {"IO Write Bytes/sec"      large 1}
            iowriteopsrate        {"IO Write Operations/sec" large 1}
            pagefaultrate         {"Page Faults/sec"         large 0}
            pagefilebytes         {"Page File Bytes"         large 0}
            pagefilebytespeak     {"Page File Bytes Peak"    large 0}
            poolnonpagedbytes     {"Pool Nonpaged Bytes"     large 0}
            poolpagedbytes        {"Pool Paged Bytes"        large 1}
            basepriority          {"Priority Base"           large 1}
            privatebytes          {"Private Bytes"           large 1}
            threadcount           {"Thread Count"            large 1}
            virtualbytes          {"Virtual Bytes"           large 1}
            virtualbytespeak      {"Virtual Bytes Peak"      large 1}
            workingset            {"Working Set"             large 1}
            workingsetpeak        {"Working Set Peak"        large 1}
        }
    }

    set optdefs {
        machine.arg
        datasource.arg
        all
        refresh
    }

    # Add counter names to option list
    foreach cntr [array names _process_counter_opt_map] {
        lappend optdefs $cntr
    }

    # Parse options
    array set opts [parseargs args $optdefs -nulldefault]

    # Force a refresh of object items
    if {$opts(refresh)} {
        # Silently ignore. The above counters are predefined and refreshing
        # is just a time-consuming no-op. Keep the option for backward
        # compatibility
        if {0} {
            _refresh_perf_objects $opts(machine) $opts(datasource)
        }
    }

    # TBD - could we not use get_perf_instance_counter_paths instead of rest of this code

    # Get the path to the process.
    set pid_paths [get_perf_counter_paths \
                       [_localize_perf_counter "Process"] \
                       [list [_localize_perf_counter "ID Process"]] \
                       $pids \
                       -machine $opts(machine) -datasource $opts(datasource) \
                       -all]

    if {[llength $pid_paths] == 0} {
        # No thread
        return [list ]
    }

    # Construct the requested counter paths
    set counter_paths [list ]
    foreach {pid pid_path} $pid_paths {

        # We have to filter out an entry for _Total which might be present
        # if pid includes "0"
        # TBD - does _Total need to be localized?
        if {$pid == 0 && [string match -nocase *_Total\#0* $pid_path]} {
            continue
        }

        # Break it down into components and store in array
        array set path_components [parse_perf_counter_path $pid_path]

        # Construct counter paths for this pid
        foreach {opt counter_info} [array get _process_counter_opt_map] {
            if {$opts(all) || $opts($opt)} {
                lappend counter_paths \
                    [list -$opt $pid [lindex $counter_info 1] \
                         [make_perf_counter_path $path_components(object) \
                              [_localize_perf_counter [lindex $counter_info 0]] \
                              -machine $path_components(machine) \
                              -parent $path_components(parent) \
                              -instance $path_components(instance) \
                              -instanceindex $path_components(instanceindex)] \
                         [lindex $counter_info 2] \
                        ]
            }
        }                        
    }

    return $counter_paths
}


# Returns the counter path for the process with the given pid. This includes
# the pid counter path element
proc twapi::get_perf_process_id_path {pid args} {
    return [get_unique_counter_path \
                [_localize_perf_counter "Process"] \
                [_localize_perf_counter "ID Process"] $pid]
}


#
# Constructs one or more counter paths for getting thread information. 
# Returned as a list of sublists. Each sublist corresponds to a counter path 
# and has the form {counteroptionname datatype counterpath rate}
# datatype is the recommended format when retrieving counter value (eg. double)
# rate is 0 or 1 depending on whether the counter is a rate based counter or 
# not (requires at least two readings when getting the value)
proc twapi::get_perf_thread_counter_paths {tids args} {
    variable _thread_counter_opt_map

    if {![info exists _thread_counter_opt_map]} {
        array set _thread_counter_opt_map {
            privilegedutilization {"% Privileged Time"       double 1}
            processorutilization  {"% Processor Time"        double 1}
            userutilization       {"% User Time"             double 1}
            contextswitchrate     {"Context Switches/sec"    long 1}
            elapsedtime           {"Elapsed Time"            large 0}
            pid                   {"ID Process"              long 0}
            tid                   {"ID Thread"               long 0}
            basepriority          {"Priority Base"           long 0}
            priority              {"Priority Current"        long 0}
            startaddress          {"Start Address"           large 0}
            state                 {"Thread State"            long 0}
            waitreason            {"Thread Wait Reason"      long 0}
        }
    }

    set optdefs {
        machine.arg
        datasource.arg
        all
        refresh
    }

    # Add counter names to option list
    foreach cntr [array names _thread_counter_opt_map] {
        lappend optdefs $cntr
    }

    # Parse options
    array set opts [parseargs args $optdefs -nulldefault]

    # Force a refresh of object items
    if {$opts(refresh)} {
        # Silently ignore. The above counters are predefined and refreshing
        # is just a time-consuming no-op. Keep the option for backward
        # compatibility
        if {0} {
            _refresh_perf_objects $opts(machine) $opts(datasource)
        }
    }

    # TBD - could we not use get_perf_instance_counter_paths instead of rest of this code

    # Get the path to the thread
    set tid_paths [get_perf_counter_paths \
                       [_localize_perf_counter "Thread"] \
                       [list [_localize_perf_counter "ID Thread"]] \
                       $tids \
                      -machine $opts(machine) -datasource $opts(datasource) \
                      -all]
    
    if {[llength $tid_paths] == 0} {
        # No thread
        return [list ]
    }

    # Now construct the requested counter paths
    set counter_paths [list ]
    foreach {tid tid_path} $tid_paths {
        # Break it down into components and store in array
        array set path_components [parse_perf_counter_path $tid_path]
        foreach {opt counter_info} [array get _thread_counter_opt_map] {
            if {$opts(all) || $opts($opt)} {
                lappend counter_paths \
                    [list -$opt $tid [lindex $counter_info 1] \
                         [make_perf_counter_path $path_components(object) \
                              [_localize_perf_counter [lindex $counter_info 0]] \
                              -machine $path_components(machine) \
                              -parent $path_components(parent) \
                              -instance $path_components(instance) \
                              -instanceindex $path_components(instanceindex)] \
                         [lindex $counter_info 2]
                    ]
            }
        }                            
    }

    return $counter_paths
}


# Returns the counter path for the thread with the given tid. This includes
# the tid counter path element
proc twapi::get_perf_thread_id_path {tid args} {

    return [get_unique_counter_path [_localize_perf_counter"Thread"] [_localize_perf_counter "ID Thread"] $tid]
}


#
# Constructs one or more counter paths for getting processor information. 
# Returned as a list of sublists. Each sublist corresponds to a counter path 
# and has the form {counteroptionname datatype counterpath rate}
# datatype is the recommended format when retrieving counter value (eg. double)
# rate is 0 or 1 depending on whether the counter is a rate based counter or 
# not (requires at least two readings when getting the value)
# $processor should be the processor number or "" to get total
proc twapi::get_perf_processor_counter_paths {processor args} {
    variable _processor_counter_opt_map

    if {![string is integer -strict $processor]} {
        if {[string length $processor]} {
            error "Processor id must be an integer or null to retrieve information for all processors"
        }
        set processor "_Total"
    }

    if {![info exists _processor_counter_opt_map]} {
        array set _processor_counter_opt_map {
            dpcutilization        {"% DPC Time"              double 1}
            interruptutilization  {"% Interrupt Time"        double 1}
            privilegedutilization {"% Privileged Time"       double 1}
            processorutilization  {"% Processor Time"        double 1}
            userutilization       {"% User Time"             double 1}
            apcbypassrate         {"APC Bypasses/sec"        double 1}
            dpcbypassrate         {"DPC Bypasses/sec"        double 1}
            dpcrate               {"DPC Rate"                double 1}
            dpcqueuerate          {"DPCs Queued/sec"         double 1}
            interruptrate         {"Interrupts/sec"          double 1}
        }
    }

    set optdefs {
        machine.arg
        datasource.arg
        all
        refresh
    }

    # Add counter names to option list
    foreach cntr [array names _processor_counter_opt_map] {
        lappend optdefs $cntr
    }

    # Parse options
    array set opts [parseargs args $optdefs -nulldefault -maxleftover 0]

    # Force a refresh of object items
    if {$opts(refresh)} {
        # Silently ignore. The above counters are predefined and refreshing
        # is just a time-consuming no-op. Keep the option for backward
        # compatibility
        if {0} {
            _refresh_perf_objects $opts(machine) $opts(datasource)
        }
    }

    # Now construct the requested counter paths
    set counter_paths [list ]
    foreach {opt counter_info} [array get _processor_counter_opt_map] {
        if {$opts(all) || $opts($opt)} {
            lappend counter_paths \
                [list $opt $processor [lindex $counter_info 1] \
                     [make_perf_counter_path \
                          [_localize_perf_counter "Processor"] \
                          [_localize_perf_counter [lindex $counter_info 0]] \
                          -machine $opts(machine) \
                          -instance $processor] \
                     [lindex $counter_info 2] \
                    ]
        }
    }

    return $counter_paths
}



#
# Returns a list comprising of the counter paths for counters with
# names in the list $counters from those instance(s) whose counter
# $key_counter matches the specified $key_counter_value
proc twapi::get_perf_instance_counter_paths {object counters
                                             key_counter key_counter_values
                                             args} {
    # Parse options
    array set opts [parseargs args {
        machine.arg
        datasource.arg
        {matchop.arg "exact"}
        skiptotal.bool
        refresh
    } -nulldefault]

    # Force a refresh of object items
    if {$opts(refresh)} {
        _refresh_perf_objects $opts(machine) $opts(datasource)
    }

    # Get the list of instances that have the specified value for the
    # key counter
    set instance_paths [get_perf_counter_paths $object \
                            [list $key_counter] $key_counter_values \
                            -machine $opts(machine) \
                            -datasource $opts(datasource) \
                            -matchop $opts(matchop) \
                            -skiptotal $opts(skiptotal) \
                            -all]

    # Loop through all instance paths, and all counters to generate 
    # We store in an array to get rid of duplicates
    array set counter_paths {}
    foreach {key_counter_value instance_path} $instance_paths {
        # Break it down into components and store in array
        array set path_components [parse_perf_counter_path $instance_path]

        # Now construct the requested counter paths
        foreach counter $counters {
            set counter_path \
                [make_perf_counter_path $path_components(object) \
                     $counter \
                     -machine $path_components(machine) \
                     -parent $path_components(parent) \
                     -instance $path_components(instance) \
                     -instanceindex $path_components(instanceindex)]
            set counter_paths($counter_path) ""
        }                            
    }

    return [array names counter_paths]


}


#
# Returns a list comprising of the counter paths for all counters
# whose values match the specified criteria
proc twapi::get_perf_counter_paths {object counters counter_values args} {
    array set opts [parseargs args {
        machine.arg
        datasource.arg
        {matchop.arg "exact"}
        skiptotal.bool
        all
        refresh
    } -nulldefault]

    if {$opts(refresh)} {
        _refresh_perf_objects $opts(machine) $opts(datasource)
    }

    set items [get_perf_object_items $object \
                   -machine $opts(machine) \
                   -datasource $opts(datasource)]
    foreach {object_counters object_instances} $items {break}

    if {[llength $counters]} {
        set object_counters $counters
    }
    set paths [_make_counter_path_list \
                   $object $object_instances $object_counters \
                   -skiptotal $opts(skiptotal) -machine $opts(machine)]
    set result_paths [list ]
    try {
        # Set up the query with the process id for all processes
        set hquery [open_perf_query -datasource $opts(datasource)]
        foreach path $paths {
            set hcounter [add_perf_counter $hquery $path]
            set lookup($hcounter) $path
        }

        # Now collect the info
        collect_perf_query_data $hquery
        
        # Now lookup each counter value to find a matching one
        foreach hcounter [array names lookup] {
            if {! [get_hcounter_value $hcounter -var value]} {
                # Counter or instance no longer exists
                continue
            }

            #puts "$lookup($hcounter): $value"
            set match_pos [lsearch -$opts(matchop) $counter_values $value]
            if {$match_pos >= 0} {
                lappend result_paths \
                    [lindex $counter_values $match_pos] $lookup($hcounter)
                if {! $opts(all)} {
                    break
                }
            }
        }
    } finally {
        # TBD - should we have a catch to throw errors?
        foreach hcounter [array names lookup] {
            remove_perf_counter $hcounter
        }
        close_perf_query $hquery
    }

    return $result_paths
}


#
# Returns the counter path for counter $counter with a value $value
# for object $object. Returns "" on no matches but exception if more than one
proc twapi::get_unique_counter_path {object counter value args} {
    set matches [eval [list get_perf_counter_paths $object [list $counter ] [list $value]] $args -all]
    if {[llength $matches] > 1} {
        error "Multiple counter paths found matching criteria object='$object' counter='$counter' value='$value"
    }
    return [lindex $matches 0]
}



#
# Utilities
# 
proc twapi::_refresh_perf_objects {machine datasource} {
    get_perf_objects -refresh
    return
}


#
# Return the localized form of a counter name
# TBD - assumes machine is local machine!
proc twapi::_localize_perf_counter {name} {
    variable _perf_counter_ids
    variable _localized_perf_counter_names
    
    set name_index [string tolower $name]

    # If we already have a translation, return it
    if {[info exists _localized_perf_counter_names($name_index)]} {
        return $_localized_perf_counter_names($name_index)
    }

    # TBD - windows NT 4.0 does not have the PdhLookup* functions
    if {! [min_os_version 5]} {
        set _localized_perf_counter_names($name_index) $name
        return $name
    }

    # Didn't already have it. Go generate the mappings

    # Get the list of counter names in English if we don't already have it
    if {![info exists _perf_counter_ids]} {
        foreach {id label} [registry get {HKEY_PERFORMANCE_DATA} {Counter 009}] {
            set _perf_counter_ids([string tolower $label]) $id
        }
    }

    # If we have do not have id for the given name, we will just use
    # the passed name as the localized version
    if {! [info exists _perf_counter_ids($name_index)]} {
        # Does not seem to exist. Just set localized name to itself
        return [set _localized_perf_counter_names($name_index) $name]
    }

    # We do have an id. THen try to get a translated name
    if {[catch {PdhLookupPerfNameByIndex "" $_perf_counter_ids($name_index)} xname]} {
        set _localized_perf_counter_names($name_index) $name
    } else {
        set _localized_perf_counter_names($name_index) $xname
    }

    return $_localized_perf_counter_names($name_index)
}


# Given a list of instances and counters, return a cross product of the 
# corresponding counter paths.
# Example: _make_counter_path_list "Process" (instance list) {{ID Process} {...}}
# TBD - bug - does not handle -parent in counter path
proc twapi::_make_counter_path_list {object instance_list counter_list args} {
    array set opts [parseargs args {
        machine.arg
        skiptotal.bool
    } -nulldefault]

    array set instances {}
    foreach instance $instance_list {
        if {![info exists instances($instance)]} {
            set instances($instance) 1
        } else {
            incr instances($instance)
        }
    }

    if {$opts(skiptotal)} {
        # TBD - does this need to be localized
        catch {array unset instances "*_Total"}
    }

    set counter_paths [list ]
    foreach {instance count} [array get instances] {
        while {$count} {
            incr count -1
            foreach counter $counter_list {
                lappend counter_paths [make_perf_counter_path \
                                           $object $counter \
                                           -machine $opts(machine) \
                                           -instance $instance \
                                           -instanceindex $count]
            }
        }
    }

    return $counter_paths
}


#
# Given a set of counter paths in the format returned by 
# get_perf_thread_counter_paths, get_perf_processor_counter_paths etc.
# return the counter information as a flat list of field value pairs
proc twapi::get_perf_values_from_metacounter_info {metacounters args} {
    array set opts [parseargs args {{interval.int 100}}]

    set result [list ]
    set counters [list ]
    if {[llength $metacounters]} {
        set hquery [open_perf_query]
        try {
            set counter_info [list ]
            set need_wait 0
            foreach counter_elem $metacounters {
                foreach {pdh_opt key data_type counter_path wait} $counter_elem {break}
                incr need_wait $wait
                set hcounter [add_perf_counter $hquery $counter_path]
                lappend counters $hcounter
                lappend counter_info $pdh_opt $key $counter_path $data_type $hcounter
            }
            
            collect_perf_query_data $hquery
            if {$need_wait} {
                after $opts(interval)
                collect_perf_query_data $hquery
            }
            
            foreach {pdh_opt key counter_path data_type hcounter} $counter_info {
                if {[get_hcounter_value $hcounter -format $data_type -var value]} {
                    lappend result $pdh_opt $key $value
                }
            }
        } onerror {} {
            #puts "Error: $msg"
        } finally {
            foreach hcounter $counters {
                remove_perf_counter $hcounter
            }
            close_perf_query $hquery
        }
    }

    return $result

}

Added Binaries/Windows/twapi/pkgIndex.tcl.
























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
# WHen script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {$::tcl_platform(os) eq "Windows NT"} {
    namespace eval twapi {
        variable version 1.1
        # Patch level is a period or letter followed by a number (like Tcl)
        # . - release, a - alpha, b - beta
        variable patchlevel .5
    }
    package ifneeded twapi $twapi::version [list source [file join $dir twapi.tcl]]
}
Added Binaries/Windows/twapi/printer.tcl.






























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#
# Copyright (c) 2004-2006 Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

namespace eval twapi {
}

proc twapi::enumerate_printers {args} {
    array set opts [parseargs args {
        {location.arg all {local remote all any}}
    } -maxleftover 0]

    set result [list ]
    foreach elem [Twapi_EnumPrinters_Level4 \
                      [string map {all 6 any 6 local 2 remote 4} $opts(location)] \
                     ] {
        lappend result [list \
                            name [kl_get $elem pPrinterName] \
                            server [kl_get $elem pServerName] \
                            attrs [_symbolize_printer_attributes \
                                       [kl_get $elem Attributes]] \
                           ]
    }
    return $result
}


proc twapi::printer_properties_dialog {name args} {
    array set opts [parseargs args {
        {hwin.int 0}
        {page.arg ""}
    } -maxleftover 0]
    
    shell_object_properties_dialog $name -type printer -hwin $opts(hwin) -page $opts(page)
}



#
# Utilities
# 
proc twapi::_symbolize_printer_attributes {attr} {
    return [_make_symbolic_bitmask $attr {
        queued         0x00000001
        direct         0x00000002
        default        0x00000004
        shared         0x00000008
        network        0x00000010
        hidden         0x00000020
        local          0x00000040
        enabledevq       0x00000080
        keepprintedjobs   0x00000100
        docompletefirst 0x00000200
        workoffline   0x00000400
        enablebidi    0x00000800
        rawonly       0x00001000
        published      0x00002000
        fax            0x00004000
        ts             0x00008000
    }]
}
Added Binaries/Windows/twapi/process.tcl.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
#
# Copyright (c) 2003-2006, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

# TBD - allow access rights to be specified symbolically using procs
# from security.tcl
# TBD - add -user option to get_process_info and get_thread_info
# TBD - add wrapper for GetProcessExitCode

namespace eval twapi {
}

#
# Get my process id
proc twapi::get_current_process_id {} {
    return [::pid]
}

#
# Get my thread id
proc twapi::get_current_thread_id {} {
    return [GetCurrentThreadId]
}

# Return list of process ids
# Note if -path or -name is specified, then processes for which this
# information cannot be obtained are skipped
proc twapi::get_process_ids {args} {

    set save_args $args;                # Need to pass to process_exists
    array set opts [parseargs args {
        user.arg
        path.arg
        name.arg
        logonsession.arg
        glob} -maxleftover 0]

    if {[info exists opts(path)] && [info exists opts(name)]} {
        error "Options -path and -name are mutually exclusive"
    }

    if {$opts(glob)} {
        set match_op match
    } else {
        set match_op equal
    }

    set process_pids [list ]

    # If we do not care about user or path, Twapi_GetProcessList
    # is faster than EnumProcesses or the WTS functions
    if {[info exists opts(user)] == 0 &&
        [info exists opts(logonsession)] == 0 &&
        [info exists opts(path)] == 0} {
        if {[info exists opts(name)] == 0} {
            return [Twapi_GetProcessList -1 0]
        }
        # We need to match against the name
        foreach {pid piddata} [Twapi_GetProcessList -1 2] {
            if {[string $match_op -nocase $opts(name) [kl_get $piddata ProcessName]]} {
                lappend process_pids $pid
            }
        }
        return $process_pids
    }
    
    # Only want pids with a specific user or path

    # If is the name we are looking for, try using the faster WTS
    # API's first. If they are not available, we try a slower method
    # If we need to match paths or logon sessions, we don't try this
    # at all as the wts api's don't provide that info
    if {[info exists opts(path)] == 0 &&
        [info exists opts(logonsession)] == 0} {
        if {[info exists opts(user)]} {
            if {[catch {map_account_to_sid $opts(user)} sid]} {
                # No such user. Return empty list (no processes)
                return [list ]
            }
        }
        if {! [catch {WTSEnumerateProcesses NULL} wtslist]} {
            foreach wtselem $wtslist {
                array set procinfo $wtselem
                if {[info exists sid] &&
                    $procinfo(pUserSid) ne $sid} {
                    continue;           # User does not match
                }
                if {[info exists opts(name)]} {
                    # We need to match on name as well
                    if {![string $match_op -nocase $opts(name) $procinfo(pProcessName)]} {
                        # No match
                        continue
                    }
                }
                lappend process_pids $procinfo(ProcessId)
            }
            return $process_pids
        }
    }

    # Either we are matching on path/logonsession, or the WTS call failed
    # Try yet another way.

    # Note that in the code below, we use "file join" with a single arg
    # to convert \ to /. Do not use file normalize as that will also
    # land up converting relative paths to full paths
    if {[info exists opts(path)]} {
        set opts(path) [file join $opts(path)]
    }

    set process_pids [list ]
    if {[info exists opts(name)]} {
        # Note we may reach here if the WTS call above failed
        foreach {pid piddata} [Twapi_GetProcessList -1 2] {
            if {[string $match_op -nocase $opts(name) [kl_get $piddata ProcessName]]} {
                lappend all_pids $pid
            }
        }
    } else {
        set all_pids [Twapi_GetProcessList -1 0]
    }

    set popts [list ]
    foreach opt {path user logonsession} {
        if {[info exists opts($opt)]} {
            lappend popts -$opt
        }
    }
    foreach {pid piddata} [eval [list get_multiple_process_info $all_pids] $popts] {
        array set pidvals $piddata
        if {[info exists opts(path)] &&
            ![string $match_op -nocase $opts(path) [file join $pidvals(-path)]]} {
            continue
        }

        if {[info exists opts(user)] && $pidvals(-user) ne $opts(user)} {
            continue
        }

        if {[info exists opts(logonsession)] &&
            $pidvals(-logonsession) ne $opts(logonsession)} {
            continue
        }

        lappend process_pids $pid
    }
    return $process_pids
}


# Return list of modules handles for a process
proc twapi::get_process_modules {pid args} {
    variable windefs

    array set opts [parseargs args {handle name path imagedata all}]

    if {$opts(all)} {
        foreach opt {handle name path imagedata} {
            set opts($opt) 1
        }
    }
    set noopts [expr {($opts(name) || $opts(path) || $opts(imagedata) || $opts(handle)) == 0}]

    set privs [expr {$windefs(PROCESS_QUERY_INFORMATION) | $windefs(PROCESS_VM_READ)}]
    set hpid [OpenProcess $privs 0 $pid]
    set results [list ]
    try {
        foreach module [EnumProcessModules $hpid] {
            if {$noopts} {
                lappend results $module
                continue
            }
            set module_data [list ]
            if {$opts(handle)} {
                lappend module_data -handle $module
            }
            if {$opts(name)} {
                if {[catch {GetModuleBaseName $hpid $module} name]} {
                    set name ""
                }
                lappend module_data -name $name
            }
           if {$opts(path)} {
                if {[catch {GetModuleFileNameEx $hpid $module} path]} {
                    set path ""
                }
               lappend module_data -path [_normalize_path $path]
            }
            if {$opts(imagedata)} {
                if {[catch {GetModuleInformation $hpid $module} imagedata]} {
                    set base ""
                    set size ""
                    set entry ""
                } else {
                    array set temp $imagedata
                    set base $temp(lpBaseOfDll)
                    set size $temp(SizeOfImage)
                    set entry $temp(EntryPoint)
                }                
                lappend module_data -imagedata [list $base $size $entry]
            }
            lappend results $module_data
        }
    } finally {
        CloseHandle $hpid
    }
    return $results
}



#
# Get the path of a process
proc twapi::get_process_path {pid args} {
    return [eval [list twapi::_get_process_name_path_helper $pid path] $args]
}


#
# Get the path of a process
proc twapi::get_process_name {pid args} {
    return [eval [list twapi::_get_process_name_path_helper $pid name] $args]
}


# Return list of device drivers
proc twapi::get_device_drivers {args} {
    variable windefs

    array set opts [parseargs args {name path base all}]

    set results [list ]
    foreach module [EnumDeviceDrivers] {
        catch {unset module_data}
        if {$opts(base) || $opts(all)} {
            set module_data [list -base $module]
        }
        if {$opts(name) || $opts(all)} {
            if {[catch {GetDeviceDriverBaseName $module} name]} {
                    set name ""
            }
            lappend module_data -name $name
        }
        if {$opts(path) || $opts(all)} {
            if {[catch {GetDeviceDriverFileName $module} path]} {
                set path ""
            }
            lappend module_data -path [_normalize_path $path]
        }
        if {[info exists module_data]} {
            lappend results $module_data
        }
    }

    return $results
}

#
# Kill a process 
# Returns 1 if process was ended, 0 if not ended within timeout
# 
proc twapi::end_process {pid args} {

    array set opts [parseargs args {
        {exitcode.int 1}
        force
        {wait.int 0}
    }]
    
    set process_path [get_process_path $pid]

    # First try to close nicely
    set toplevels [get_toplevel_windows -pid $pid]
    if {[llength $toplevels]} {
        # Try and close by sending them a message. WM_CLOSE is 0x10
        foreach toplevel $toplevels {
            # Send a message but come back right away
            if {0} {
                catch {PostMessage $toplevel 0x10 0 0}
            } else {
                catch {SendNotifyMessage $toplevel 0x10 0 0}
            }
        }

        # Wait for the specified time to verify process has gone away
        set gone [twapi::wait {process_exists $pid -path $process_path} 0 $opts(wait)]
        if {$gone || ! $opts(force)} {
            # Succeeded or do not want to force a kill
            return $gone
        }
        
        # Only wait 10 ms since we have already waited above
        if {$opts(wait)} {
            set opts(wait) 10
        }
    }

    # Open the process for terminate access. IF access denied (5), retry after
    # getting the required privilege
    try {
        set hpid [OpenProcess $twapi::windefs(PROCESS_TERMINATE) 0 $pid]
    } onerror {TWAPI_WIN32 5} {
        # Retry - if still fail, then just throw the error
        eval_with_privileges {
            set hpid [OpenProcess $twapi::windefs(PROCESS_TERMINATE) 0 $pid]
        } SeDebugPrivilege
    }

    try {
        TerminateProcess $hpid $opts(exitcode)
    } finally {
        CloseHandle $hpid
    }

    if {0} {
        While the process is being terminated, we can get access denied
        if we try to get the path so this if branch is commented out
        return [twapi::wait {process_exists $pid -path $process_path} 0 $opts(wait)]
    } else {
        return [twapi::wait {process_exists $pid} 0 $opts(wait)]
    }
}


# Check if the given process exists
# 0 - does not exist or exists but paths/names do not match, 
# 1 - exists and matches path (or no -path or -name specified)
# -1 - exists but do not know path and cannot compare
proc twapi::process_exists {pid args} {
    array set opts [parseargs args { path.arg name.arg glob}]

    # Simplest case - don't care about name or path
    if {! ([info exists opts(path)] || [info exists opts(name)])} {
        if {[llength [Twapi_GetProcessList $pid 0]] == 0} {
            return 0
        } else {
            return 1
        }
    }

    # Can't specify both name and path
    if {[info exists opts(path)] && [info exists opts(name)]} {
        error "Options -path and -name are mutually exclusive"
    }

    if {$opts(glob)} {
        set string_cmd match
    } else {
        set string_cmd equal
    }

    if {[info exists opts(name)]} {
        # Name is specified
        set piddata [Twapi_GetProcessList $pid 2]
        if {[llength $piddata] &&
            [string $string_cmd -nocase $opts(name) [kl_get [lindex $piddata 1] ProcessName]]} {
            # PID exists and name matches
            return 1
        } else {
            return 0
        }
    }

    # Need to match on the path
    set process_path [get_process_path $pid -noexist "" -noaccess "(unknown)"]
    if {[string length $process_path] == 0} {
        # No such process
        return 0
    }

    # Process with this pid exists
    # Path still has to match
    if {[string equal $process_path "(unknown)"]} {
        # Exists but cannot check path/name
        return -1
    }

    # Note we do not use file normalize here since that will tack on
    # absolute paths which we do not want for glob matching

    # We use [file join ] to convert \ to / to avoid special
    # interpretation of \ in string match command
    return [string $string_cmd -nocase [file join $opts(path)] [file join $process_path]]
}

#
# Get the parent process of a thread. Return "" if no such thread
proc twapi::get_thread_parent_process_id {tid} {
    set status [catch {
        set th [get_thread_handle $tid]
        try {
            set pid [lindex [lindex [Twapi_NtQueryInformationThreadBasicInformation $th] 2] 0]
        } finally {
            close_handles [list $th]
        }
    }]

    if {$status == 0} {
        return $pid
    }


    # Could not use undocumented function. Try slooooow perf counter method
    set pid_paths [get_perf_thread_counter_paths $tid -pid]
    if {[llength $pid_paths] == 0} {
        return ""
    }
    
    if {[get_counter_path_value [lindex [lindex $pid_paths 0] 3] -var pid]} {
        return $pid
    } else {
        return ""
    }
}

#
# Get the thread ids belonging to a process
proc twapi::get_process_thread_ids {pid} {
    return [lindex [lindex [get_multiple_process_info [list $pid] -tids] 1] 1]
}


#
# Get process information 
proc twapi::get_process_info {pid args} {
    return [lindex [eval [list get_multiple_process_info [list $pid]] $args] 1]
}


#
# Get multiple process information 
proc twapi::get_multiple_process_info {pids args} {

    # Options that are directly available from Twapi_GetProcessList
    if {![info exists ::twapi::get_multiple_process_info_base_opts]} {
        # Array value is the flags to pass to Twapi_GetProcessList
        array set ::twapi::get_multiple_process_info_base_opts {
            basepriority       1
            parent             1
            tssession          1
            name               2
            createtime         4
            usertime           4
            privilegedtime     4
            elapsedtime        4
            handlecount        4
            pagefaults         8
            pagefilebytes      8
            pagefilebytespeak  8
            poolnonpagedbytes  8
            poolnonpagedbytespeak  8
            poolpagedbytes     8
            poolpagedbytespeak 8
            threadcount        4
            virtualbytes       8
            virtualbytespeak   8
            workingset         8
            workingsetpeak     8
            tids               32
        }

        # The ones below are not supported on NT 4
        if {[min_os_version 5]} {
            array set ::twapi::get_multiple_process_info_base_opts {
                ioreadops         16
                iowriteops        16
                iootherops        16
                ioreadbytes       16
                iowritebytes      16
                iootherbytes      16
            }
        }
    }

    
    # Note the PDH options match those of twapi::get_process_perf_counter_paths
    set pdh_opts {
        privatebytes
    }

    set pdh_rate_opts {
        privilegedutilization
        processorutilization
        userutilization
        iodatabytesrate
        iodataopsrate
        iootherbytesrate
        iootheropsrate
        ioreadbytesrate
        ioreadopsrate
        iowritebytesrate
        iowriteopsrate
        pagefaultrate
    }

    set token_opts {
        user
        groups
        primarygroup
        privileges
        logonsession
    }

    array set opts [parseargs args \
                        [concat [list all \
                                     pid \
                                     handles \
                                     path \
                                     toplevels \
                                     commandline \
                                     [list noexist.arg "(no such process)"] \
                                     [list noaccess.arg "(unknown)"] \
                                     [list interval.int 100]] \
                             [array names ::twapi::get_multiple_process_info_base_opts] \
                             $token_opts \
                             $pdh_opts \
                             $pdh_rate_opts]]

    array set results {}

    # If user is requested, try getting it through terminal services
    # if possible since the token method fails on some newer platforms
    if {$opts(all) || $opts(user)} {
        _get_wts_pids wtssids wtsnames
    }

    # See if any Twapi_GetProcessList options are requested and if
    # so, calculate the appropriate flags
    set flags 0
    foreach opt [array names ::twapi::get_multiple_process_info_base_opts] {
        if {$opts($opt) || $opts(all)} {
            set flags [expr {$flags | $::twapi::get_multiple_process_info_base_opts($opt)}]
        }
    }
    if {$flags} {
        if {[llength $pids] == 1} {
            array set basedata [twapi::Twapi_GetProcessList [lindex $pids 0] $flags]
        } else {
            array set basedata [twapi::Twapi_GetProcessList -1 $flags]
        }
    }

    foreach pid $pids {
        set result [list ]

        if {$opts(all) || $opts(pid)} {
            lappend result -pid $pid
        }

        foreach {opt field} {
            createtime         CreateTime
            usertime           UserTime
            privilegedtime     KernelTime
            handlecount        HandleCount
            pagefaults         VmCounters.PageFaultCount
            pagefilebytes      VmCounters.PagefileUsage
            pagefilebytespeak  VmCounters.PeakPagefileUsage
            poolnonpagedbytes  VmCounters.QuotaNonPagedPoolUsage
            poolnonpagedbytespeak  VmCounters.QuotaPeakNonPagedPoolUsage
            poolpagedbytespeak     VmCounters.QuotaPeakPagedPoolUsage
            poolpagedbytes     VmCounters.QuotaPagedPoolUsage
            basepriority       BasePriority
            threadcount        ThreadCount
            virtualbytes       VmCounters.VirtualSize
            virtualbytespeak   VmCounters.PeakVirtualSize
            workingset         VmCounters.WorkingSetSize
            workingsetpeak     VmCounters.PeakWorkingSetSize
            ioreadops          IoCounters.ReadOperationCount
            iowriteops         IoCounters.WriteOperationCount
            iootherops         IoCounters.OtherOperationCount
            ioreadbytes        IoCounters.ReadTransferCount
            iowritebytes       IoCounters.WriteTransferCount
            iootherbytes       IoCounters.OtherTransferCount
            parent             InheritedFromProcessId
            tssession          SessionId
        } {
            if {$opts($opt) || $opts(all)} {
                if {[info exists basedata($pid)]} {
                    lappend result -$opt [twapi::kl_get $basedata($pid) $field]
                } else {
                    lappend result -$opt $opts(noexist)
                }
            }
        }

        if {$opts(elapsedtime) || $opts(all)} {
            if {[info exists basedata($pid)]} {
                lappend result -elapsedtime [expr {[clock seconds]-[large_system_time_to_secs [twapi::kl_get $basedata($pid) CreateTime]]}]
            } else {
                lappend result -elapsedtime $opts(noexist)
            }
        }

        if {$opts(tids) || $opts(all)} {
            if {[info exists basedata($pid)]} {
                set tids [list ]
                foreach {tid threaddata} [twapi::kl_get $basedata($pid) Threads] {
                    lappend tids $tid
                }
                lappend result -tids $tids
            } else {
                lappend result -tids $opts(noexist)
            }
        }

        if {$opts(name) || $opts(all)} {
            if {[info exists basedata($pid)]} {
                set name [twapi::kl_get $basedata($pid) ProcessName]
                if {$name eq ""} {
                    if {[is_system_pid $pid]} {
                        set name "System"
                    } elseif {[is_idle_pid $pid]} {
                        set name "System Idle Process"
                    }
                }
                lappend result -name $name
            } else {
                lappend result -name $opts(noexist)
            }
        }
        
        if {$opts(all) || $opts(path)} {
            lappend result -path [get_process_path $pid -noexist $opts(noexist) -noaccess $opts(noaccess)]
        }
        
        if {$opts(all) || $opts(toplevels)} {
            set toplevels [get_toplevel_windows -pid $pid]
            if {[llength $toplevels]} {
                lappend result -toplevels $toplevels
            } else {
                if {[process_exists $pid]} {
                    lappend result -toplevels [list ]
                } else {
                    lappend result -toplevels $opts(noexist)
                }
            }
        }

        # NOTE: we do not check opts(all) for handles since the latter
        # is an unsupported option
        if {$opts(handles)} {
            set handles [list ]
            foreach hinfo [get_open_handles $pid] {
                lappend handles [list [kl_get $hinfo -handle] [kl_get $hinfo -type] [kl_get $hinfo -name]]
            }
            lappend result -handles $handles
        }

        if {$opts(all) || $opts(commandline)} {
            lappend result -commandline [get_process_commandline $pid -noexist $opts(noexist) -noaccess $opts(noaccess)]
        }

        # Now get token related info, if any requested
        set requested_opts [list ]
        if {$opts(all) || $opts(user)} {
            # See if we already have the user. Note sid of system idle
            # will be empty string
            if {[info exists wtssids($pid)]} {
                if {$wtssids($pid) == ""} {
                    # Put user as System
                    lappend result -user "SYSTEM"
                } else {
                    # We speed up account lookup by caching sids
                    if {[info exists sidcache($wtssids($pid))]} {
                        lappend result -user $sidcache($wtssids($pid))
                    } else {
                        set uname [lookup_account_sid $wtssids($pid)]
                        lappend result -user $uname
                        set sidcache($wtssids($pid)) $uname
                    }
                }
            } else {
                lappend requested_opts -user
            }
        }
        foreach opt {groups primarygroup privileges logonsession} {
            if {$opts(all) || $opts($opt)} {
                lappend requested_opts -$opt
            }
        }
        if {[llength $requested_opts]} {
            try {
                eval lappend result [_get_token_info process $pid $requested_opts]
            } onerror {TWAPI_WIN32 5} {
                foreach opt $requested_opts {
                    set tokresult($opt) $opts(noaccess)
                }
                # The NETWORK SERVICE and LOCAL SERVICE processes cannot
                # be accessed. If we are looking for the logon session for
                # these, try getting it from the witssid if we have it
                # since the logon session is hardcoded for these accounts
                if {[lsearch -exact $requested_opts "-logonsession"] >= 0} {
                    if {![info exists wtssids]} {
                        _get_wts_pids wtssids wtsnames
                    }
                    if {[info exists wtssids($pid)]} {
                        # Map user SID to logon session
                        switch -exact -- $wtssids($pid) {
                            S-1-5-18 {
                                # SYSTEM
                                set tokresult(-logonsession) 00000000-000003e7
                            }
                            S-1-5-19 {
                                # LOCAL SERVICE
                                set tokresult(-logonsession) 00000000-000003e5
                            }
                            S-1-5-20 {
                                # LOCAL SERVICE
                                set tokresult(-logonsession) 00000000-000003e4
                            }
                        }
                    }
                }
                set result [concat $result [array get tokresult]]
            } onerror {TWAPI_WIN32 87} {
                foreach opt $requested_opts {
                    lappend result $opt $opts(noexist)
                }
            }
        }

        set results($pid) $result
    }

    # Now deal with the PDH stuff. We need to track what data we managed
    # to get
    array set gotdata {}

    # Now retrieve each PDH non-rate related counter which do not
    # require an interval of measurement
    set wanted_pdh_opts [_array_non_zero_switches opts $pdh_opts $opts(all)]
    if {[llength $wanted_pdh_opts] != 0} {
        set counters [eval [list get_perf_process_counter_paths $pids] \
                          $wanted_pdh_opts]
        foreach {opt pid val} [get_perf_values_from_metacounter_info $counters -interval 0] {
            lappend results($pid) $opt $val
            set gotdata($pid,$opt) 1; # Since we have the data
        }
    }

    # NOw do the rate related counter. Again, we need to track missing data
    set wanted_pdh_rate_opts [_array_non_zero_switches opts $pdh_rate_opts $opts(all)]
    foreach pid $pids {
        foreach opt $wanted_pdh_rate_opts {
            set missingdata($pid,$opt) 1
        }
    }
    if {[llength $wanted_pdh_rate_opts] != 0} {
        set counters [eval [list get_perf_process_counter_paths $pids] \
                          $wanted_pdh_rate_opts]
        foreach {opt pid val} [get_perf_values_from_metacounter_info $counters -interval $opts(interval)] {
            lappend results($pid) $opt $val
            set gotdata($pid,$opt) 1; # Since we have the data
        }
    }

    # For data that we could not get from PDH assume the process does not exist
    foreach pid $pids {
        foreach opt [concat $wanted_pdh_opts $wanted_pdh_rate_opts] {
            if {![info exists gotdata($pid,$opt)]} {
                # Could not get this combination. Assume missing process
                lappend results($pid) $opt $opts(noexist)
            }
        }
    }

    return [array get results]
}


#
# Get thread information 
# TBD - add info from GetGUIThreadInfo
proc twapi::get_thread_info {tid args} {

    # Options that are directly available from Twapi_GetProcessList
    if {![info exists ::twapi::get_thread_info_base_opts]} {
        # Array value is the flags to pass to Twapi_GetProcessList
        array set ::twapi::get_thread_info_base_opts {
            pid 32
            elapsedtime 96
            waittime 96
            usertime 96
            createtime 96
            privilegedtime 96
            contextswitches 96
            basepriority 160
            priority 160
            startaddress 160
            state 160
            waitreason 160
        }
    }

    # Note the PDH options match those of twapi::get_thread_perf_counter_paths
    # Right now, we don't need any PDH non-rate options
    set pdh_opts {
    }
    set pdh_rate_opts {
        privilegedutilization 
        processorutilization
        userutilization
        contextswitchrate
    }

    set token_opts {
        groups
        user
        primarygroup
        privileges
    }

    array set opts [parseargs args \
                        [concat [list all tid [list interval.int 100]] \
                             [array names ::twapi::get_thread_info_base_opts] \
                             $token_opts $pdh_opts $pdh_rate_opts]]

    set requested_opts [_array_non_zero_switches opts $token_opts $opts(all)]
    # Now get token info, if any
    if {[llength $requested_opts]} {
        if {[catch {_get_token_info thread $tid $requested_opts} results]} {
            set erCode $::errorCode
            set erInfo $::errorInfo
            if {[string equal [lindex $erCode 0] "TWAPI_WIN32"] &&
                [lindex $erCode 1] == 1008} {
                # Thread does not have its own token. Use it's parent process
                set results [_get_token_info process [get_thread_parent_process_id $tid] $requested_opts]
            } else {
                error $results $erInfo $erCode
            }
        }
    } else {
        set results [list ]
    }

    # Now get the base options
    set flags 0
    foreach opt [array names ::twapi::get_thread_info_base_opts] {
        if {$opts($opt) || $opts(all)} {
            set flags [expr {$flags | $::twapi::get_thread_info_base_opts($opt)}]
        }
    }

    if {$flags} {
        # We need at least one of the base options
        foreach {pid piddata} [twapi::Twapi_GetProcessList -1 $flags] {
            foreach {thread_id threaddata} [kl_get $piddata Threads] {
                if {$tid == $thread_id} {
                    # Found the thread we want
                    array set threadinfo $threaddata
                    break
                }
            }
            if {[info exists threadinfo]} {
                break;  # Found it, no need to keep looking through other pids
            }
        }
        # It is possible that we looped through all the processs without
        # a thread match. Hence we check again that we have threadinfo
        # Note currently as in older versions, we do not pass back
        # any fields if the thread did not exist. Perhaps that should
        # be changed to behave similar to get_process_info
        if {[info exists threadinfo]} {
            foreach {opt field} {
                pid            ClientId.UniqueProcess
                waittime       WaitTime
                usertime       UserTime
                createtime     CreateTime
                privilegedtime KernelTime
                basepriority   BasePriority
                priority       Priority
                startaddress   StartAddress
                state          State
                waitreason     WaitReason
                contextswitches ContextSwitchCount
            } {
                if {$opts($opt) || $opts(all)} {
                    lappend results -$opt $threadinfo($field)
                }
            }

            if {$opts(elapsedtime) || $opts(all)} {
                lappend results -elapsedtime [expr {[clock seconds]-[large_system_time_to_secs $threadinfo(CreateTime)]}]
            }
        }
    }

    # Now retrieve each PDH non-rate related counter which do not
    # require an interval of measurement
    set requested_opts [_array_non_zero_switches opts $pdh_opts $opts(all)]
    if {[llength $requested_opts] != 0} {
        set counter_list [eval [list get_perf_thread_counter_paths [list $tid]] \
                          $requested_opts]
        foreach {opt tid value} [get_perf_values_from_metacounter_info $counter_list -interval 0] {
            lappend results $opt $value
        }
    }

    # Now do the same for any interval based counters
    set requested_opts [_array_non_zero_switches opts $pdh_rate_opts $opts(all)]
    if {[llength $requested_opts] != 0} {
        set counter_list [eval [list get_perf_thread_counter_paths [list $tid]] \
                          $requested_opts]
        foreach {opt tid value} [get_perf_values_from_metacounter_info $counter_list -interval $opts(interval)] {
            lappend results $opt $value
        }
    }

    if {$opts(all) || $opts(tid)} {
        lappend results -tid $tid
    }

    return $results
}


#
# Wait until the process is ready
proc twapi::process_waiting_for_input {pid args} {
    array set opts [parseargs args {{wait.int 0}}]

    set hpid [OpenProcess $twapi::windefs(PROCESS_QUERY_INFORMATION) 0 $pid]
    try {
        set status [WaitForInputIdle $hpid $opts(wait)]
    } finally {
        CloseHandle $hpid
    }
    return $status
}

#
# Create a process
proc twapi::create_process {path args} {
    array set opts [parseargs args \
                        [list \
                             [list cmdline.arg ""] \
                             [list inheritablechildprocess.bool 0] \
                             [list inheritablechildthread.bool 0] \
                             [list childprocesssecd.arg ""] \
                             [list childthreadsecd.arg ""] \
                             [list inherithandles.bool 0] \
                             [list env.arg ""] \
                             [list startdir.arg ""] \
                             [list inheriterrormode.bool 1] \
                             [list newconsole.bool 0] \
                             [list detached.bool 0] \
                             [list newprocessgroup.bool 0] \
                             [list noconsole.bool 0] \
                             [list separatevdm.bool 0] \
                             [list sharedvdm.bool 0] \
                             [list createsuspended.bool 0] \
                             [list debugchildtree.bool 0] \
                             [list debugchild.bool 0] \
                             [list priority.arg "normal" [list normal abovenormal belownormal high realtime idle]] \
                             [list desktop.arg "__null__"] \
                             [list title.arg ""] \
                             windowpos.arg \
                             windowsize.arg \
                             screenbuffersize.arg \
                             [list feedbackcursoron.bool false] \
                             [list feedbackcursoroff.bool false] \
                             background.arg \
                             foreground.arg \
                             [list fullscreen.bool false] \
                             [list showwindow.arg ""] \
                             [list stdhandles.arg ""] \
                             [list stdchannels.arg ""] \
                             [list returnhandles.bool 0]\
                            ]]
                             
    set process_sec_attr [_make_secattr $opts(childprocesssecd) $opts(inheritablechildprocess)]
    set thread_sec_attr [_make_secattr $opts(childthreadsecd) $opts(inheritablechildthread)]

    # Check incompatible options
    foreach {opt1 opt2} {
        newconsole detached
        sharedvdm  separatevdm
    } {
        if {$opts($opt1) && $opts($opt2)} {
            error "Options -$opt1 and -$opt2 cannot be specified together"
        }
    }
    # Create the start up info structure
    set si_flags 0
    if {[info exists opts(windowpos)]} {
        foreach {xpos ypos} [_parse_integer_pair $opts(windowpos)] break
        setbits si_flags 0x4
    } else {
        set xpos 0
        set ypos 0
    }
    if {[info exists opts(windowsize)]} {
        foreach {xsize ysize} [_parse_integer_pair $opts(windowsize)] break
        setbits si_flags 0x2
    } else {
        set xsize 0
        set ysize 0
    }
    if {[info exists opts(screenbuffersize)]} {
        foreach {xscreen yscreen} [_parse_integer_pair $opts(screenbuffersize)] break
        setbits si_flags 0x8
    } else {
        set xscreen 0
        set yscreen 0
    }

    set fg 7;                           # Default to white
    set bg 0;                           # Default to black
    if {[info exists opts(foreground)]} {
        set fg [_map_console_color $opts(foreground) 0]
        setbits si_flags 0x10
    }
    if {[info exists opts(background)]} {
        set bg [_map_console_color $opts(background) 1]
        setbits si_flags 0x10
    }

    if {$opts(feedbackcursoron)} {
        setbits si_flags 0x40
    }

    if {$opts(feedbackcursoron)} {
        setbits si_flags 0x80
    }

    if {$opts(fullscreen)} {
        setbits si_flags 0x20
    }

    switch -exact -- $opts(showwindow) {
        ""        { }
        hidden    {set opts(showwindow) 0}
        normal    {set opts(showwindow) 1}
        minimized {set opts(showwindow) 2}
        maximized {set opts(showwindow) 3}
        default   {error "Invalid value '$opts(showwindow)' for -showwindow option"}
    }
    if {[string length $opts(showwindow)]} {
        setbits si_flags 0x1
    }
    
    if {[llength $opts(stdhandles)] && [llength $opts(stdchannels)]} {
        error "Options -stdhandles and -stdchannels cannot be used together"
    }

    if {[llength $opts(stdhandles)]} {
        if {! $opts(inherithandles)} {
            error "Cannot specify -stdhandles option if option -inherithandles is specified as 0"
        }
        setbits si_flags 0x100
    }

    if {[llength $opts(stdchannels)]} {
        if {! $opts(inherithandles)} {
            error "Cannot specify -stdhandles option if option -inherithandles is specified as 0"
        }
        if {[llength $opts(stdchannels)] != 3} {
            error "Must specify 3 channels for -stdchannels option corresponding stdin, stdout and stderr"
        }

        setbits si_flags 0x100

        # Convert the channels to handles
        lappend opts(stdhandles) [duplicate_handle [get_tcl_channel_handle [lindex $opts(stdchannels) 0] read] -inherit]
        lappend opts(stdhandles) [duplicate_handle [get_tcl_channel_handle [lindex $opts(stdchannels) 1] write] -inherit]
        lappend opts(stdhandles) [duplicate_handle [get_tcl_channel_handle [lindex $opts(stdchannels) 2] write] -inherit]
    }

    set startup [list $opts(desktop) $opts(title) $xpos $ypos \
                     $xsize $ysize $xscreen $yscreen \
                     [expr {$fg|$bg}] $si_flags $opts(showwindow) \
                     $opts(stdhandles)]

    # Figure out process creation flags
    set flags 0x00000400;               # CREATE_UNICODE_ENVIRONMENT
    foreach {opt flag} {
        debugchildtree       0x00000001
        debugchild           0x00000002
        createsuspended      0x00000004
        detached             0x00000008
        newconsole           0x00000010
        newprocessgroup      0x00000200
        separatevdm          0x00000800
        sharedvdm            0x00001000
        inheriterrormode     0x04000000
        noconsole            0x08000000    
    } {
        if {$opts($opt)} {
            setbits flags $flag
        }
    }

    switch -exact -- $opts(priority) {
        normal      {set priority 0x00000020}
        abovenormal {set priority 0x00008000}
        belownormal {set priority 0x00004000}
        ""          {set priority 0}
        high        {set priority 0x00000080}
        realtime    {set priority 0x00000100}
        idle        {set priority 0x00000040}
        default     {error "Unknown priority '$priority'"}
    }
    setbits flags $priority

    # Create the environment strings
    if {[llength $opts(env)]} {
        set child_env [list ]
        foreach {envvar envval} $opts(env) {
            lappend child_env "$envvar=$envval"
        }
    } else {
        set child_env "__null__"
    }
    
    try {
        foreach {ph th pid tid} [CreateProcess [file nativename $path] \
                                     $opts(cmdline) \
                                     $process_sec_attr $thread_sec_attr \
                                     $opts(inherithandles) $flags $child_env \
                                     [file normalize $opts(startdir)] $startup] {
            break
        }
    } finally {
        # If opts(stdchannels) is not an empty list, we duplicated the handles
        # into opts(stdhandles) ourselves so free them
        if {[llength $opts(stdchannels)]} {
            # Free corresponding handles in opts(stdhandles)
            eval close_handles $opts(stdhandles)
        }
    }

    # From the Tcl source code - (tclWinPipe.c)
    #     /* 
    #      * "When an application spawns a process repeatedly, a new thread 
    #      * instance will be created for each process but the previous 
    #      * instances may not be cleaned up.  This results in a significant 
    #      * virtual memory loss each time the process is spawned.  If there 
    #      * is a WaitForInputIdle() call between CreateProcess() and
    #      * CloseHandle(), the problem does not occur." PSS ID Number: Q124121
    #      */
    # WaitForInputIdle $ph 5000 -- Apparently this is only needed for NT 3.5


    if {$opts(returnhandles)} {
        return [list $pid $tid $ph $th]
    } else {
        CloseHandle $th
        CloseHandle $ph
        return [list $pid $tid]
    }
}


#
# Get a handle to a process
proc twapi::get_process_handle {pid args} {
    array set opts [parseargs args {
        {access.arg process_query_information}
        {inherit.bool 0}
    }]
    return [OpenProcess [_access_rights_to_mask $opts(access)] $opts(inherit) $pid]
}

#
# Get a handle to a thread
proc twapi::get_thread_handle {tid args} {
    array set opts [parseargs args {
        {access.arg thread_query_information}
        {inherit.bool 0}
    }]
    return [OpenThread [_access_rights_to_mask $opts(access)] $opts(inherit) $tid]
}

#
# Suspend a thread
proc twapi::suspend_thread {tid} {
    set htid [OpenProcess $twapi::windefs(THREAD_SUSPEND_RESUME) 0 $tid]
    try {
        set status [SuspendThread $htid]
    } finally {
        CloseHandle $htid
    }
    return $status
}

#
# Resume a thread
proc twapi::resume_thread {tid} {
    set htid [OpenThread $twapi::windefs(THREAD_SUSPEND_RESUME) 0 $tid]
    try {
        set status [ResumeThread $htid]
    } finally {
        CloseHandle $htid
    }
    return $status
}


#
# Get the exit code for a process. Returns "" if still running.
proc twapi::get_process_exit_code {hpid} {
    set code [GetExitCodeProcess $hpid]
    return [expr {$code == 259 ? "" : $code}]
}


#
# Get the command line for a process
proc twapi::get_process_commandline {pid args} {

    if {[is_system_pid $pid] || [is_idle_pid $pid]} {
        return ""
    }

    array set opts [parseargs args {
        {noexist.arg "(no such process)"}
        {noaccess.arg "(unknown)"}
    }]

    try {
        # Assume max command line len is 1024 chars (2048 bytes)
        set max_len 2048
        set hgbl [GlobalAlloc 0 $max_len]
        set pgbl [GlobalLock $hgbl]
        try {
            set hpid [OpenProcess [expr {$twapi::windefs(PROCESS_QUERY_INFORMATION)
                                         | $twapi::windefs(PROCESS_VM_READ)}] \
                          0 \
                          $pid]
        } onerror {TWAPI_WIN32 87} {
            # Process does not exist
            return $opts(noexist)
        }
        
        # Get the address where the PEB is stored - see Nebbett
        set peb_addr [lindex [Twapi_NtQueryInformationProcessBasicInformation $hpid] 1]
        # Read the PEB as binary
        # The pointer to the process information block is the 5th longword
        ReadProcessMemory $hpid [expr {16+$peb_addr}] $pgbl 4
        
        # Convert this to an integer address
        if {![binary scan [Twapi_ReadMemoryBinary $pgbl 0 4] i info_addr]} {
            error "Could not get address of process information block"
        }
        # The pointer to the command line is stored at offset 68
        ReadProcessMemory $hpid [expr {$info_addr + 68}] $pgbl 4
        if {![binary scan [Twapi_ReadMemoryBinary $pgbl 0 4] i cmdline_addr]} {
            error "Could not get address of command line"
        }

        # Now read the command line itself. We do not know the length
        # so assume MAX_PATH (1024) chars (2048 bytes). However, this may
        # fail if the memory beyond the command line is not allocated in the
        # target process. So we have to check for this error and retry with
        # smaller read sizes
        while {$max_len > 128} {
            try {
                ReadProcessMemory $hpid $cmdline_addr $pgbl $max_len
                break
            } onerror {TWAPI_WIN32 299} {
                # Reduce read size
                set max_len [expr {$max_len / 2}]
            }
        }

        # OK, got something. It's in Unicode format, may not be null terminated
        # or may have multiple null terminated strings. THe command line
        # is the first string.
        set cmdline [encoding convertfrom unicode [Twapi_ReadMemoryBinary $pgbl 0 $max_len]]
        set null_offset [string first "\0" $cmdline]
        if {$null_offset >= 0} {
            set cmdline [string range $cmdline 0 [expr {$null_offset-1}]]
        }
        
    } onerror {TWAPI_WIN32 5} {
        # Access denied
        set cmdline $opts(noaccess)
    } finally {
        if {[info exists hpid]} {
            close_handles $hpid
        }
        if {[info exists hgbl]} {
            if {[info exists pgbl]} {
                # We had locked the memory
                GlobalUnlock $hgbl
            }
            GlobalFree $hgbl
        }
    }

    return $cmdline
}


#
# Get process parent - can return ""
proc twapi::get_process_parent {pid args} {
    array set opts [parseargs args {
        {noexist.arg "(no such process)"}
        {noaccess.arg "(unknown)"}
    }]

    if {[is_system_pid $pid] || [is_idle_pid $pid]} {
        return ""
    }

    try {
        set hpid [OpenProcess $twapi::windefs(PROCESS_QUERY_INFORMATION) 0 $pid]
        set parent [lindex [Twapi_NtQueryInformationProcessBasicInformation $hpid] 5]
        
    } onerror {TWAPI_WIN32 5} {
        set error noaccess
    } onerror {TWAPI_WIN32 87} {
        set error noexist
    } finally {
        if {[info exists hpid]} {
            close_handles $hpid
        }
    }

    # TBD - if above fails, try through Twapi_GetProcessList

    if {![info exists parent]} {
        # Try getting through pdh library
        set counters [get_perf_process_counter_paths $pid -parent]
        if {[llength counters]} {
            set vals [get_perf_values_from_metacounter_info $counters -interval 0]
            if {[llength $vals] > 2} {
                set parent [lindex $vals 2]
            }
        }
        if {![info exists parent]} {
            set parent $opts($error)
        }
    }

    return $parent
}

#
# Get the command line
proc twapi::get_command_line {} {
    return [GetCommandLineW]
}

#
# Parse the command line
proc twapi::get_command_line_args {cmdline} {
    # Special check for empty line. CommandLinetoArgv returns process
    # exe name in this case.
    if {[string length $cmdline] == 0} {
        return [list ]
    }
    return [CommandLineToArgv $cmdline]
}



# Return true if passed pid is system
proc twapi::is_system_pid {pid} {
    foreach {major minor} [get_os_version] break
    if {$major == 4 } {
        # NT 4
        set syspid 2
    } elseif {$major == 5 && $minor == 0} {
        # Win2K
        set syspid 8
    } else {
        # XP and Win2K3
        set syspid 4
    }

    # Redefine ourselves and call the redefinition
    proc ::twapi::is_system_pid pid "expr \$pid==$syspid"
    return [is_system_pid $pid]
}

# Return true if passed pid is of idle process
proc twapi::is_idle_pid {pid} {
    return [expr {$pid == 0}]
}


#
# Utility procedures
#


#
# Get the path of a process
proc twapi::_get_process_name_path_helper {pid {type name} args} {
    variable windefs

    array set opts [parseargs args {
        {noexist.arg "(no such process)"}
        {noaccess.arg "(unknown)"}
    }]

    if {![string is integer $pid]} {
        error "Invalid non-numeric pid $pid"
    }
    if {[is_system_pid $pid]} {
        return "System"
    }
    if {[is_idle_pid $pid]} {
        return "System Idle Process"
    }
    # OpenProcess masks off the bottom two bits thereby converting
    # an invalid pid to a real one. We do not want this except on
    # NT 4.0 where PID's can be any number
    if {($pid & 3) && [min_os_version 5]} {
        return $opts(noexist)
    }

    set privs [expr {$windefs(PROCESS_QUERY_INFORMATION) | $windefs(PROCESS_VM_READ)}]

    try {
        set hpid [OpenProcess $privs 0 $pid]
    } onerror {TWAPI_WIN32 87} {
        return $opts(noexist)
    } onerror {TWAPI_WIN32 5} {
        # Access denied
        # If it is the name we want, first try WTS and if that
        # fails try getting it from PDH (slowest)

        if {[string equal $type "name"]} {
            if {! [catch {WTSEnumerateProcesses NULL} wtslist]} {
                foreach wtselem $wtslist {
                    if {[kl_get $wtselem ProcessId] == $pid} {
                        return [kl_get $wtselem pProcessName]
                    }
                }
            }

            # That failed as well, try PDH
            set pdh_path [lindex [lindex [twapi::get_perf_process_counter_paths [list $pid] -pid] 0] 3]
            array set pdhinfo [parse_perf_counter_path $pdh_path]
            return $pdhinfo(instance)
        }                        
        return $opts(noaccess)
    }

    try {
        set module [lindex [EnumProcessModules $hpid] 0]
        if {[string equal $type "name"]} {
            set path [GetModuleBaseName $hpid $module]
        } else {
            set path [_normalize_path [GetModuleFileNameEx $hpid $module]]
        }
    } onerror {TWAPI_WIN32 5} {
        # Access denied
        # On win2k (and may be Win2k3), if the process has exited but some
        # app still has a handle to the process, the OpenProcess succeeds
        # but the EnumProcessModules call returns access denied. So
        # check for this case
        if {[min_os_version 5 0]} {
            # Try getting exit code. 259 means still running.
            # Anything else means process has terminated
            if {[GetExitCodeProcess $hpid] == 259} {
                return $opts(noaccess)
            } else {
                return $opts(noexist)
            }
        } else {
            # Rethrows original error - note try automatically beings these
            # into scope
            error $errorResult $errorInfo $errorCode
        }
    } finally {
        CloseHandle $hpid
    }
    return $path
}

#
# Return various information from a process token
proc twapi::_get_token_info {type id optlist} {
    array set opts [parseargs optlist {
        user
        groups
        primarygroup
        privileges
        logonsession
        {noexist.arg "(no such process)"}
        {noaccess.arg "(unknown)"}
    } -maxleftover 0]

    if {$type == "thread"} {
        set tok [open_thread_token -tid $id -access [list token_query]]
    } else {
        set tok [open_process_token -pid $id -access [list token_query]]
    }
    
    set result [list ]
    try {
        if {$opts(user)} {
            lappend result -user [get_token_user $tok -name]
        }
        if {$opts(groups)} {
            lappend result -groups [get_token_groups $tok -name]
        }
        if {$opts(primarygroup)} {
            lappend result -primarygroup [get_token_primary_group $tok -name]
        }
        if {$opts(privileges)} {
            lappend result -privileges [get_token_privileges $tok -all]
        }
        if {$opts(logonsession)} {
            array set stats [get_token_statistics $tok]
            lappend result -logonsession $stats(authluid)
        }
    } finally {
        close_token $tok
    }

    return $result
}

#
# Fill in arrays with result from WTSEnumerateProcesses if available
proc twapi::_get_wts_pids {v_sids v_names} {
    # Note this call is expected to fail on NT 4.0 without terminal server
    if {! [catch {WTSEnumerateProcesses NULL} wtslist]} {
        upvar $v_sids wtssids
        upvar $v_names wtsnames
        foreach wtselem $wtslist {
            set pid [kl_get $wtselem ProcessId]
            set wtssids($pid) [kl_get $wtselem pUserSid]
            set wtsnames($pid) [kl_get $wtselem pProcessName]
        }
    }
}
Added Binaries/Windows/twapi/security.tcl.






































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
#
# Copyright (c) 2003, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

# TBD - allow SID and account name to be used interchangeably in various
# functions
# TBD - ditto for LUID v/s privilege names

namespace eval twapi {
    # Map privilege level mnemonics to priv level
    array set priv_level_map {guest 0 user 1 admin 2}

    # Map of Sid integer type to Sid type name
    array set sid_type_names {
        1 user 
        2 group
        3 domain 
        4 alias 
        5 wellknowngroup
        6 deletedaccount
        7 invalid
        8 unknown
        9 computer
    }

    # Well known group to SID mapping
    array set well_known_sids {
        nullauthority     S-1-0
        nobody            S-1-0-0
        worldauthority    S-1-1
        everyone          S-1-1-0
        localauthority    S-1-2
        creatorauthority  S-1-3
        creatorowner      S-1-3-0
        creatorgroup      S-1-3-1
        creatorownerserver  S-1-3-2
        creatorgroupserver  S-1-3-3
        ntauthority       S-1-5
        dialup            S-1-5-1
        network           S-1-5-2
        batch             S-1-5-3
        interactive       S-1-5-4
        service           S-1-5-6
        anonymouslogon    S-1-5-7
        proxy             S-1-5-8
        serverlogon       S-1-5-9
        authenticateduser S-1-5-11
        terminalserver    S-1-5-13
        localsystem       S-1-5-18
        localservice      S-1-5-19
        networkservice    S-1-5-20
    }

    # Built-in accounts
    # TBD - see http://support.microsoft.com/?kbid=243330 for more built-ins
    array set builtin_account_sids {
        administrators  S-1-5-32-544
        users           S-1-5-32-545
        guests          S-1-5-32-546
        "power users"   S-1-5-32-547
    }
}

#
# Helper for lookup_account_name{sid,name}
proc twapi::_lookup_account {func account args} {
    if {$func == "LookupAccountSid"} {
        set lookup name
        # If we are mapping a SID to a name, check if it is the logon SID
        # LookupAccountSid returns an error for this SID
        if {[is_valid_sid_syntax $account] &&
            [string match -nocase "S-1-5-5-*" $account]} {
            set name "Logon SID"
            set domain "NT AUTHORITY"
            set type "logonid"
        }
    } else {
        set lookup sid
    }
    array set opts [parseargs args \
                        [list all \
                             $lookup \
                             domain \
                             type \
                             [list system.arg ""]\
                            ]]


    # Lookup the info if have not already hardcoded results
    if {![info exists domain]} {
        foreach "$lookup domain type" [$func $opts(system) $account] break
    }

    set result [list ]
    if {$opts(all) || $opts(domain)} {
        lappend result -domain $domain
    }
    if {$opts(all) || $opts(type)} {
        lappend result -type $twapi::sid_type_names($type)
    }

    if {$opts(all) || $opts($lookup)} {
        lappend result -$lookup [set $lookup]
    }

    # If no options specified, only return the sid/name
    if {[llength $result] == 0} {
        return [set $lookup]
    }

    return $result
}

# Returns the sid, domain and type for an account
proc twapi::lookup_account_name {name args} {
    return [eval [list _lookup_account LookupAccountName $name] $args]
}


# Returns the name, domain and type for an account
proc twapi::lookup_account_sid {sid args} {
    return [eval [list _lookup_account LookupAccountSid $sid] $args]
}

#
# Returns the sid for a account - may be given as a SID or name
proc twapi::map_account_to_sid {account args} {
    array set opts [parseargs args {system.arg} -nulldefault]

    # Treat empty account as null SID (self)
    if {[string length $account] == ""} {
        return ""
    }

    if {[is_valid_sid_syntax $account]} {
        return $account
    } else {
        return [lookup_account_name $account -system $opts(system)]
    }
}


#
# Returns the name for a account - may be given as a SID or name
proc twapi::map_account_to_name {account args} {
    array set opts [parseargs args {system.arg} -nulldefault]

    if {[is_valid_sid_syntax $account]} {
        return [lookup_account_sid $account -system $opts(system)]
    } else {
        # Verify whether a valid account by mapping to an sid
        if {[catch {map_account_to_sid $account -system $opts(system)}]} {
            # As a special case, change LocalSystem to SYSTEM. Some Windows
            # API's (such as services) return LocalSystem which cannot be
            # resolved by the security functions. This name is really the
            # same a the built-in SYSTEM
            if {$account == "LocalSystem"} {
                return "SYSTEM"
            }
            error "Unknown account '$account'"
        } 
        return $account
    }
}

#
# Return the user account for the current process
proc twapi::get_current_user {{format ""}} {
    set user [GetUserName]
    if {$format == ""} {
        return $user
    }
    if {$format == "-sid"} {
        return [map_account_to_sid $user]
    }
    error "Unknown option '$format'"
}

#
# Verify that the given sid is valid. This is purely a syntactic check
proc twapi::is_valid_sid_syntax sid {
    try {
        set result [IsValidSid $sid]
    } onerror {TWAPI_WIN32 1337} {
        set result 0
    }

    return $result
}

#
# Returns token for the process with pid $pid
proc twapi::open_process_token {args} {
    variable windefs

    array set opts [parseargs args {
        pid.int
        {access.arg token_query}
    } -maxleftover 0]

    set access [_access_rights_to_mask $opts(access)]

    # If "Win2K all access" specified, modify for NT 4.0 else we get an error
    if {($access == $windefs(TOKEN_ALL_ACCESS_WIN2K))
        && ([lindex [get_os_version] 0] == 4)} {
        set access $windefs(TOKEN_ALL_ACCESS_WINNT)
    }

    # Get a handle for the process
    if {[info exists opts(pid)]} {
        set ph [OpenProcess $windefs(PROCESS_QUERY_INFORMATION) 0 $opts(pid)]
    } else {
        variable my_process_handle
        set ph $my_process_handle
    }
    try {
        # Get a token for the process
        set ptok [OpenProcessToken $ph $access]
    } finally {
        # Close handle only if we did an OpenProcess
        if {[info exists opts(pid)]} {
            CloseHandle $ph
        }
    }

    return $ptok
}


#
# Returns token for the thread with tid $tid. If $tid is "", current thread
# is assumed
proc twapi::open_thread_token {args} {
    variable windefs

    array set opts [parseargs args {
        tid.int
        {access.arg token_query}
        {self.bool  false}
    } -maxleftover 0]

    set access [_access_rights_to_mask $opts(access)]

    # If "Win2K all access" specified, modify for NT 4.0 else we get an error
    if {($access == $windefs(TOKEN_ALL_ACCESS_WIN2K))
        && ([lindex [get_os_version] 0] == 4)} {
        set access $windefs(TOKEN_ALL_ACCESS_WINNT)
    }

    # Get a handle for the thread
    if {[info exists opts(tid)]} {
        set th [OpenThread $windefs(THREAD_QUERY_INFORMATION) 0 $opts(tid)]
    } else {
        set th [GetCurrentThread]
    }
    try {
        # Get a token for the process
        set ttok [OpenThreadToken $th $access $opts(self)]
    } finally {
        # Close handle only if we did an OpenProcess
        if {[info exists opts(tid)]} {
            CloseHandle $th
        }
    }

    return $ttok
}

#
# Close a token
proc twapi::close_token {tok} {
    CloseHandle $tok
}

#
# Get the user account associated with a token
proc twapi::get_token_user {tok args} {
    array set opts [parseargs args [list name]]
    set user [lindex [GetTokenInformation $tok $twapi::windefs(TokenUser)] 0]
    if {$opts(name)} {
        set user [lookup_account_sid $user]
    }
    return $user
}

#
# Get the groups associated with a token
proc twapi::get_token_groups {tok args} {
    array set opts [parseargs args [list name] -maxleftover 0]

    set groups [list ]
    foreach {group} [GetTokenInformation $tok $twapi::windefs(TokenGroups)] {
        set group [lindex $group 0]
        if {$opts(name)} {
            set group [lookup_account_sid $group]
        }
        lappend groups $group
    }

    return $groups
}

#
# Get the groups associated with a token along with their attributes
# These are returned as a flat list of the form "sid attrlist sid attrlist..."
# where the attrlist is a list of attributes
proc twapi::get_token_group_sids_and_attrs {tok} {
    variable windefs 

    set sids_and_attrs [list ]
    foreach {group} [GetTokenInformation $tok $windefs(TokenGroups)] {
        foreach {sid attr} $group break
        set attr_list {enabled enabled_by_default logon_id
            mandatory owner resource use_for_deny_only}
        lappend sids_and_attrs $sid [_map_token_attr $attr $attr_list SE_GROUP]
    }

    return $sids_and_attrs
}

# Get list of privileges that are currently enabled for the token
# If -all is specified, returns a list {enabled_list disabled_list}
proc twapi::get_token_privileges {tok args} {
    variable windefs

    set all [expr {[lsearch -exact $args -all] >= 0}]

    set enabled_privs [list ]
    set disabled_privs [list ]
    foreach {item} [GetTokenInformation $tok $windefs(TokenPrivileges)] {
        set priv [map_luid_to_privilege [lindex $item 0] -mapunknown]
        if {[lindex $item 1] & $windefs(SE_PRIVILEGE_ENABLED)} {
            lappend enabled_privs $priv
        } else {
            lappend disabled_privs $priv
        }
    }

    if {$all} {
        return [list $enabled_privs $disabled_privs]
    } else {
        return $enabled_privs
    }
}

#
# Return true if the token has the given privilege
proc twapi::check_enabled_privileges {tok privlist args} {
    set all_required [expr {[lsearch -exact $args "-any"] < 0}]

    if {0} {
        We now call the PrivilegeCheck instead. Not sure it matters
        This code also does not handle -any option
        foreach priv $privlist {
            if {[expr {
                       [lsearch -exact [get_token_privileges $tok] $priv] < 0
                   }]} {
                return 0
            }
        }
        return 1
    } else {
        set luid_attr_list [list ]
        foreach priv $privlist {
            lappend luid_attr_list [list [map_privilege_to_luid $priv] 0]
        }
        return [Twapi_PrivilegeCheck $tok $luid_attr_list $all_required]
    }
}


#
# Enable specified privileges. Returns "" if the given privileges were
# already enabled, else returns the privileges that were modified
proc twapi::enable_privileges {privlist} {
    variable my_process_handle

    # Get our process token
    set tok [OpenProcessToken $my_process_handle 0x28]; # QUERY + ADJUST_PRIVS
    try {
        return [enable_token_privileges $tok $privlist]
    } finally {
        close_token $tok
    }
}


#
# Disable specified privileges. Returns "" if the given privileges were
# already enabled, else returns the privileges that were modified
proc twapi::disable_privileges {privlist} {
    variable my_process_handle

    # Get our process token
    set tok [OpenProcessToken $my_process_handle 0x28]; # QUERY + ADJUST_PRIVS
    try {
        return [disable_token_privileges $tok $privlist]
    } finally {
        close_token $tok
    }
}


#
# Execute the given script with the specified privileges.
# After the script completes, the original privileges are restored
proc twapi::eval_with_privileges {script privs args} {
    array set opts [parseargs args {besteffort} -maxleftover 0]

    if {[catch {enable_privileges $privs} privs_to_disable]} {
        if {! $opts(besteffort)} {
            return -code error -errorinfo $::errorInfo \
                -errorcode $::errorCode $privs_to_disable
        }
        set privs_to_disable [list ]
    }

    set code [catch {uplevel $script} result]
    switch $code {
        0 {
            disable_privileges $privs_to_disable
            return $result
        }
        1 {
            # Save error info before calling disable_privileges
            set erinfo $::errorInfo
            set ercode $::errorCode
            disable_privileges $privs_to_disable
            return -code error -errorinfo $::errorInfo \
                -errorcode $::errorCode $result
        }
        default {
            disable_privileges $privs_to_disable
            return -code $code $result
        }
    }
}


# Get the privilege associated with a token and their attributes
proc twapi::get_token_privileges_and_attrs {tok} {
    set privs_and_attrs [list ]
    foreach priv [GetTokenInformation $tok $twapi::windefs(TokenPrivileges)] {
        foreach {luid attr} $priv break
        set attr_list {enabled enabled_by_default used_for_access}
        lappend privs_and_attrs [map_luid_to_privilege $luid -mapunknown] \
            [_map_token_attr $attr $attr_list SE_PRIVILEGE]
    }

    return $privs_and_attrs

}


#
# Get the sid that will be used as the owner for objects created using this
# token. Returns name instead of sid if -name options specified
proc twapi::get_token_owner {tok args} {
    return [ _get_token_sid_field $tok TokenOwner $args]
}


#
# Get the sid that will be used as the primary group for objects created using
# this token. Returns name instead of sid if -name options specified
proc twapi::get_token_primary_group {tok args} {
    return [ _get_token_sid_field $tok TokenPrimaryGroup $args]
}


#
# Return the source of an access token
proc twapi::get_token_source {tok} {
    return [GetTokenInformation $tok $twapi::windefs(TokenSource)]
}


#
# Return the token type of an access token
proc twapi::get_token_type {tok} {
    if {[GetTokenInformation $tok $twapi::windefs(TokenType)]} {
        return "primary"
    } else {
        return "impersonation"
    }
}

#
# Return the token type of an access token
proc twapi::get_token_impersonation_level {tok} {
    return [_map_impersonation_level \
                [GetTokenInformation $tok \
                     $twapi::windefs(TokenImpersonationLevel)]]
}

#
# Return token statistics
proc twapi::get_token_statistics {tok} {
    array set stats {}
    set labels {luid authluid expiration type impersonationlevel
        dynamiccharged dynamicavailable groupcount
        privilegecount modificationluid}
    set statinfo [GetTokenInformation $tok $twapi::windefs(TokenStatistics)]
    foreach label $labels val $statinfo {
        set stats($label) $val
    }
    set stats(type) [expr {$stats(type) == 1 ? "primary" : "impersonation"}]
    set stats(impersonationlevel) [_map_impersonation_level $stats(impersonationlevel)]

    return [array get stats]
}


#
# Enable the privilege state of a token. Generates an error if
# the specified privileges do not exist in the token (either
# disabled or enabled), or cannot be adjusted
proc twapi::enable_token_privileges {tok privs} {
    variable windefs

    set luid_attrs [list]
    foreach priv $privs {
        lappend luid_attrs [list [map_privilege_to_luid $priv] $windefs(SE_PRIVILEGE_ENABLED)]
    }

    set privs [list ]
    foreach {item} [Twapi_AdjustTokenPrivileges $tok 0 $luid_attrs] {
        lappend privs [map_luid_to_privilege [lindex $item 0] -mapunknown]
    }
    return $privs

    

}

#
# Disable the privilege state of a token. Generates an error if
# the specified privileges do not exist in the token (either
# disabled or enabled), or cannot be adjusted
proc twapi::disable_token_privileges {tok privs} {
    set luid_attrs [list]
    foreach priv $privs {
        lappend luid_attrs [list [map_privilege_to_luid $priv] 0]
    }

    set privs [list ]
    foreach {item} [Twapi_AdjustTokenPrivileges $tok 0 $luid_attrs] {
        lappend privs [map_luid_to_privilege [lindex $item 0] -mapunknown]
    }
    return $privs
}

#
# Disable all privs in a token
proc twapi::disable_all_token_privileges {tok} {
    set privs [list ]
    foreach {item} [Twapi_AdjustTokenPrivileges $tok 1 [list ]] {
        lappend privs [map_luid_to_privilege [lindex $item 0] -mapunknown]
    }
    return $privs
}


#
# Get list of users on a system
proc twapi::get_users {args} {
    array set opts [parseargs args {system.arg} -nulldefault]
    return [Twapi_NetUserEnum $opts(system) 0]
}

#
# Add a new user account
proc twapi::new_user {username args} {
    

    array set opts [parseargs args [list \
                                        system.arg \
                                        password.arg \
                                        comment.arg \
                                        [list priv.arg "user" [array names twapi::priv_level_map]] \
                                        home_dir.arg \
                                        script_path.arg \
                                       ] \
                        -nulldefault]

    # NetUserAdd requires the $priv level to be 1 (USER). We change it below
    # using the NetUserSetInfo call
    NetUserAdd $opts(system) $username $opts(password) 1 \
        $opts(home_dir) $opts(comment) 0 $opts(script_path)

    try {
        set_user_priv_level $username $opts(priv) -system $opts(system)
    } onerror {} {
        # Remove the previously created user account
        set ecode $errorCode
        set einfo $errorInfo
        catch {delete_user $username -system $opts(system)}
        error $errorResult $einfo $ecode
    }
}


#
# Delete a user account
proc twapi::delete_user {username args} {
    eval set [parseargs args {system.arg} -nulldefault]

    # Remove the user from the LSA rights database.
    _delete_rights $username $system

    NetUserDel $system $username
}


#
# Define various functions to set various user account fields
foreach field {name password home_dir comment script_path full_name country_code profile home_dir_drive} {
    proc twapi::set_user_$field {username fieldval args} "
        array set opts \[parseargs args {
            system.arg
        } -nulldefault \]
        Twapi_NetUserSetInfo_$field \$opts(system) \$username \$fieldval"
}

#
# Set user privilege level
proc twapi::set_user_priv_level {username priv_level args} {
    eval set [parseargs args {system.arg} -nulldefault]

    if {0} {
        # FOr some reason NetUserSetInfo cannot change priv level
        # Tried it separately with a simple C program. So this code
        # is commented out and we use group membership to achieve
        # the desired result
        if {![info exists twapi::priv_level_map($priv_level)]} {
            error "Invalid privilege level value '$priv_level' specified. Must be one of [join [array names twapi::priv_level_map] ,]"
        }
        set priv $twapi::priv_level_map($priv_level)

        Twapi_NetUserSetInfo_priv $system $username $priv
    } else {
        # Don't hardcode group names - reverse map SID's instead for 
        # non-English systems. Also note that since
        # we might be lowering privilege level, we have to also
        # remove from higher privileged groups
        variable builtin_account_sids
        switch -exact -- $priv_level {
            guest {
                set outgroups {administrators users}
                set ingroup guests
            }
            user  {
                set outgroups {administrators}
                set ingroup users
            }
            admin {
                set outgroups {}
                set ingroup administrators
            }
            default {error "Invalid privilege level '$priv_level'. Must be one of 'guest', 'user' or 'admin'"}
        }
        # Remove from higher priv groups
        foreach outgroup $outgroups {
            # Get the potentially localized name of the group
            set group [lookup_account_sid $builtin_account_sids($outgroup)]
            # Catch since may not be member of that group
            catch {remove_member_from_local_group $group $username}
        }

        # Get the potentially localized name of the group to be added
        set group [lookup_account_sid $builtin_account_sids($ingroup)]
        add_member_to_local_group $group $username
    }
}

#
# Set account expiry time
proc twapi::set_user_expiration {username time args} {
    eval set [parseargs args {system.arg} -nulldefault]

    if {[string equal $time "never"]} {
        set time -1
    } else {
        set time [clock scan $time]
    }

    Twapi_NetUserSetInfo_acct_expires $system $username $time
}

#
# Unlock a user account
proc twapi::unlock_user {username args} {
    eval [list _change_usri3_flags $username $twapi::windefs(UF_LOCKOUT) 0] $args
}

#
# Enable a user account
proc twapi::enable_user {username args} {
    eval [list _change_usri3_flags $username $twapi::windefs(UF_ACCOUNTDISABLE) 0] $args
}

#
# Disable a user account
proc twapi::disable_user {username args} {
    variable windefs
    eval [list _change_usri3_flags $username $windefs(UF_ACCOUNTDISABLE) $windefs(UF_ACCOUNTDISABLE)] $args
}



#
# Return the specified fields for a user account
proc twapi::get_user_account_info {account args} {
    variable windefs

    # Define each option, the corresponding field, and the 
    # information level at which it is returned
    array set fields {
        comment {usri3_comment 1}
        password_expired {usri3_password_expired 3}
        full_name {usri3_full_name 2}
        parms {usri3_parms 2}
        units_per_week {usri3_units_per_week 2}
        primary_group_id {usri3_primary_group_id 3}
        status {usri3_flags 1}
        logon_server {usri3_logon_server 2}
        country_code {usri3_country_code 2}
        home_dir {usri3_home_dir 1}
        password_age {usri3_password_age 1}
        home_dir_drive {usri3_home_dir_drive 3}
        num_logons {usri3_num_logons 2}
        acct_expires {usri3_acct_expires 2}
        last_logon {usri3_last_logon 2}
        user_id {usri3_user_id 3}
        usr_comment {usri3_usr_comment 2}
        bad_pw_count {usri3_bad_pw_count 2}
        code_page {usri3_code_page 2}
        logon_hours {usri3_logon_hours 2}
        workstations {usri3_workstations 2}
        last_logoff {usri3_last_logoff 2}
        name {usri3_name 0}
        script_path {usri3_script_path 1}
        priv {usri3_priv 1}
        profile {usri3_profile 3}
        max_storage {usri3_max_storage 2}
    }
    # Left out - auth_flags {usri3_auth_flags 2}
    # Left out (always returned as NULL) - password {usri3_password 1}


    array set opts [parseargs args \
                        [concat [array names fields] \
                             [list sid local_groups global_groups system.arg all]] \
                       -nulldefault]

    if {$opts(all)} {
        foreach field [array names fields] {
            set opts($field) 1
        }
        set opts(local_groups) 1
        set opts(global_groups) 1
        set opts(sid) 1
    }

    # Based on specified fields, figure out what level info to ask for
    set level 0
    foreach {field fielddata} [array get fields] {
        if {[lindex $fielddata 1] > $level} {
            set level [lindex $fielddata 1]
        }
    }
    
    array set data [NetUserGetInfo $opts(system) $account $level]

    # Extract the requested data
    array set result [list ]
    foreach {field fielddata} [array get fields] {
        if {$opts($field)} {
            set result($field) $data([lindex $fielddata 0])
        }
    }

    # Map internal values to more friendly formats
    if {$opts(status)} {
        if {$result(status) & $windefs(UF_ACCOUNTDISABLE)} {
            set result(status) "disabled"
        } elseif {$result(status) & $windefs(UF_LOCKOUT)} {
            set result(status) "locked"
        } else {
            set result(status) "enabled"
        }
    }

    if {[info exists result(logon_hours)]} {
        binary scan $result(logon_hours) b* result(logon_hours)
    }

    foreach time_field {acct_expires last_logon last_logoff} {
        if {[info exists result($time_field)]} {
            if {$result($time_field) == -1} {
                set result($time_field) "never"
            } elseif {$result($time_field) == 0} {
                set result($time_field) "unknown"
            } else {
                set result($time_field) [clock format $result($time_field) -gmt 1]
            }
        }
    }
    
    if {[info exists result(priv)]} {
        switch -exact -- [expr {$result(priv) & 3}] {
            0 { set result(priv) "guest" }
            1 { set result(priv) "user" }
            2 { set result(priv) "admin" }
        }
    }

    if {$opts(local_groups)} {
        set result(local_groups) [NetUserGetLocalGroups $opts(system) $account 0]
    }

    if {$opts(global_groups)} {
        set result(global_groups) [NetUserGetGroups $opts(system) $account]
    }

    if {$opts(sid)} {
        set result(sid) [lookup_account_name $account]
    }

    return [get_array_as_options result]
}

proc twapi::get_user_local_groups_recursive {account args} {
    array set opts [parseargs args {
        system.arg
    } -nulldefault -maxleftover 0]

    return [NetUserGetLocalGroups $opts(system) [map_account_to_name $account] 1]
}


#
# Set the specified fields for a user account
proc twapi::set_user_account_info {account args} {
    variable windefs

    set notspecified "3kjafnq2or2034r12"; # Some junk

    # Define each option, the corresponding field, and the 
    # information level at which it is returned
    array set opts [parseargs args {
        {system.arg ""}
        comment.arg
        full_name.arg
        country_code.arg
        home_dir.arg
        home_dir.arg
        acct_expires.arg
        name.arg
        script_path.arg
        priv.arg
        profile.arg
    }]

    if {[info exists opts(comment)]} {
        set_user_comment $account $opts(comment) -system $opts(system)
    }

    if {[info exists opts(full_name)]} {
        set_user_full_name $account $opts(full_name) -system $opts(system)
    }

    if {[info exists opts(country_code)]} {
        set_user_country_code $account $opts(country_code) -system $opts(system)
    }

    if {[info exists opts(home_dir)]} {
        set_user_home_dir $account $opts(home_dir) -system $opts(system)
    }

    if {[info exists opts(home_dir_drive)]} {
        set_user_home_dir_drive $account $opts(home_dir_drive) -system $opts(system)
    }

    if {[info exists opts(acct_expires)]} {
        set_user_expiration $account $opts(acct_expires) -system $opts(system)
    }

    if {[info exists opts(name)]} {
        set_user_name $account $opts(name) -system $opts(system)
    }

    if {[info exists opts(script_path)]} {
        set_user_script_path $account $opts(script_path) -system $opts(system)
    }

    if {[info exists opts(priv)]} {
        set_user_priv_level $account $opts(priv) -system $opts(system)
    }

    if {[info exists opts(profile)]} {
        set_user_profile $account $opts(profile) -system $opts(system)
    }
}
                    

proc twapi::get_global_group_info {name args} {
    array set opts [parseargs args {
        {system.arg ""}
        comment
        name
        members
        sid
        all
    } -maxleftover 0]

    set result [list ]
    if {$opts(all) || $opts(sid)} {
        lappend result -sid [lookup_account_name $name -system $opts(system)]
    }
    if {$opts(all) || $opts(comment) || $opts(name)} {
        array set info [NetGroupGetInfo $opts(system) $name 1]
        if {$opts(all) || $opts(name)} {
            lappend result -name $info(grpi3_name)
        }
        if {$opts(all) || $opts(comment)} {
            lappend result -comment $info(grpi3_comment)
        }
    }
    if {$opts(all) || $opts(members)} {
        lappend result -members [get_global_group_members $name -system $opts(system)]
    }
    return $result
}

#
# Get info about a local or global group
proc twapi::get_local_group_info {name args} {
    array set opts [parseargs args {
        {system.arg ""}
        comment
        name
        members
        sid
        all
    } -maxleftover 0]

    set result [list ]
    if {$opts(all) || $opts(sid)} {
        lappend result -sid [lookup_account_name $name -system $opts(system)]
    }
    if {$opts(all) || $opts(comment) || $opts(name)} {
        array set info [NetLocalGroupGetInfo $opts(system) $name 1]
        if {$opts(all) || $opts(name)} {
            lappend result -name $info(lgrpi1_name)
        }
        if {$opts(all) || $opts(comment)} {
            lappend result -comment $info(lgrpi1_comment)
        }
    }
    if {$opts(all) || $opts(members)} {
        lappend result -members [get_local_group_members $name -system $opts(system)]
    }
    return $result
}

#
# Get list of global groups on a system
proc twapi::get_global_groups {args} {
    array set opts [parseargs args {system.arg} -nulldefault]
    return [NetGroupEnum $opts(system)]
}

#
# Get list of local groups on a system
proc twapi::get_local_groups {args} {
    array set opts [parseargs args {system.arg} -nulldefault]
    return [NetLocalGroupEnum $opts(system)]
}


#
# Create a new global group
proc twapi::new_global_group {grpname args} {
    array set opts [parseargs args {
        system.arg
        comment.arg
    } -nulldefault]

    NetGroupAdd $opts(system) $grpname $opts(comment)
}


#
# Create a new local group
proc twapi::new_local_group {grpname args} {
    array set opts [parseargs args {
        system.arg
        comment.arg
    } -nulldefault]

    NetLocalGroupAdd $opts(system) $grpname $opts(comment)
}


#
# Delete a global group
proc twapi::delete_global_group {grpname args} {
    eval set [parseargs args {system.arg} -nulldefault]

    # Remove the group from the LSA rights database.
    _delete_rights $grpname $system

    NetGroupDel $opts(system) $grpname
}

#
# Delete a local group
proc twapi::delete_local_group {grpname args} {
    array set opts [parseargs args {system.arg} -nulldefault]

    # Remove the group from the LSA rights database.
    _delete_rights $grpname $opts(system)

    NetLocalGroupDel $opts(system) $grpname
}


#
# Enumerate members of a global group
proc twapi::get_global_group_members {grpname args} {
    array set opts [parseargs args {system.arg} -nulldefault]

    NetGroupGetUsers $opts(system) $grpname
}

#
# Enumerate members of a local group
proc twapi::get_local_group_members {grpname args} {
    array set opts [parseargs args {system.arg} -nulldefault]

    NetLocalGroupGetMembers $opts(system) $grpname
}

#
# Add a user to a global group
proc twapi::add_user_to_global_group {grpname username args} {
    eval set [parseargs args {system.arg} -nulldefault]

    # No error if already member of the group
    try {
        NetGroupAddUser $system $grpname $username
    } onerror {TWAPI_WIN32 1320} {
        # Ignore
    }
}


#
# Add a user to a local group
proc twapi::add_member_to_local_group {grpname username args} {
    eval set [parseargs args {system.arg} -nulldefault]

    # No error if already member of the group
    try {
        Twapi_NetLocalGroupAddMember $system $grpname $username
    } onerror {TWAPI_WIN32 1378} {
        # Ignore
    }
}


# Remove a user from a global group
proc twapi::remove_user_from_global_group {grpname username args} {
    eval set [parseargs args {system.arg} -nulldefault]

    try {
        NetGroupDelUser $system $grpname $username
    } onerror {TWAPI_WIN32 1321} {
        # Was not in group - ignore
    }
}


# Remove a user from a local group
proc twapi::remove_member_from_local_group {grpname username args} {
    eval set [parseargs args {system.arg} -nulldefault]

    try {
        Twapi_NetLocalGroupDelMember $system $grpname $username
    } onerror {TWAPI_WIN32 1377} {
        # Was not in group - ignore
    }
}


#
# Map a privilege given as a LUID
proc twapi::map_luid_to_privilege {luid args} {
    
    array set opts [parseargs args [list system.arg mapunknown] -nulldefault]

    # luid may in fact be a privilege name. Check for this
    if {[is_valid_luid_syntax $luid]} {
        try {
            set name [LookupPrivilegeName $opts(system) $luid]
        } onerror {TWAPI_WIN32 1313} {
            if {! $opts(mapunknown)} {
                error $errorResult $errorInfo $errorCode
            }
            set name "Privilege-$luid"
        }
    } else {
        # Not a valid LUID syntax. Check if it's a privilege name
        if {[catch {map_privilege_to_luid $luid -system $opts(system)}]} {
            error "Invalid LUID '$luid'"
        }
        return $luid;                   # $luid is itself a priv name
    }

    return $name
}


#
# Map a privilege to a LUID
proc twapi::map_privilege_to_luid {priv args} {
    array set opts [parseargs args [list system.arg] -nulldefault]

    # First check for privilege names we might have generated
    if {[string match "Privilege-*" $priv]} {
        set priv [string range $priv 10 end]
    }

    # If already a LUID format, return as is
    if {[is_valid_luid_syntax $priv]} {
        return $priv
    }
    return [LookupPrivilegeValue $opts(system) $priv]
}


#
# Return 1/0 if in LUID format
proc twapi::is_valid_luid_syntax {luid} {
    return [regexp {^[[:xdigit:]]{8}-[[:xdigit:]]{8}$} $luid]
}


################################################################
# Functions related to ACE's and ACL's

#
# Create a new ACE
proc twapi::new_ace {type account rights args} {
    variable windefs

    array set opts [parseargs args {
        {self.bool 1}
        {recursecontainers.bool 0}
        {recurseobjects.bool 0}
        {recurseonelevelonly.bool 0}
    }]

    set sid [map_account_to_sid $account]

    set access_mask [_access_rights_to_mask $rights]

    switch -exact -- $type {
        allow -
        deny  -
        audit {
            set typecode [_ace_type_symbol_to_code $type]
        }
        default {
            error "Invalid or unsupported ACE type '$type'"
        }
    }

    set inherit_flags 0
    if {! $opts(self)} {
        setbits inherit_flags $windefs(INHERIT_ONLY_ACE)
    }

    if {$opts(recursecontainers)} {
        setbits inherit_flags $windefs(CONTAINER_INHERIT_ACE)
    }

    if {$opts(recurseobjects)} {
        setbits inherit_flags $windefs(OBJECT_INHERIT_ACE)
    }

    if {$opts(recurseonelevelonly)} {
        setbits inherit_flags $windefs(NO_PROPAGATE_INHERIT_ACE)
    }

    return [list $typecode $inherit_flags $access_mask $sid]
}

#
# Get the ace type (allow, deny etc.)
proc twapi::get_ace_type {ace} {
    return [_ace_type_code_to_symbol [lindex $ace 0]]
}


#
# Set the ace type (allow, deny etc.)
proc twapi::set_ace_type {ace type} {
    return [lreplace $ace 0 0 [_ace_type_symbol_to_code $type]]
}

#
# Get the access rights in an ACE
proc twapi::get_ace_rights {ace args} {
    array set opts [parseargs args {type.arg raw} -nulldefault]
    if {$opts(raw)} {
        return [format 0x%x [lindex $ace 2]]
    } else {
        return [_access_mask_to_rights [lindex $ace 2] $opts(type)]
    }
}

#
# Set the access rights in an ACE
proc twapi::set_ace_rights {ace rights} {
    return [lreplace $ace 2 2 [_access_rights_to_mask $rights]]
}


#
# Get the ACE sid
proc twapi::get_ace_sid {ace} {
    return [lindex $ace 3]
}

#
# Set the ACE sid
proc twapi::set_ace_sid {ace account} {
    return [lreplace $ace 3 3 [map_account_to_sid $account]]
}


#
# Get the inheritance options
proc twapi::get_ace_inheritance {ace} {
    variable windefs
    
    set inherit_opts [list ]
    set inherit_mask [lindex $ace 1]

    lappend inherit_opts -self \
        [expr {($inherit_mask & $windefs(INHERIT_ONLY_ACE)) == 0}]
    lappend inherit_opts -recursecontainers \
        [expr {($inherit_mask & $windefs(CONTAINER_INHERIT_ACE)) != 0}]
    lappend inherit_opts -recurseobjects \
        [expr {($inherit_mask & $windefs(OBJECT_INHERIT_ACE)) != 0}]
    lappend inherit_opts -recurseonelevelonly \
        [expr {($inherit_mask & $windefs(NO_PROPAGATE_INHERIT_ACE)) != 0}]
    lappend inherit_opts -inherited \
        [expr {($inherit_mask & $windefs(INHERITED_ACE)) != 0}]

    return $inherit_opts
}

#
# Set the inheritance options. Unspecified options are not set
proc twapi::set_ace_inheritance {ace args} {
    variable windefs

    array set opts [parseargs args {
        self.bool
        recursecontainers.bool
        recurseobjects.bool
        recurseonelevelonly.bool
    }]
    
    set inherit_flags [lindex $ace 1]
    if {[info exists opts(self)]} {
        if {$opts(self)} {
            resetbits inherit_flags $windefs(INHERIT_ONLY_ACE)
        } else {
            setbits   inherit_flags $windefs(INHERIT_ONLY_ACE)
        }
    }

    foreach {
        opt                 mask
    } {
        recursecontainers   CONTAINER_INHERIT_ACE
        recurseobjects      OBJECT_INHERIT_ACE
        recurseonelevelonly NO_PROPAGATE_INHERIT_ACE
    } {
        if {[info exists opts($opt)]} {
            if {$opts($opt)} {
                setbits inherit_flags $windefs($mask)
            } else {
                resetbits inherit_flags $windefs($mask)
            }
        }
    }

    return [lreplace $ace 1 1 $inherit_flags]
}


#
# Sort ACE's in the standard recommended Win2K order
proc twapi::sort_aces {aces} {
    variable windefs

    _init_ace_type_symbol_to_code_map

    foreach type [array names twapi::_ace_type_symbol_to_code_map] {
        set direct_aces($type) [list ]
        set inherited_aces($type) [list ]
    }
    
    # Sort order is as follows: all direct (non-inherited) ACEs come
    # before all inherited ACEs. Within these groups, the order should be
    # access denied ACEs, access denied ACEs for objects/properties,
    # access allowed ACEs, access allowed ACEs for objects/properties,
    foreach ace $aces {
        set type [get_ace_type $ace]
        if {[lindex $ace 1] & $windefs(INHERITED_ACE)} {
            lappend inherited_aces($type) $ace
        } else {
            lappend direct_aces($type) $ace
        }
    }

    # TBD - check this order
    return [concat \
                $direct_aces(deny) \
                $direct_aces(deny_object) \
                $direct_aces(deny_callback) \
                $direct_aces(deny_callback_object) \
                $direct_aces(allow) \
                $direct_aces(allow_object) \
                $direct_aces(allow_compound) \
                $direct_aces(allow_callback) \
                $direct_aces(allow_callback_object) \
                $direct_aces(audit) \
                $direct_aces(audit_object) \
                $direct_aces(audit_callback) \
                $direct_aces(audit_callback_object) \
                $direct_aces(alarm) \
                $direct_aces(alarm_object) \
                $direct_aces(alarm_callback) \
                $direct_aces(alarm_callback_object) \
                $inherited_aces(deny) \
                $inherited_aces(deny_object) \
                $inherited_aces(deny_callback) \
                $inherited_aces(deny_callback_object) \
                $inherited_aces(allow) \
                $inherited_aces(allow_object) \
                $inherited_aces(allow_compound) \
                $inherited_aces(allow_callback) \
                $inherited_aces(allow_callback_object) \
                $inherited_aces(audit) \
                $inherited_aces(audit_object) \
                $inherited_aces(audit_callback) \
                $inherited_aces(audit_callback_object) \
                $inherited_aces(alarm) \
                $inherited_aces(alarm_object) \
                $inherited_aces(alarm_callback) \
                $inherited_aces(alarm_callback_object)]
}

#
# Pretty print an ACE
proc twapi::get_ace_text {ace args} {
    array set opts [parseargs args {
        {resourcetype.arg raw}
        {offset.arg ""}
    } -maxleftover 0]

    if {$ace eq "null"} {
        return "Null"
    }

    set offset $opts(offset)
    array set bools {0 No 1 Yes}
    array set inherit_flags [get_ace_inheritance $ace]
    append inherit_text "${offset}Inherited: $bools($inherit_flags(-inherited))\n"
    append inherit_text "${offset}Include self: $bools($inherit_flags(-self))\n"
    append inherit_text "${offset}Recurse containers: $bools($inherit_flags(-recursecontainers))\n"
    append inherit_text "${offset}Recurse objects: $bools($inherit_flags(-recurseobjects))\n"
    append inherit_text "${offset}Recurse single level only: $bools($inherit_flags(-recurseonelevelonly))\n"
    
    set rights [get_ace_rights $ace -type $opts(resourcetype)]
    if {[lsearch -glob $rights *_all_access] >= 0} {
        set rights "All"
    } else {
        set rights [join $rights ", "]
    }

    append result "${offset}Type: [string totitle [get_ace_type $ace]]\n"
    append result "${offset}User: [map_account_to_name [get_ace_sid $ace]]\n"
    append result "${offset}Rights: $rights\n"
    append result $inherit_text

    return $result
}

#
# Create a new ACL
proc twapi::new_acl {{aces ""}} {
    variable windefs

    set acl_rev $windefs(ACL_REVISION)
    
    foreach ace $aces {
        set ace_typecode [lindex $ace 0]
        if {$ace_typecode != $windefs(ACCESS_ALLOWED_ACE_TYPE) &&
            $ace_typecode != $windefs(ACCESS_DENIED_ACE_TYPE) &&
            $ace_typecode != $windefs(SYSTEM_AUDIT_ACE_TYPE)} {
            set acl_rev $windefs(ACL_REVISION_DS)
            break
        }
    }

    return [list $acl_rev $aces]
}

#
# Return the list of ACE's in an ACL
proc twapi::get_acl_aces {acl} {
    return [lindex $acl 1]
}

#
# Set the ACE's in an ACL
proc twapi::set_acl_aces {acl aces} {
    # Note, we call new_acl since when ACEs change, the rev may also change
    return [new_acl $aces]
}

#
# Append to the ACE's in an ACL
proc twapi::append_acl_aces {acl aces} {
    return [set_acl_aces $acl [concat [get_acl_aces $acl] $aces]]
}

#
# Prepend to the ACE's in an ACL
proc twapi::prepend_acl_aces {acl aces} {
    return [set_acl_aces $acl [concat $aces [get_acl_aces $acl]]]
}

#
# Arrange the ACE's in an ACL in a standard order
proc twapi::sort_acl_aces {acl} {
    return [set_acl_aces $acl [sort_aces [get_acl_aces $acl]]]
}

#
# Return the ACL revision of an ACL
proc twapi::get_acl_rev {acl} {
    return [lindex $acl 0]
}


#
# Create a new security descriptor
proc twapi::new_security_descriptor {args} {
    array set opts [parseargs args {
        owner.arg
        group.arg
        dacl.arg
        sacl.arg
    }]

    set secd [Twapi_InitializeSecurityDescriptor]

    foreach field {owner group dacl sacl} {
        if {[info exists opts($field)]} {
            set secd [set_security_descriptor_$field $secd $opts($field)]
        }
    }

    return $secd
}

#
# Return the control bits in a security descriptor
proc twapi::get_security_descriptor_control {secd} {
    if {[_null_secd $secd]} {
        error "Attempt to get control field from NULL security descriptor."
    }

    set control [lindex $secd 0]
    
    set retval [list ]
    if {$control & 0x0001} {
        lappend retval owner_defaulted
    }
    if {$control & 0x0002} {
        lappend retval group_defaulted
    }
    if {$control & 0x0004} {
        lappend retval dacl_present
    }
    if {$control & 0x0008} {
        lappend retval dacl_defaulted
    }
    if {$control & 0x0010} {
        lappend retval sacl_present
    }
    if {$control & 0x0020} {
        lappend retval sacl_defaulted
    }
    if {$control & 0x0100} {
        lappend retval dacl_auto_inherit_req
    }
    if {$control & 0x0200} {
        lappend retval sacl_auto_inherit_req
    }
    if {$control & 0x0400} {
        lappend retval dacl_auto_inherited
    }
    if {$control & 0x0800} {
        lappend retval sacl_auto_inherited
    }
    if {$control & 0x1000} {
        lappend retval dacl_protected
    }
    if {$control & 0x2000} {
        lappend retval sacl_protected
    }
    if {$control & 0x4000} {
        lappend retval rm_control_valid
    }
    if {$control & 0x8000} {
        lappend retval self_relative
    }
    return $retval
}

#
# Return the owner in a security descriptor
proc twapi::get_security_descriptor_owner {secd} {
    if {[_null_secd $secd]} {
        win32_error 87 "Attempt to get owner field from NULL security descriptor."
    }
    return [lindex $secd 1]
}

#
# Set the owner in a security descriptor
proc twapi::set_security_descriptor_owner {secd account} {
    if {[_null_secd $secd]} {
        set secd [new_security_descriptor]
    }
    set sid [map_account_to_sid $account]
    return [lreplace $secd 1 1 $sid]
}

#
# Return the group in a security descriptor
proc twapi::get_security_descriptor_group {secd} {
    if {[_null_secd $secd]} {
        win32_error 87 "Attempt to get group field from NULL security descriptor."
    }
    return [lindex $secd 2]
}

#
# Set the group in a security descriptor
proc twapi::set_security_descriptor_group {secd account} {
    if {[_null_secd $secd]} {
        set secd [new_security_descriptor]
    }
    set sid [map_account_to_sid $account]
    return [lreplace $secd 2 2 $sid]
}

#
# Return the DACL in a security descriptor
proc twapi::get_security_descriptor_dacl {secd} {
    if {[_null_secd $secd]} {
        win32_error 87 "Attempt to get DACL field from NULL security descriptor."
    }
    return [lindex $secd 3]
}

#
# Set the dacl in a security descriptor
proc twapi::set_security_descriptor_dacl {secd acl} {
    if {[_null_secd $secd]} {
        set secd [new_security_descriptor]
    }
    return [lreplace $secd 3 3 $acl]
}

#
# Return the SACL in a security descriptor
proc twapi::get_security_descriptor_sacl {secd} {
    if {[_null_secd $secd]} {
        win32_error 87 "Attempt to get SACL field from NULL security descriptor."
    }
    return [lindex $secd 4]
}

#
# Set the sacl in a security descriptor
proc twapi::set_security_descriptor_sacl {secd acl} {
    if {[_null_secd $secd]} {
        set secd [new_security_descriptor]
    }
    return [lreplace $secd 4 4 $acl]
}

#
# Get the specified security information for the given object
proc twapi::get_resource_security_descriptor {restype name args} {
    variable windefs

    array set opts [parseargs args {
        owner
        group
        dacl
        sacl
        all
        handle
    }]

    set wanted 0

    foreach field {owner group dacl sacl} {
        if {$opts($field) || $opts(all)} {
            set wanted [expr {$wanted | $windefs([string toupper $field]_SECURITY_INFORMATION)}]
        }
    }

    # Note if no options specified, we ask for everything except
    # SACL's which require special privileges
    if {! $wanted} {
        foreach field {owner group dacl} {
            set wanted [expr {$wanted | $windefs([string toupper $field]_SECURITY_INFORMATION)}]
        }
        set opts($field) 1
    }

    if {$opts(handle)} {
        set secd [Twapi_GetSecurityInfo \
                      [CastToHANDLE $name] \
                      [_map_resource_symbol_to_type $restype false] \
                      $wanted]
    } else {
        # GetNamedSecurityInfo seems to fail with a overlapped i/o
        # in progress error under some conditions. If this happens
        # try getting with resource-specific API's if possible.
        try {
            set secd [Twapi_GetNamedSecurityInfo \
                          $name \
                          [_map_resource_symbol_to_type $restype true] \
                          $wanted]
        } onerror {} {
            # TBD - see what other resource-specific API's there are
            if {$restype eq "share"} {
                set secd [lindex [get_share_info $name -secd] 1]
            } else {
                # Throw the same error
                error $errorResult $errorInfo $errorCode
            }
        }
    }

    return $secd
}


#
# Set the specified security information for the given object
# See http://search.cpan.org/src/TEVERETT/Win32-Security-0.50/README
# for a good discussion even though that applies to Perl
proc twapi::set_resource_security_descriptor {restype name secd args} {
    variable windefs

    array set opts [parseargs args {
        handle
        owner
        group
        dacl
        sacl
        all
        protect_dacl
        unprotect_dacl
        protect_sacl
        unprotect_sacl
    }]

    set mask 0

    if {[min_os_version 5 0]} {
        # Only win2k and above. Ignore otherwise

        if {$opts(protect_dacl) && $opts(unprotect_dacl)} {
            error "Cannot specify both -protect_dacl and -unprotect_dacl."
        }

        if {$opts(protect_dacl)} {
            setbits mask $windefs(PROTECTED_DACL_SECURITY_INFORMATION)
        }
        if {$opts(unprotect_dacl)} {
            setbits mask $windefs(UNPROTECTED_DACL_SECURITY_INFORMATION)
        }

        if {$opts(protect_sacl) && $opts(unprotect_sacl)} {
            error "Cannot specify both -protect_sacl and -unprotect_sacl."
        }

        if {$opts(protect_sacl)} {
            setbits mask $windefs(PROTECTED_SACL_SECURITY_INFORMATION)
        }
        if {$opts(unprotect_sacl)} {
            setbits mask $windefs(UNPROTECTED_SACL_SECURITY_INFORMATION)
        }

    }

    if {$opts(owner) || $opts(all)} {
        set opts(owner) [get_security_descriptor_owner $secd]
        setbits mask $windefs(OWNER_SECURITY_INFORMATION)
    } else {
        set opts(owner) ""
    }

    if {$opts(group) || $opts(all)} {
        set opts(group) [get_security_descriptor_group $secd]
        setbits mask $windefs(GROUP_SECURITY_INFORMATION)
    } else {
        set opts(group) ""
    }

    if {$opts(dacl) || $opts(all)} {
        set opts(dacl) [get_security_descriptor_dacl $secd]
        setbits mask $windefs(DACL_SECURITY_INFORMATION)
    } else {
        set opts(dacl) null
    }

    if {$opts(sacl) || $opts(all)} {
        set opts(sacl) [get_security_descriptor_sacl $secd]
        setbits mask $windefs(SACL_SECURITY_INFORMATION)
    } else {
        set opts(sacl) null
    }

    if {$opts(handle)} {
        SetSecurityInfo \
            [CastToHANDLE $name] \
            [_map_resource_symbol_to_type $restype false] \
            $mask \
            $opts(owner) \
            $opts(group) \
            $opts(dacl) \
            $opts(sacl)
    } else {
        SetNamedSecurityInfo \
            $name \
            [_map_resource_symbol_to_type $restype true] \
            $mask \
            $opts(owner) \
            $opts(group) \
            $opts(dacl) \
            $opts(sacl)
    }
}

#
# Return the text for a security descriptor
proc twapi::get_security_descriptor_text {secd args} {
    if {[_null_secd $secd]} {
        return "null"
    }

    array set opts [parseargs args {
        {resourcetype.arg raw}
    } -maxleftover 0]

    append result "Flags:\t[get_security_descriptor_control $secd]\n"
    append result "Owner:\t[map_account_to_name [get_security_descriptor_owner $secd]]\n"
    append result "Group:\t[map_account_to_name [get_security_descriptor_group $secd]]\n"

    set acl [get_security_descriptor_dacl $secd]
    append result "DACL Rev: [get_acl_rev $acl]\n"
    set index 0
    foreach ace [get_acl_aces $acl] {
        append result "\tDACL Entry [incr index]\n"
        append result "[get_ace_text $ace -offset "\t    " -resourcetype $opts(resourcetype)]"
    }

    set acl [get_security_descriptor_sacl $secd]
    append result "SACL Rev: [get_acl_rev $acl]\n"
    set index 0
    foreach ace [get_acl_aces $acl] {
        append result "\tSACL Entry $index\n"
        append result "[get_ace_text $ace -offset "\t    " -resourcetype $opts(resourcetype)]"
    }

    return $result
}

#
# Get a token for a user
proc twapi::open_user_token {username password args} {
    variable windefs

    array set opts [parseargs args {
        domain.arg
        {type.arg batch}
        {provider.arg default}
    } -nulldefault]

    set typedef "LOGON32_LOGON_[string toupper $opts(type)]"
    if {![info exists windefs($typedef)]} {
        error "Invalid value '$opts(type)' specified for -type option"
    }

    set providerdef "LOGON32_PROVIDER_[string toupper $opts(provider)]"
    if {![info exists windefs($typedef)]} {
        error "Invalid value '$opts(provider)' specified for -provider option"
    }
    
    # If username is of the form user@domain, then domain must not be specified
    # If username is not of the form user@domain, then domain is set to "."
    # if it is empty
    if {[regexp {^([^@]+)@(.+)} $username dummy user domain]} {
        if {[string length $opts(domain)] == 0} {
            error "The -domain option must not be specified when the username is of in UPN format (user@domain)"
        }
    } else {
        if {[string length $opts(domain)] == 0} {
            set opts(domain) "."
        }
    }

    return [LogonUser $username $opts(domain) $password $windefs($typedef) $windefs($providerdef)]
}


#
# Impersonate a user given a token
proc twapi::impersonate_token {token} {
    ImpersonateLoggedOnUser $token
}


#
# Impersonate a user
proc twapi::impersonate_user {args} {
    set token [eval open_user_token $args]
    try {
        impersonate_token $token
    } finally {
        close_token $token
    }
}


#
# Revert to process token
proc twapi::revert_to_self {{opt ""}} {
    RevertToSelf
}


#
# Impersonate self
proc twapi::impersonate_self {level} {
    switch -exact -- $level {
        anonymous      { set level 0 }
        identification { set level 1 }
        impersonation  { set level 2 }
        delegation     { set level 3 }
        default {
            error "Invalid impersonation level $level"
        }
    }
    ImpersonateSelf $level
}


#
# Log off
proc twapi::logoff {args} {
    array set opts [parseargs args {force forceifhung}]
    set flags 0
    if {$opts(force)} {setbits flags 0x4}
    if {$opts(forceifhung)} {setbits flags 0x10}
    ExitWindowsEx $flags 0
}

#
# Lock the workstation
proc twapi::lock_workstation {} {
    LockWorkStation
}

#
# Set a thread token - currently only for current thread
proc twapi::set_thread_token {token} {
    SetThreadToken NULL $token
}

#
# Reset a thread token - currently only for current thread
proc twapi::reset_thread_token {} {
    SetThreadToken NULL NULL
}

#
# Get a handle to a LSA policy
proc twapi::get_lsa_policy_handle {args} {
    array set opts [parseargs args {
        {system.arg ""}
        {access.arg policy_read}
    } -maxleftover 0]

    set access [_access_rights_to_mask $opts(access)]
    return [Twapi_LsaOpenPolicy $opts(system) $access]
}

#
# Close a LSA policy handle
proc twapi::close_lsa_policy_handle {h} {
    LsaClose $h
    return
}

#
# Get rights for an account
proc twapi::get_account_rights {account args} {
    array set opts [parseargs args {
        {system.arg ""}
    } -maxleftover 0]

    set sid [map_account_to_sid $account -system $opts(system)]

    try {
        set lsah [get_lsa_policy_handle -system $opts(system) -access policy_lookup_names]
        return [Twapi_LsaEnumerateAccountRights $lsah $sid]
    } onerror {TWAPI_WIN32 2} {
        # No specific rights for this account
        return [list ]
    } finally {
        if {[info exists lsah]} {
            close_lsa_policy_handle $lsah
        }
    }
}

#
# Get accounts having a specific right
proc twapi::find_accounts_with_right {right args} {
    array set opts [parseargs args {
        {system.arg ""}
        name
    } -maxleftover 0]

    try {
        set lsah [get_lsa_policy_handle \
                      -system $opts(system) \
                      -access {
                          policy_lookup_names
                          policy_view_local_information
                      }]
        set accounts [list ]
        foreach sid [Twapi_LsaEnumerateAccountsWithUserRight $lsah $right] {
            if {$opts(name)} {
                if {[catch {lappend accounts [lookup_account_sid $sid]}]} {
                    # No mapping for SID - can happen if account has been
                    # deleted but LSA policy not updated accordingly
                    lappend accounts $sid
                }
            } else {
                lappend accounts $sid
            }
        }
        return $accounts
    } onerror {TWAPI_WIN32 259} {
        # No accounts have this right
        return [list ]
    } finally {
        if {[info exists lsah]} {
            close_lsa_policy_handle $lsah
        }
    }

}

#
# Add/remove rights to an account
proc twapi::_modify_account_rights {operation account rights args} {
    set switches {
        system.arg
        handle.arg
    }    

    switch -exact -- $operation {
        add {
            # Nothing to do
        }
        remove {
            lappend switches all
        }
        default {
            error "Invalid operation '$operation' specified"
        }
    }

    array set opts [parseargs args $switches -maxleftover 0]

    if {[info exists opts(system)] && [info exists opts(handle)]} {
        error "Options -system and -handle may not be specified together"
    }

    if {[info exists opts(handle)]} {
        set lsah $opts(handle)
        set sid $account
    } else {
        if {![info exists opts(system)]} {
            set opts(system) ""
        }

        set sid [map_account_to_sid $account -system $opts(system)]
        # We need to open a policy handle ourselves. First try to open
        # with max privileges in case the account needs to be created
        # and then retry with lower privileges if that fails
        catch {
            set lsah [get_lsa_policy_handle \
                          -system $opts(system) \
                          -access {
                              policy_lookup_names
                              policy_create_account
                          }]
        }
        if {![info exists lsah]} {
            set lsah [get_lsa_policy_handle \
                          -system $opts(system) \
                          -access policy_lookup_names]
        }
    }

    try {
        if {$operation == "add"} {
            Twapi_LsaAddAccountRights $lsah $sid $rights
        } else {
            Twapi_LsaRemoveAccountRights $lsah $sid $opts(all) $rights
        }
    } finally {
        # Close the handle if we opened it
        if {! [info exists opts(handle)]} {
            close_lsa_policy_handle $lsah
        }
    }
}

interp alias {} twapi::add_account_rights {} twapi::_modify_account_rights add
interp alias {} twapi::remove_account_rights {} twapi::_modify_account_rights remove

#
# Get a new LUID
proc twapi::new_luid {} {
    return [AllocateLocallyUniqueId]
}

#
# TBD - maybe these UUID functions should not be in the security module
# Get a new uuid
proc twapi::new_uuid {{opt ""}} {
    if {[string length $opt]} {
        if {[string equal $opt "-localok"]} {
            set local_ok 1
        } else {
            error "Invalid or unknown argument '$opt'"
        }
    } else {
        set local_ok 0
    }
    return [UuidCreate $local_ok] 
}
proc twapi::nil_uuid {} {
    return [UuidCreateNil]
}


#
# Get the description of a privilege
proc twapi::get_privilege_description {priv} {
    if {[catch {LookupPrivilegeDisplayName "" $priv} desc]} {
        switch -exact -- $priv {
            # The above function will only return descriptions for
            # privileges, not account rights. Hard code descriptions
            # for some account rights
            SeBatchLogonRight { set desc "Log on as a batch job" }
            SeDenyBatchLogonRight { set desc "Deny logon as a batch job" }
            SeDenyInteractiveLogonRight { set desc "Deny logon locally" }
            SeDenyNetworkLogonRight { set desc "Deny access to this computer from the network" }
            SeDenyServiceLogonRight { set desc "Deny logon as a service" }
            SeInteractiveLogonRight { set desc "Log on locally" }
            SeNetworkLogonRight { set desc "Access this computer from the network" }
            SeServiceLogonRight { set desc "Log on as a service" }
            default {set desc ""}
        }
    }
    return $desc
}


# Return list of logon sesionss
proc twapi::find_logon_sessions {args} {
    array set opts [parseargs args {
        user.arg
        type.arg
        tssession.arg
    } -maxleftover 0]

    set luids [LsaEnumerateLogonSessions]
    if {! ([info exists opts(user)] || [info exists opts(type)] ||
           [info exists opts(tssession)])} {
        return $luids
    }


    # Need to get the data for each session to see if it matches
    set result [list ]
    if {[info exists opts(user)]} {
        set sid [map_account_to_sid $opts(user)]
    }
    if {[info exists opts(type)]} {
        set logontypes [list ]
        foreach logontype $opts(type) {
            lappend logontypes [_logon_session_type_code $logontype]
        }
    }

    foreach luid $luids {
        try {
            unset -nocomplain session
            array set session [LsaGetLogonSessionData $luid]

            # For the local system account, no data is returned on some
            # platforms
            if {[array size session] == 0} {
                set session(Sid) S-1-5-18; # SYSTEM
                set session(Session) 0
                set session(LogonType) 0
            }
            if {[info exists opts(user)] && $session(Sid) ne $sid} {
                continue;               # User id does not match
            }

            if {[info exists opts(type)] && [lsearch -exact $logontypes $session(LogonType)] < 0} {
                continue;               # Type does not match
            }

            if {[info exists opts(tssession)] && $session(Session) != $opts(tssession)} {
                continue;               # Term server session does not match
            }

            lappend result $luid

        } onerror {TWAPI_WIN32 1312} {
            # Session no longer exists. Just skip
            continue
        }
    }

    return $result
}


# Return data for a logon session
proc twapi::get_logon_session_info {luid args} {
    array set opts [parseargs args {
        all
        authpackage
        dnsdomain
        logondomain
        logonid
        logonserver
        logontime
        type
        sid
        user
        tssession
        userprincipal
    } -maxleftover 0]

    array set session [LsaGetLogonSessionData $luid]

    # Some fields may be missing on Win2K
    foreach fld {LogonServer DnsDomainName Upn} {
        if {![info exists session($fld)]} {
            set session($fld) ""
        }
    }

    array set result [list ]
    foreach {opt index} {
        authpackage AuthenticationPackage
        dnsdomain   DnsDomainName
        logondomain LogonDomain
        logonid     LogonId
        logonserver LogonServer
        logontime   LogonTime
        type        LogonType
        sid         Sid
        user        UserName
        tssession   Session
        userprincipal Upn
    } {
        if {$opts(all) || $opts($opt)} {
            set result(-$opt) $session($index)
        }
    }

    if {[info exists result(-type)]} {
        set result(-type) [_logon_session_type_symbol $result(-type)]
    }

    return [array get result]
}



################################################################
# Utility and helper functions



# Returns an sid field from a token
proc twapi::_get_token_sid_field {tok field options} {
    array set opts [parseargs options {name}]
    set owner [GetTokenInformation $tok $twapi::windefs($field)]
    if {$opts(name)} {
        set owner [lookup_account_sid $owner]
    }
    return $owner
}


#
# Map a token attribute mask to list of attribute names
proc twapi::_map_token_attr {attr names prefix} {
    variable windefs

    set attrs [list ]
    foreach attr_name $names {
        set attr_mask $windefs(${prefix}_[string toupper $attr_name])
        if {[expr {$attr & $attr_mask}]} {
            lappend attrs $attr_name
        }
    }

    return $attrs
}

#
# Set/reset the given bits in the usri3_flags field for a user account
# mask indicates the mask of bits to set. values indicates the values
# of those bits
proc twapi::_change_usri3_flags {username mask values args} {
    array set opts [parseargs args {
        system.arg
    } -nulldefault -maxleftover 0]

    # Get current flags
    array set data [NetUserGetInfo $opts(system) $username 1]

    # Turn off mask bits and write flags back
    set flags [expr {$data(usri3_flags) & (~ $mask)}]
    # Set the specified bits
    set flags [expr {$flags | ($values & $mask)}]

    # Write new flags back
    Twapi_NetUserSetInfo_flags $opts(system) $username $flags
}


#
# Map a set of access right symbols to a flag. Concatenates
# all the arguments, and then OR's the individual elements. Each
# element may either be a integer or one of the access rights
proc twapi::_access_rights_to_mask {args} {
    variable windefs

    set rights 0
    foreach right [eval concat $args] {
        if {![string is integer $right]} {
            if {$right == "token_all_access"} {
                if {[min_os_version 5 0]} {
                    set right $windefs(TOKEN_ALL_ACCESS_WIN2K)
                } else {
                    set right $windefs(TOKEN_ALL_ACCESS_WIN2K)
                }
            } else {
                if {[catch {set right $windefs([string toupper $right])}]} {
                    error "Invalid access right symbol '$right'"
                }
            }
        }
        set rights [expr {$rights | $right}]
    }

    return $rights
}


#
# Map an access mask to a set of rights
proc twapi::_access_mask_to_rights {access_mask {type ""}} {
    variable windefs

    set rights [list ]

    # The returned list will include rights that map to multiple bits
    # as well as the individual bits. We first add the multiple bits
    # and then the individual bits (since we clear individual bits
    # after adding)

    #
    # Check standard multiple bit masks
    #
    foreach x {STANDARD_RIGHTS_REQUIRED STANDARD_RIGHTS_READ STANDARD_RIGHTS_WRITE STANDARD_RIGHTS_EXECUTE STANDARD_RIGHTS_ALL SPECIFIC_RIGHTS_ALL} {
        if {($windefs($x) & $access_mask) == $windefs($x)} {
            lappend rights [string tolower $x]
        }
    }
    #
    # Check type specific multiple bit masks
    #
    switch -exact -- $type {
        file {
            set masks [list FILE_ALL_ACCESS FILE_GENERIC_READ FILE_GENERIC_WRITE FILE_GENERIC_EXECUTE]
        }
        pipe {
            set masks [list FILE_ALL_ACCESS]
        }
        service {
            set masks [list SERVICE_ALL_ACCESS]
        }
        registry {
            set masks [list KEY_READ KEY_WRITE KEY_EXECUTE KEY_ALL_ACCESS]
        }
        process {
            set masks [list PROCESS_ALL_ACCESS]
        }
        thread {
            set masks [list THREAD_ALL_ACCESS]
        }
        token {
            set masks [list TOKEN_READ TOKEN_WRITE TOKEN_EXECUTE]
            # TOKEN_ALL_ACCESS depends on platform
            if {[min_os_version 5 0]} {
                set token_all_access $windefs(TOKEN_ALL_ACCESS_WIN2K)
            } else {
                set token_all_access $windefs(TOKEN_ALL_ACCESS_WIN2K)
            }
            if {($token_all_access & $access_mask) == $token_all_access} {
                lappend rights "token_all_access"
            }
        }
        desktop {
            # THere is no desktop all access bits
        }
        winsta {
            set masks [list WINSTA_ALL_ACCESS]
        }
        default {
            set masks [list ]
        }
    }

    foreach x $masks {
        if {($windefs($x) & $access_mask) == $windefs($x)} {
            lappend rights [string tolower $x]
        }
    }


    #
    # OK, now map individual bits

    # First map the common bits
    foreach x {DELETE READ_CONTROL WRITE_DAC WRITE_OWNER SYNCHRONIZE} {
        if {$windefs($x) & $access_mask} {
            lappend rights [string tolower $x]
            resetbits access_mask $windefs($x)
        }
    }

    # Then the generic bits
    foreach x {GENERIC_READ GENERIC_WRITE GENERIC_EXECUTE GENERIC_ALL} {
        if {$windefs($x) & $access_mask} {
            lappend rights [string tolower $x]
            resetbits access_mask $windefs($x)
        }
    }

    # Then the type specific
    switch -exact -- $type {
        file {
            set masks {
                FILE_READ_DATA
                FILE_WRITE_DATA
                FILE_APPEND_DATA
                FILE_READ_EA
                FILE_WRITE_EA
                FILE_EXECUTE
                FILE_DELETE_CHILD
                FILE_READ_ATTRIBUTES
                FILE_WRITE_ATTRIBUTES
            }
        }
        pipe {
            set masks {
                FILE_READ_DATA
                FILE_WRITE_DATA
                FILE_CREATE_PIPE_INSTANCE
                FILE_READ_ATTRIBUTES
                FILE_WRITE_ATTRIBUTES
            }
        }
        service {
            set masks {
                SERVICE_QUERY_CONFIG
                SERVICE_CHANGE_CONFIG
                SERVICE_QUERY_STATUS
                SERVICE_ENUMERATE_DEPENDENTS
                SERVICE_START
                SERVICE_STOP
                SERVICE_PAUSE_CONTINUE
                SERVICE_INTERROGATE
                SERVICE_USER_DEFINED_CONTROL
            }
        }
        registry {
            set masks {
                KEY_QUERY_VALUE
                KEY_SET_VALUE
                KEY_CREATE_SUB_KEY
                KEY_ENUMERATE_SUB_KEYS
                KEY_NOTIFY
                KEY_CREATE_LINK
                KEY_WOW64_32KEY
                KEY_WOW64_64KEY
                KEY_WOW64_RES
            }
        }
        process {
            set masks {
                PROCESS_TERMINATE
                PROCESS_CREATE_THREAD
                PROCESS_SET_SESSIONID
                PROCESS_VM_OPERATION
                PROCESS_VM_READ
                PROCESS_VM_WRITE
                PROCESS_DUP_HANDLE
                PROCESS_CREATE_PROCESS
                PROCESS_SET_QUOTA
                PROCESS_SET_INFORMATION
                PROCESS_QUERY_INFORMATION
                PROCESS_SUSPEND_RESUME
            }
        }
        thread {
            set masks {
                THREAD_TERMINATE
                THREAD_SUSPEND_RESUME
                THREAD_GET_CONTEXT
                THREAD_SET_CONTEXT
                THREAD_SET_INFORMATION
                THREAD_QUERY_INFORMATION
                THREAD_SET_THREAD_TOKEN
                THREAD_IMPERSONATE
                THREAD_DIRECT_IMPERSONATION
            }
        }
        token {
            set masks {
                TOKEN_ASSIGN_PRIMARY
                TOKEN_DUPLICATE
                TOKEN_IMPERSONATE
                TOKEN_QUERY
                TOKEN_QUERY_SOURCE
                TOKEN_ADJUST_PRIVILEGES
                TOKEN_ADJUST_GROUPS
                TOKEN_ADJUST_DEFAULT
                TOKEN_ADJUST_SESSIONID
            }
        }
        desktop {
            set masks {
                DESKTOP_READOBJECTS
                DESKTOP_CREATEWINDOW
                DESKTOP_CREATEMENU
                DESKTOP_HOOKCONTROL
                DESKTOP_JOURNALRECORD
                DESKTOP_JOURNALPLAYBACK
                DESKTOP_ENUMERATE
                DESKTOP_WRITEOBJECTS
                DESKTOP_SWITCHDESKTOP
            }
        }
        windowstation -
        winsta {
            set masks {
                WINSTA_ENUMDESKTOPS
                WINSTA_READATTRIBUTES
                WINSTA_ACCESSCLIPBOARD
                WINSTA_CREATEDESKTOP
                WINSTA_WRITEATTRIBUTES
                WINSTA_ACCESSGLOBALATOMS
                WINSTA_EXITWINDOWS
                WINSTA_ENUMERATE
                WINSTA_READSCREEN
            }
        }
        default {
            set masks [list ]
        }
    }

    foreach x $masks {
        if {$windefs($x) & $access_mask} {
            lappend rights [string tolower $x]
            resetbits access_mask $windefs($x)
        }
    }

    # Finally add left over bits if any
    for {set i 0} {$i < 32} {incr i} {
        set x [expr {1 << $i}]
        if {$access_mask & $x} {
            lappend rights [format 0x%.8X $x]
        }
    }

    return $rights
}


#
# Map an ace type symbol (eg. allow) to the underlying ACE type code
proc twapi::_ace_type_symbol_to_code {type} {
    _init_ace_type_symbol_to_code_map
    return $::twapi::_ace_type_symbol_to_code_map($type)
}


#
# Map an ace type code to an ACE type symbol
proc twapi::_ace_type_code_to_symbol {type} {
    _init_ace_type_symbol_to_code_map
    return $::twapi::_ace_type_code_to_symbol_map($type)
}


# Init the arrays used for mapping ACE type symbols to codes and back
proc twapi::_init_ace_type_symbol_to_code_map {} {
    variable windefs

    if {[info exists ::twapi::_ace_type_symbol_to_code_map]} {
        return
    }

    # Define the array. Be careful to "normalize" the integer values
    array set ::twapi::_ace_type_symbol_to_code_map \
        [list \
             allow [expr { $windefs(ACCESS_ALLOWED_ACE_TYPE) + 0 }] \
             deny [expr  { $windefs(ACCESS_DENIED_ACE_TYPE) + 0 }] \
             audit [expr { $windefs(SYSTEM_AUDIT_ACE_TYPE) + 0 }] \
             alarm [expr { $windefs(SYSTEM_ALARM_ACE_TYPE) + 0 }] \
             allow_compound [expr { $windefs(ACCESS_ALLOWED_COMPOUND_ACE_TYPE) + 0 }] \
             allow_object [expr   { $windefs(ACCESS_ALLOWED_OBJECT_ACE_TYPE) + 0 }] \
             deny_object [expr    { $windefs(ACCESS_DENIED_OBJECT_ACE_TYPE) + 0 }] \
             audit_object [expr   { $windefs(SYSTEM_AUDIT_OBJECT_ACE_TYPE) + 0 }] \
             alarm_object [expr   { $windefs(SYSTEM_ALARM_OBJECT_ACE_TYPE) + 0 }] \
             allow_callback [expr { $windefs(ACCESS_ALLOWED_CALLBACK_ACE_TYPE) + 0 }] \
             deny_callback [expr  { $windefs(ACCESS_DENIED_CALLBACK_ACE_TYPE) + 0 }] \
             allow_callback_object [expr { $windefs(ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE) + 0 }] \
             deny_callback_object [expr  { $windefs(ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE) + 0 }] \
             audit_callback [expr { $windefs(SYSTEM_AUDIT_CALLBACK_ACE_TYPE) + 0 }] \
             alarm_callback [expr { $windefs(SYSTEM_ALARM_CALLBACK_ACE_TYPE) + 0 }] \
             audit_callback_object [expr { $windefs(SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE) + 0 }] \
             alarm_callback_object [expr { $windefs(SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE) + 0 }] \
                 ]

    # Now define the array in the other direction
    foreach {sym code} [array get ::twapi::_ace_type_symbol_to_code_map] {
        set ::twapi::_ace_type_code_to_symbol_map($code) $sym
    }
}

#
# Construct a security attributes structure out of a security descriptor
# and inheritance flave
proc twapi::_make_secattr {secd inherit} {
    if {$inherit} {
        set sec_attr [list $secd 1]
    } else {
        if {$secd == ""} {
            # If a security descriptor not specified, keep
            # all security attributes as an empty list (ie. NULL)
            set sec_attr [list ]
        } else {
            set sec_attr [list $secd 0]
        }
    }
    return $sec_attr
}

#
# Map a resource symbol type to value
proc twapi::_map_resource_symbol_to_type {sym {named true}} {
    if {[string is integer $sym]} {
        return $sym
    }

    # Note "window" is not here because window stations and desktops
    # do not have unique names and cannot be used with Get/SetNamedSecurityInfo
    switch -exact -- $sym {
        file      { return 1 }
        service   { return 2 }
        printer   { return 3 }
        registry  { return 4 }
        share     { return 5 }
        kernelobj { return 6 }
    }
    if {$named} {
        error "Resource type '$restype' not valid for named resources."
    }

    switch -exact -- $sym {
        windowstation    { return 7 }
        directoryservice { return 8 }
        directoryserviceall { return 9 }
        providerdefined { return 10 }
        wmiguid { return 111 }
        registrywow6432key { return 12 }
    }

    error "Resource type '$restype' not valid"
}

#
# Map impersonation level to symbol
proc twapi::_map_impersonation_level ilevel {
    switch -exact -- $ilevel {
        0 { return "anonymous" }
        1 { return "identification" }
        2 { return "impersonation" }
        3 { return "delegation" }
        default { return $ilevel }
    }
}

#
# Valid LUID syntax
proc twapi::_is_valid_luid_syntax luid {
    return [regexp {^[[:xdigit:]]{8}-[[:xdigit:]]{8}$} $luid]
}


# Delete rights for an account
proc twapi::_delete_rights {account system} {
    # Remove the user from the LSA rights database. Ignore any errors
    catch {
        remove_account_rights $account {} -all -system $system

        # On Win2k SP1 and SP2, we need to delay a bit for notifications
        # to complete before deleting the account.
        # See http://support.microsoft.com/?id=316827
        foreach {major minor sp dontcare} [get_os_version] break
        if {($major == 5) && ($minor == 0) && ($sp < 3)} {
            after 1000
        }
    }
}

# Variable that maps logon session type codes to integer values
# See ntsecapi.h for definitions
set twapi::::logon_session_type_map {
    0
    1
    interactive
    network
    batch
    service
    proxy
    unlockworkstation
    networkclear
    newcredentials
    remoteinteractive
    cachedinteractive
    cachedremoteinteractive
    cachedunlockworkstation
}

# REturns the logon session type value for a symbol
proc twapi::_logon_session_type_code {type} {
    # Type may be an integer or one of the strings below
    set code [lsearch -exact $::twapi::logon_session_type_map $type]
    if {$code >= 0} {
        return $code
    }

    if {![string is integer -strict $type]} {
        error "Invalid logon session type '$type' specified"
    }
    return $type
}

# Returns the logon session type symbol for an integer value
proc twapi::_logon_session_type_symbol {code} {
    set symbol [lindex $::twapi::logon_session_type_map $code]
    if {$symbol eq ""} {
        return $code
    } else {
        return $symbol
    }
}

# Returns true if null security descriptor
proc twapi::_null_secd {secd} {
    if {[llength $secd] == 0} {
        return 1
    } else {
        return 0
    }
}

# Returns true if a valid ACL
proc twapi::_is_valid_acl {acl} {
    if {$acl eq "null"} {
        return 1
    } else {
        return [IsValidAcl $acl]
    }
}

# Returns true if a valid ACL
proc twapi::_is_valid_security_descriptor {secd} {
    if {[_null_secd $secd]} {
        return 1
    } else {
        return [IsValidSecurityDescriptor $secd]
    }
}
Added Binaries/Windows/twapi/services.tcl.






































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
#
# Copyright (c) 2003-2007, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

namespace eval twapi {
} 

# Locks the scm database and returns a handle to the lock
proc twapi::lock_scm_db {args} {
    variable windefs

    array set opts [parseargs args {system.arg database.arg} -nulldefault]

    set scm [OpenSCManager $opts(system) $opts(database) \
                 $windefs(SC_MANAGER_LOCK)]
    try {
        set lock [LockServiceDatabase $scm]
    } finally {
        CloseServiceHandle $scm
    }
    return $lock
}

# Unlocks the scm database
proc twapi::unlock_scm_db {lock} {
    UnlockServiceDatabase $lock
}

# Query the lock status of the scm database. Returns 1/0 depending on whether
# database is locked. $v_lockinfo will contain a two element list of
# {lockowner time_locked}
proc twapi::query_scm_db_lock_status {v_lockinfo args} {
    variable windefs

    upvar $v_lockinfo lockinfo

    array set opts [parseargs args {system.arg database.arg} -nulldefault]
    set scm [OpenSCManager $opts(system) $opts(database) \
                 $windefs(SC_MANAGER_QUERY_LOCK_STATUS)]
    try {
        array set lock_status [QueryServiceLockStatus $scm]
        set lockinfo [list $lock_status(lpLockOwner) $lock_status(dwLockDuration)]
    } finally {
        CloseServiceHandle $scm
    }

    return $lock_status(fIsLocked)
}


#
# Return 1/0 depending on whether the given service exists
# $name may be either the internal or display name
proc twapi::service_exists {name args} {
    variable windefs

    array set opts [parseargs args {system.arg database.arg} -nulldefault]
    set scm [OpenSCManager $opts(system) $opts(database) \
                 $windefs(STANDARD_RIGHTS_READ)]
 
    try {
        GetServiceKeyName $scm $name
        set exists 1
    } onerror {TWAPI_WIN32 1060} {
        # "no such service" error for internal name.
        # Try display name
        try {
            GetServiceDisplayName $scm $name
            set exists 1
        } onerror {TWAPI_WIN32 1060} {
            set exists 0
        }
    } finally {
        CloseServiceHandle $scm
    }

    return $exists
}


#
# Create a service of the specified name
proc twapi::create_service {name command args} {
    variable windefs

    array set opts [parseargs args {
        displayname.arg
        {servicetype.arg     win32_own_process {win32_own_process win32_share_process file_system_driver kernel_driver}}
        {interactive.bool    0}
        {starttype.arg       auto_start {auto_start boot_start demand_start disabled system}}
        {errorcontrol.arg    normal {ignore normal severe critical}}
        loadordergroup.arg
        dependencies.arg
        account.arg
        password.arg
        system.arg
        database.arg
    } -nulldefault]
    

    if {[string length $opts(displayname)] == 0} {
        set opts(displayname) $name
    }

    if {[string length $command] == 0} {
        error "The executable path must not be null when creating a service"
    }
    set opts(command) $command

    switch -exact -- $opts(servicetype) {
        file_system_driver -
        kernel_driver {
            if {$opts(interactive)} {
                error "Option -interactive cannot be specified when -servicetype is $opts(servicetype)."
            }
        }
        default {
            if {$opts(interactive) && [string length $opts(account)]} {
                error "Option -interactive cannot be specified with the -account option as interactive services must run under the LocalSystem account."
            }
            if {[string equal $opts(starttype) "boot_start"]
                || [string equal $opts(starttype) "system_start"]} {
                error "Option -starttype value must be one of auto_start, demand_start or disabled when -servicetype is '$opts(servicetype)'."
            }
        }
    }

    # Map keywords to integer values
    set opts(servicetype)  $windefs(SERVICE_[string toupper $opts(servicetype)])
    set opts(starttype)    $windefs(SERVICE_[string toupper $opts(starttype)])
    set opts(errorcontrol) $windefs(SERVICE_ERROR_[string toupper $opts(errorcontrol)])

    # If interactive, add the flag to the service type
    if {$opts(interactive)} {
        setbits opts(servicetype) $windefs(SERVICE_INTERACTIVE_PROCESS)
    }

    # Ignore password if username not specified
    if {[string length $opts(account)] == 0} {
        set opts(password) ""
    } else {
        # If domain/system not specified, tack on ".\" for local system
        if {[string first \\ $opts(account)] < 0} {
            set opts(account) ".\\$opts(account)"
        }
    }

    set scm [OpenSCManager $opts(system) $opts(database) \
                 $windefs(SC_MANAGER_CREATE_SERVICE)]
    try {
        set svch [CreateService \
                      $scm \
                      $name \
                      $opts(displayname) \
                      $windefs(SERVICE_ALL_ACCESS) \
                      $opts(servicetype) \
                      $opts(starttype) \
                      $opts(errorcontrol) \
                      $opts(command) \
                      $opts(loadordergroup) \
                      NULL \
                      $opts(dependencies) \
                      $opts(account) \
                      $opts(password)]
        
        CloseServiceHandle $svch
        
    } finally {
        CloseServiceHandle $scm
    }
    
    return
}


# Delete the given service
proc twapi::delete_service {name args} {
    variable windefs

    array set opts [parseargs args {system.arg database.arg} -nulldefault]
    set opts(scm_priv) DELETE
    set opts(svc_priv) DELETE
    set opts(proc)     twapi::DeleteService
    
    _service_fn_wrapper $name opts

    return
}


# Get the internal name of a service
proc twapi::get_service_internal_name {name args} {
    variable windefs

    array set opts [parseargs args {system.arg database.arg} -nulldefault]
    set scm [OpenSCManager $opts(system) $opts(database) \
                 $windefs(STANDARD_RIGHTS_READ)]


    try {
        if {[catch {GetServiceKeyName $scm $name} internal_name]} {
            # Maybe this is an internal name itself
            GetServiceDisplayName $scm $name; # Will throw an error if not internal name
            set internal_name $name
        }
    } finally {
        CloseServiceHandle $scm
    }

    return $internal_name
}

# Get the display name of a service
proc twapi::get_service_display_name {name args} {
    variable windefs

    array set opts [parseargs args {system.arg database.arg} -nulldefault]
    set scm [OpenSCManager $opts(system) $opts(database) \
                 $windefs(STANDARD_RIGHTS_READ)]


    try {
        if {[catch {GetServiceDisplayName $scm $name} display_name]} {
            # Maybe this is an display name itself
            GetServiceKeyName $scm $name; # Will throw an error if not display name
            set display_name $name
        }
    } finally {
        CloseServiceHandle $scm
    }

    return $display_name
}


# Start the specified service
proc twapi::start_service {name args} {
    variable windefs

    array set opts [parseargs args {
        system.arg
        database.arg
        params.arg
        wait.int 
    } -nulldefault]
    set opts(svc_priv) SERVICE_START
    set opts(proc)     twapi::StartService
    set opts(args)     [list $opts(params)]
    unset opts(params)

    try {
        _service_fn_wrapper $name opts
    } onerror {TWAPI_WIN32 1056} {
        # Error 1056 means service already running
    }

    return [wait {twapi::get_service_state $name -system $opts(system) -database $opts(database)} running $opts(wait)]
}


# Send a control code to the specified service
proc twapi::control_service {name code access finalstate args} {
    variable windefs

    array set opts [parseargs args {
        system.arg
        database.arg
        ignorecodes.arg
        wait.int
    } -nulldefault]
    set scm [OpenSCManager $opts(system) $opts(database) \
                 $windefs(STANDARD_RIGHTS_READ)]
    
    try {
        set svch [OpenService $scm $name $access]
    } finally {
        CloseServiceHandle $scm
    }

    SERVICE_STATUS svc_status
    try {
        ControlService $svch $code svc_status
    } onerror {TWAPI_WIN32} {
        if {[lsearch -exact -integer $opts(ignorecodes) [lindex $errorCode 1]] < 0} {
            #Not one of the error codes we can ignore. Rethrow the error
            error $errorResult $errorInfo $errorCode
        }
    } finally {
        svc_status -delete
        CloseServiceHandle $svch
    }

    if {[string length $finalstate]} {
        # Wait until service is in specified state
        return [wait {twapi::get_service_state $name -system $opts(system) -database $opts(database)} $finalstate $opts(wait)]
    } else {
        return 0
    }
}

proc twapi::stop_service {name args} {
    variable windefs
    eval [list control_service $name \
              $windefs(SERVICE_CONTROL_STOP) $windefs(SERVICE_STOP) stopped -ignorecodes 1062] $args
}

proc twapi::pause_service {name args} {
    variable windefs
    eval [list control_service $name \
              $windefs(SERVICE_CONTROL_PAUSE) \
              $windefs(SERVICE_PAUSE_CONTINUE) paused] $args
}

proc twapi::continue_service {name args} {
    variable windefs
    eval [list control_service $name \
              $windefs(SERVICE_CONTROL_CONTINUE) \
              $windefs(SERVICE_PAUSE_CONTINUE) running] $args
}

proc twapi::interrogate_service {name args} {
    variable windefs
    eval [list control_service $name \
              $windefs(SERVICE_CONTROL_INTERROGATE) \
              $windefs(SERVICE_INTERROGATE) ""] $args
    return
}


# Retrieve status information for a service
proc twapi::get_service_status {name args} {
    variable windefs

    array set opts [parseargs args {system.arg database.arg} -nulldefault]
    set scm [OpenSCManager $opts(system) $opts(database) \
                 $windefs(STANDARD_RIGHTS_READ)]

    try {
        set svch [OpenService $scm $name $windefs(SERVICE_QUERY_STATUS)]
    } finally {
        # Do not need SCM anymore
        CloseServiceHandle $scm
    }

    try {
        return [_format_SERVICE_STATUS_EX [QueryServiceStatusEx $svch 0]]
    } finally {
        CloseServiceHandle $svch
    }
}


# Get the state of the service
proc twapi::get_service_state {name args} {
    return [kl_get [eval [list get_service_status $name] $args] state]
}


# Get the current configuration for a service
proc twapi::get_service_configuration {name args} {
    variable windefs

    array set opts [parseargs args {
        system.arg
        database.arg
        all
        servicetype
        interactive
        errorcontrol
        starttype
        command
        loadordergroup
        account
        displayname
        dependencies
        description
        scm_handle.arg
    } -nulldefault]

    set opts(svc_priv) SERVICE_QUERY_CONFIG
    set opts(proc)     twapi::QueryServiceConfig
    array set svc_config [_service_fn_wrapper $name opts]

    # Get the service type info
    foreach {servicetype interactive} \
        [_map_servicetype_code $svc_config(dwServiceType)] break

    set result [list ]
    if {$opts(all) || $opts(servicetype)} {
        lappend result -servicetype $servicetype
    }
    if {$opts(all) || $opts(interactive)} {
        lappend result -interactive $interactive
    }
    if {$opts(all) || $opts(errorcontrol)} {
        lappend result -errorcontrol [_map_errorcontrol_code $svc_config(dwErrorControl)]
    }
    if {$opts(all) || $opts(starttype)} {
        lappend result -starttype [_map_starttype_code $svc_config(dwStartType)]
    }
    if {$opts(all) || $opts(command)} {
        lappend result -command $svc_config(lpBinaryPathName)
    }
    if {$opts(all) || $opts(loadordergroup)} {
        lappend result -loadordergroup $svc_config(lpLoadOrderGroup)
    }
    if {$opts(all) || $opts(account)} {
        lappend result -account $svc_config(lpServiceStartName)
    }
    if {$opts(all) || $opts(displayname)} {
        lappend result -displayname    $svc_config(lpDisplayName)
    }
    if {$opts(all) || $opts(dependencies)} {
        lappend result -dependencies $svc_config(lpDependencies)
    }
    if {$opts(all) || $opts(description)} {
        # TBD - replace with call to QueryServiceConfig2 when available
        if {[catch {
            registry get "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\$name" "Description"
        } desc]} {
            lappend result -description ""
        } else {
            lappend result -description $desc
        }
    }
    # Note currently we do not return svc_config(dwTagId)

    return $result
}

# Sets a service configuration
proc twapi::set_service_configuration {name args} {
    variable windefs

    # Get the current values - we will need these for validation
    # with the new values
    array set current [get_service_configuration $name -all]
    set current(-password) ""; # This is not returned by get_service_configuration

    # Remember which arguments were actually specified
    array set specified_args $args

    # Now parse arguments, filling in defaults
    array set opts [parseargs args {
        displayname.arg
        servicetype.arg
        interactive.bool
        starttype.arg
        errorcontrol.arg
        command.arg
        loadordergroup.arg
        dependencies.arg
        account.arg
        password.arg
        {system.arg ""}
        {database.arg ""}
    }]

    if {[info exists opts(account)] && ! [info exists opts(password)]} {
        error "Option -password must also be specified when -account is specified."
    }

    # Overwrite current configuration with specified options
    foreach opt {
        displayname
        servicetype
        interactive
        starttype
        errorcontrol
        command
        loadordergroup
        dependencies
        account
        password
    } {
        if {[info exists opts($opt)]} {
            set winparams($opt) $opts($opt)
        } else {
            set winparams($opt) $current(-$opt)
        }
    }

    # Validate the new configuration
    switch -exact -- $winparams(servicetype) {
        file_system_driver -
        kernel_driver {
            if {$winparams(interactive)} {
                error "Option -interactive cannot be specified when -servicetype is $winparams(servicetype)."
            }
        }
        default {
            if {$winparams(interactive) &&
                [string length $winparams(account)] &&
                [string compare -nocase $winparams(account) "LocalSystem"]
            } {
                error "Option -interactive cannot be specified with the -account option as interactive services must run under the LocalSystem account."
            }
            if {[string equal $winparams(starttype) "boot_start"]
                || [string equal $winparams(starttype) "system_start"]} {
                error "Option -starttype value must be one of auto_start, demand_start or disabled when -servicetype is '$winparams(servicetype)'."
            }
        }
    }
    
    # Map keywords to integer values
    set winparams(servicetype)  $windefs(SERVICE_[string toupper $winparams(servicetype)])
    set winparams(starttype)    $windefs(SERVICE_[string toupper $winparams(starttype)])
    set winparams(errorcontrol) $windefs(SERVICE_ERROR_[string toupper $winparams(errorcontrol)])

    # If interactive, add the flag to the service type
    if {$winparams(interactive)} {
        if {![info exists opts(servicetype)]} {
            set opts(servicetype) $winparams(servicetype)
        }
        setbits opts(servicetype) $windefs(SERVICE_INTERACTIVE_PROCESS)
        setbits winparams(servicetype) $opts(servicetype)
    }

    # If domain/system not specified, tack on ".\" for local system
    if {[string length $winparams(account)]} {
        if {[string first \\ $winparams(account)] < 0} {
            set winparams(account) ".\\$winparams(account)"
        }
    }

    # Now replace any options that were not specified with "no change"
    # tokens. Note -interactive is not listed here, since it is included
    # in servicetype at this point
    foreach opt {servicetype starttype errorcontrol} {
        if {![info exists opts($opt)]} {
            set winparams($opt) $windefs(SERVICE_NO_CHANGE)
        }
    }
    foreach opt {command loadordergroup dependencies account password displayname} {
        if {![info exists opts($opt)]} {
            set winparams($opt) $twapi::nullptr
        }
    }

    set opts(scm_priv) STANDARD_RIGHTS_READ
    set opts(svc_priv) SERVICE_CHANGE_CONFIG
    set opts(proc)     twapi::ChangeServiceConfig
    set opts(args) \
        [list \
             $winparams(servicetype) \
             $winparams(starttype) \
             $winparams(errorcontrol) \
             $winparams(command) \
             $winparams(loadordergroup) \
             NULL \
             $winparams(dependencies) \
             $winparams(account) \
             $winparams(password) \
             $winparams(displayname)]

    _service_fn_wrapper $name opts

    return
}


# Get status for the specified service types
proc twapi::get_multiple_service_status {args} {
    variable windefs

    set service_types [list \
                           kernel_driver \
                           file_system_driver \
                           adapter \
                           recognizer_driver \
                           win32_own_process \
                           win32_share_process]
    set switches [concat $service_types \
                      [list active inactive] \
                      [list system.arg database.arg]]
    array set opts [parseargs args $switches -nulldefault]

    set servicetype 0
    foreach type $service_types {
        if {$opts($type)} {
            set servicetype [expr { $servicetype
                                    | $windefs(SERVICE_[string toupper $type])
                                }]
        }
    }
    if {$servicetype == 0} {
        # No type specified, return all
        set servicetype [expr {$windefs(SERVICE_KERNEL_DRIVER)
                               | $windefs(SERVICE_FILE_SYSTEM_DRIVER)
                               | $windefs(SERVICE_ADAPTER)
                               | $windefs(SERVICE_RECOGNIZER_DRIVER)
                               | $windefs(SERVICE_WIN32_OWN_PROCESS)
                               | $windefs(SERVICE_WIN32_SHARE_PROCESS)}]
    }

    set servicestate 0
    if {$opts(active)} {
        set servicestate [expr {$servicestate |
                                $windefs(SERVICE_ACTIVE)}]
    }
    if {$opts(inactive)} {
        set servicestate [expr {$servicestate |
                                $windefs(SERVICE_INACTIVE)}]
    }
    if {$servicestate == 0} {
        # No state specified, include all
        set servicestate $windefs(SERVICE_STATE_ALL)
    }
    
    set servicelist [list ]

    set scm [OpenSCManager $opts(system) $opts(database) \
                 $windefs(SC_MANAGER_ENUMERATE_SERVICE)]
    try {
        if {[min_os_version 5]} {
            set status_recs [EnumServicesStatusEx $scm 0 $servicetype $servicestate __null__]
        } else {
            set status_recs [EnumServicesStatus $scm $servicetype $servicestate]
        }
    } finally {
        CloseServiceHandle $scm
    }

    foreach status_rec $status_recs {
        lappend servicelist [_format_status_record $status_rec]
    }

    return $servicelist
}


# Get status for the dependents of the specified service
proc twapi::get_dependent_service_status {name args} {
    variable windefs

    array set opts [parseargs args \
                        [list active inactive system.arg database.arg] \
                        -nulldefault]

    set servicestate 0
    if {$opts(active)} {
        set servicestate [expr {$servicestate |
                                $windefs(SERVICE_ACTIVE)}]
    }
    if {$opts(inactive)} {
        set servicestate [expr {$servicestate |
                                $windefs(SERVICE_INACTIVE)}]
    }
    if {$servicestate == 0} {
        # No state specified, include all
        set servicestate $windefs(SERVICE_STATE_ALL)
    }
    
    set opts(svc_priv) SERVICE_ENUMERATE_DEPENDENTS
    set opts(proc)     twapi::EnumDependentServices
    set opts(args)     [list $servicestate]
    set status_recs [_service_fn_wrapper $name opts]

    set servicelist [list ]
    foreach status_rec $status_recs {
        lappend servicelist [_format_status_record $status_rec]
    }
        
    return $servicelist
}


# Map an integer service type code into a list consisting of 
# {SERVICETYPESYMBOL BOOLEAN}. If there is not symbolic service type
# for the service, just the integer code is returned. The BOOLEAN
# is 1/0 depending on whether the service type code is interactive
proc twapi::_map_servicetype_code {servicetype} {
    variable windefs

    set interactive [expr {($servicetype & $windefs(SERVICE_INTERACTIVE_PROCESS)) != 0}]
    set servicetype [expr {$servicetype & (~$windefs(SERVICE_INTERACTIVE_PROCESS))}]

    # Map service type integer code to symbol, *if possible*
    set service_syms {
        win32_own_process win32_share_process kernel_driver
        file_system_driver adapter recognizer_driver
    }
    set servicetype [code_to_symbol $servicetype $service_syms]
    
    return [list $servicetype $interactive]
}

# Map a start type code into a symbol. Returns the integer code if
# no mapping possible
proc twapi::_map_starttype_code {code} {
    return [code_to_symbol \
                $code {auto_start boot_start demand_start disabled system_start}]
}


# Map a error control code into a symbol. Returns the integer code if
# no mapping possible
proc twapi::_map_errorcontrol_code {code} {
    return [code_to_symbol \
                $code {ignore normal severe critical} "SERVICE_ERROR_"]
}


# Map a service state code to a symbol 
proc twapi::_map_state_code {code} {
    # Map state integer code to symbol *if possible*
    set states {
        stopped start_pending stop_pending running continue_pending
        pause_pending paused
    }
    set state [code_to_symbol $code $states]
}


#
# Format a service status list record 
# {dwServiceType 1 dwCurrentState 2....}
# gets formatted as 
# {-servicetype win32_own_process -state running ...}
proc twapi::_format_status_record {status_rec} {

    set retval [_format_SERVICE_STATUS_EX $status_rec]
    if {[kl_vget $status_rec lpServiceName name]} {
        lappend retval name $name
    }
    if {[kl_vget $status_rec lpDisplayName displayname]} {
        lappend retval displayname $displayname
    }
    return $retval
}

#
# Format an extended service status record
proc twapi::_format_SERVICE_STATUS_EX {svc_status} {
    # Get the service type and strip off the interactive flag
    foreach {servicetype interactive} \
        [_map_servicetype_code [kl_get $svc_status dwServiceType]] break

    # Map state integer code to symbol *if possible*
    set state [_map_state_code [kl_get $svc_status dwCurrentState]]

    # Pid if available
    if {![kl_vget $svc_status dwProcessId pid]} {
        # There was no dwProcessId field. NT 4
        if {$state == "stopped"} {
            set pid 0
        } else {
            set pid -1
        }
    }

    set attrs [list ]
    if {[kl_vget $svc_status dwServiceFlags flags] &&
        ($flags & 1)} {
        lappend attrs systemprocess
    }
    
    return [list \
                servicetype  $servicetype \
                interactive  $interactive \
                state        $state \
                controls_accepted [kl_get $svc_status dwControlsAccepted] \
                exitcode     [kl_get $svc_status dwWin32ExitCode] \
                service_code [kl_get $svc_status dwServiceSpecificExitCode] \
                checkpoint   [kl_get $svc_status dwCheckPoint] \
                wait_hint    [kl_get $svc_status dwWaitHint] \
                pid          $pid \
                attrs        $attrs]
}


# Maps an integer code to a symbolic name if possible, else returns the
# integer code
proc twapi::code_to_symbol {code symlist {prefix "SERVICE_"}} {
    variable windefs
    foreach sym $symlist {
        if {$code == $windefs(${prefix}[string toupper $sym])} {
            return $sym
        }
    }
    return $code
}


#
# Standard template for calling a service function. v_opts should refer
# to an array with the following elements:
# opts(system) - target system. Must be specified
# opts(database) - target database. Must be specified
# opts(scm_priv) - requested privilege when opening SCM. STANDARD_RIGHTS_READ
#   is used if unspecified. Not used if scm_handle is specified
# opts(scm_handle) - handle to service control manager. Optional
# opts(svc_priv) - requested privilege when opening service. Must be present
# opts(proc) - proc/function to call. The first arg is the service handle
# opts(args) - additional arguments to pass to the function.
#   Empty if unspecified
# 
proc twapi::_service_fn_wrapper {name v_opts} {
    variable windefs
    upvar $v_opts opts

    # Use STANDARD_RIGHTS_READ for SCM if not specified
    set scm_priv [expr {[info exists opts(scm_priv)] ? $opts(scm_priv) : "STANDARD_RIGHTS_READ"}]

    if {[info exists opts(scm_handle)] &&
        $opts(scm_handle) ne ""} {
        set scm $opts(scm_handle)
    } else {
        set scm [OpenSCManager $opts(system) $opts(database) \
                     $windefs($scm_priv)]
    }
    try {
        set svch [OpenService $scm $name $windefs($opts(svc_priv))]
    } finally {
        # No need for scm handle anymore. Close it unless it was
        # passed to us
        if {(![info exists opts(scm_handle)]) ||
            ($opts(scm_handle) eq "")} {
            CloseServiceHandle $scm
        }
    }

    set proc_args [expr {[info exists opts(args)] ? $opts(args) : ""}]
    try {
        set results [eval [list $opts(proc) $svch] $proc_args]
    } finally {
        CloseServiceHandle $svch
    }
    
    return $results
}


Added Binaries/Windows/twapi/share.tcl.
















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
#
# Copyright (c) 2003, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

namespace eval twapi {
}


#
# Create a network share
proc twapi::new_share {sharename path args} {
    variable windefs

    array set opts [parseargs args {
        {system.arg ""}
        {type.arg "file"}
        {comment.arg ""}
        {max_conn.int -1}
        secd.arg
    } -maxleftover 0]

    # If no security descriptor specified, default to "Everyone,
    # read permission". Levaing it empty will give everyone all permissions
    # which is probably not a good idea!
    if {![info exists opts(secd)]} {
        set opts(secd) [new_security_descriptor -dacl [new_acl [list [new_ace allow S-1-1-0 1179817]]]]
    }
    
    NetShareAdd $opts(system) \
        $sharename \
        [_share_type_symbols_to_code $opts(type)] \
        $opts(comment) \
        $opts(max_conn) \
        [file nativename $path] \
        $opts(secd)
}

#
# Delete a network share
proc twapi::delete_share {sharename args} {
    array set opts [parseargs args {system.arg} -nulldefault]
    NetShareDel $opts(system) $sharename 0
}

#
# Enumerate network shares
proc twapi::get_shares {args} {
    variable windefs

    array set opts [parseargs args {
        system.arg
        type.arg
        excludespecial
    } -nulldefault]

    if {$opts(type) != ""} {
        set type_filter [_share_type_symbols_to_code $opts(type) 1]
    } else {
        set type_filter ""
    }

    set shares [list ]
    foreach share [Twapi_NetShareEnum $opts(system)] {
        foreach {name type comment} $share break
        set special [expr {$type & ($windefs(STYPE_SPECIAL) | $windefs(STYPE_TEMPORARY))}]
        if {$special && $opts(excludespecial)} {
            continue
        }
        # We need the special cast to int because else operands get promoted
        # to 64 bits as the hex is treated as an unsigned value
        set type [expr {int($type & ~ $special)}]
        if {([string length $type_filter] == 0) || ($type == $type_filter)} {
            lappend shares $name
        }
    }

    return $shares
}


#
# Get details about a share
proc twapi::get_share_info {sharename args} {
    array set opts [parseargs args {
        system.arg
        all
        name
        type
        path
        comment
        max_conn
        current_conn
        secd
    } -nulldefault]

    if {$opts(all)} {
        foreach opt {name type path comment max_conn current_conn secd} {
            set opts($opt) 1
        }
    }

    set level 0

    if {$opts(name) || $opts(type) || $opts(comment)} {
        set level 1
    }

    if {$opts(max_conn) || $opts(current_conn) || $opts(path)} {
        set level 2
    }

    if {$opts(secd)} {
        set level 502
    }

    if {! $level} {
        return
    }

    set shareinfo [NetShareGetInfo $opts(system) $sharename $level]

    set result [list ]
    if {$opts(name)} {
        lappend result -name [lindex $shareinfo 0]
    }
    if {$opts(type)} {
        lappend result -type [_share_type_code_to_symbols [lindex $shareinfo 1]]
    }
    if {$opts(comment)} {
        lappend result -comment [lindex $shareinfo 2]
    }
    if {$opts(max_conn)} {
        lappend result -max_conn [lindex $shareinfo 4]
    }
    if {$opts(current_conn)} {
        lappend result -current_conn [lindex $shareinfo 5]
    }
    if {$opts(path)} {
        lappend result -path [lindex $shareinfo 6]
    }
    if {$opts(secd)} {
        lappend result -secd [lindex $shareinfo 9]
    }
    
    return $result
}


#
# Set a share configuration
proc twapi::set_share_info {sharename args} {
    array set opts [parseargs args {
        {system.arg ""}
        comment.arg
        max_conn.int
        secd.arg
    }]

    # First get the current config so we can change specified fields
    # and write back
    array set shareinfo [get_share_info $sharename -system $opts(system) \
                             -comment -max_conn -secd]
    foreach field {comment max_conn secd} {
        if {[info exists opts($field)]} {
            set shareinfo(-$field) $opts($field)
        }
    }

    NetShareSetInfo $opts(system) $sharename $shareinfo(-comment) \
        $shareinfo(-max_conn) $shareinfo(-secd)
}


#
# Get list of remote shares
proc twapi::get_connected_shares {} {
    return [get_client_shares]
}


#
# Get list of remote shares
proc twapi::get_client_shares {} {
    return [NetUseEnum]
}


#
# Connect to a share
proc twapi::connect_share {remoteshare args} {
    array set opts [parseargs args {
        {type.arg  "disk"} 
        localdevice.arg
        provider.arg
        password.arg
        nopassword
        defaultpassword
        user.arg
        {window.arg 0}
        interactive
        prompt
        updateprofile
        commandline
    } -nulldefault]

    set flags 0

    switch -exact -- $opts(type) {
        "any"       {set type 0}
        "disk"      -
        "file"      {set type 1}
        "printer"   {set type 2}
        default {
            error "Invalid network share type '$opts(type)'"
        }
    }

    # localdevice - "" means no local device, * means pick any, otherwise
    # it's a local device to be mapped
    if {$opts(localdevice) == "*"} {
        set opts(localdevice) ""
        setbits flags 0x80;             # CONNECT_REDIRECT
    }

    if {$opts(defaultpassword) && $opts(nopassword)} {
        error "Options -defaultpassword and -nopassword may not be used together"
    }
    if {$opts(nopassword)} {
        set opts(password) ""
        set ignore_password 1
    } else {
        set ignore_password 0
        if {$opts(defaultpassword)} {
            set opts(password) ""
        }
    }

    foreach {opt mask} {
        interactive   0x8
        prompt        0x10
        updateprofile 0x1
        commandline   0x800
    } {
        if {$opts($opt)} {
            setbits flags $mask
        }
    }

    return [Twapi_WNetUseConnection $opts(window) $type $opts(localdevice) \
                $remoteshare $opts(provider) $opts(user) $ignore_password \
                $opts(password) $flags]
}

#
# Disconnects an existing share
proc twapi::disconnect_share {sharename args} {
    array set opts [parseargs args {updateprofile force}]

    set flags [expr {$opts(updateprofile) ? 0x1 : 0}]
    WNetCancelConnection2 $sharename $flags $opts(force)
}


#
# Get information about a connected share
proc twapi::get_client_share_info {sharename args} {

    if {$sharename eq ""} {
        error "A share name cannot be the empty string"
    }

    # We have to use a combination of NetUseGetInfo and 
    # WNetGetResourceInformation as neither gives us the full information
    # THe former takes the local device name if there is one and will
    # only accept a UNC if there is an entry for the UNC with
    # no local device mapped. The latter
    # always wants the UNC. So we need to figure out exactly if there
    # is a local device mapped to the sharename or not
    
    # There may be multiple entries for the same UNC
    # If there is an entry for the UNC with no device mapped, select
    # that else select any of the local devices mapped to it
    # TBD - any better way of finding out a mapping than calling
    # get_client_shares?
    foreach elem [get_client_shares] {
        foreach {elem_device elem_unc} $elem break
        if {[string equal -nocase $sharename $elem_unc]} {
            if {$elem_device eq ""} {
                # Found an entry without a local device. Use it
                set unc $elem_unc
                unset -nocomplain local; # In case we found a match earlier
                break
            } else {
                # Found a matching device
                set local $elem_device
                set unc $elem_unc
                # Keep looping in case we find an entry with no local device
                # (which we will prefer)
            }
        } else {
            # See if the sharename is actually a local device name
            if {[string equal -nocase [string trimright $elem_device :] [string trimright $sharename :]]} {
                # Device name matches. Use it
                set local $elem_device
                set unc $elem_unc
                break
            }
        }
    }

    if {![info exists unc]} {
        win32_error 2250 "Share '$sharename' not found."
    }

    # At this point $unc is the UNC form of the share and
    # $local is either undefined or the local mapped device if there is one

    array set opts [parseargs args {
        user
        localdevice
        remoteshare
        status
        type
        opencount
        usecount
        domain
        provider
        comment
        all
    } -maxleftover 0]


    # Call Twapi_NetGetInfo always to get status. If we are not connected,
    # we will not call WNetGetResourceInformation as that will time out
    if {$opts(all) || $opts(user) || $opts(status) || $opts(type) ||
        $opts(opencount) || $opts(usecount) || $opts(domain)} {
        if {[info exists local]} {
            array set shareinfo [Twapi_NetUseGetInfo "" $local]
        } else {
            array set shareinfo [Twapi_NetUseGetInfo "" $unc]
        }
    }

    if {$opts(all) || $opts(comment) || $opts(provider) || $opts(remoteshare)} {
        # Only get this information if we are connected
        if {$shareinfo(ui2_status) == 0} {
            array set shareinfo [lindex [Twapi_WNetGetResourceInformation $unc "" 0] 0]
        } else {
            set shareinfo(lpRemoteName) $unc
            set shareinfo(lpProvider) ""
            set shareinfo(lpComment) ""
        }
    }


    array set result {}
    foreach {opt index} {
        user           ui2_username
        localdevice    ui2_local
        remoteshare    lpRemoteName
        status         ui2_status
        type           ui2_asg_type
        opencount      ui2_refcount
        usecount       ui2_usecount
        domain         ui2_domainname
        provider       lpProvider
        comment        lpComment
    } {
        if {$opts(all) || $opts($opt)} {
            set result(-$opt) $shareinfo($index)
        }
    }

    # Map values to symbols

    if {[info exists result(-status)]} {
        # Map code 0-5
        set temp [lindex {connected paused lostsession disconnected networkerror connecting reconnecting} $result(-status)]
        if {$temp ne ""} {
            set result(-status) $temp
        } else {
            set result(-status) "unknown"
        }
    }

    if {[info exists result(-type)]} {
        set temp [lindex {file printer char ipc} $result(-type)]
        if {$temp ne ""} {
            set result(-type) $temp
        } else {
            set result(-type) "unknown"
        }
    }

    return [array get result]
}



#
# Get connected share info
proc twapi::get_mapped_share_info {path args} {
    array set opts [parseargs args {
        all user uncpath uncvolume relativepath
    }]

    if {! [regexp {^([[:alpha:]]:)} $path dontcare drive]} {
        error "No drive specified in path '$path'"
    }

    set result [list ]

    foreach {uncpath uncvolume relativepath} [WNetGetUniversalName $path] break
    foreach opt {uncpath uncvolume relativepath} {
        if {$opts($opt) || $opts(all)} {
            lappend result -$opt [set $opt]
        }
    }

    if {$opts(user) || $opts(all)} {
        lappend result -user [WNetGetUser $drive]
    }

    return $result
}


#
# Enumerate sessions
proc twapi::find_lm_sessions args {
    array set opts [parseargs args {
        all
        {client.arg ""}
        {system.arg ""}
        {user.arg ""}
        transport
        clientname
        username
        clienttype
        opencount
        idleseconds
        activeseconds
        attrs
    } -maxleftover 0]

    set level [_calc_minimum_session_info_level opts]
    if {![min_os_version 5]} {
        # System name is specified. If NT, make sure it is UNC form
        set opts(system) [_make_unc_computername $opts(system)]
    }
    
    # On all platforms, client must be in UNC format
    set opts(client) [_make_unc_computername $opts(client)]

    try {
        set sessions [NetSessionEnum $opts(system) $opts(client) $opts(user) $level]
    } onerror {TWAPI_WIN32 2312} {
        # No session matching the specified client
        return [list ]
    } onerror {TWAPI_WIN32 2221} {
        # No session matching the user
        return [list ]
    }

    set retval [list ]
    foreach sess $sessions {
        lappend retval [_format_lm_session $sess opts]
    }

    return $retval
}


#
# Get information about a session 
proc twapi::get_lm_session_info {client user args} {
    array set opts [parseargs args {
        all
        {system.arg ""}
        transport
        clientname
        username
        clienttype
        opencount
        idleseconds
        activeseconds
        attrs
    } -maxleftover 0]

    set level [_calc_minimum_session_info_level opts]
    if {$level == -1} {
        # No data requested so return empty list
        return [list ]
    }

    if {![min_os_version 5]} {
        # System name is specified. If NT, make sure it is UNC form
        set opts(system) [_make_unc_computername $opts(system)]
    }
    
    # On all platforms, client must be in UNC format
    set client [_make_unc_computername $client]

    # Note an error is generated if no matching session exists
    set sess [NetSessionGetInfo $opts(system) $client $user $level]

    return [_format_lm_session $sess opts]
}

# Delete sessions
proc twapi::end_lm_sessions args {
    array set opts [parseargs args {
        {client.arg ""}
        {system.arg ""}
        {user.arg ""}
    } -maxleftover 0]

    if {![min_os_version 5]} {
        # System name is specified. If NT, make sure it is UNC form
        set opts(system) [_make_unc_computername $opts(system)]
    }

    if {$opts(client) eq "" && $opts(user) eq ""} {
        win32_error 87 "At least one of -client and -user must be specified."
    }

    # On all platforms, client must be in UNC format
    set opts(client) [_make_unc_computername $opts(client)]

    try {
        NetSessionDel $opts(system) $opts(client) $opts(user)
    } onerror {TWAPI_WIN32 2312} {
        # No session matching the specified client - ignore error
    } onerror {TWAPI_WIN32 2221} {
        # No session matching the user - ignore error
    }
    return
}

#
# Enumerate open files
proc twapi::find_lm_open_files args {
    array set opts [parseargs args {
        {basepath.arg ""}
        {system.arg ""}
        {user.arg ""}
        all
        permissions
        id
        lockcount
        path
        username
    } -maxleftover 0]

    if {![min_os_version 5]} {
        # System name is specified. If NT, make sure it is UNC form
        set opts(system) [_make_unc_computername $opts(system)]
    }
    
    set level 3
    if {! ($opts(all) || $opts(permissions) || $opts(lockcount) ||
           $opts(path) || $opts(username))} {
        # Only id's required
        set level 2
    }

    try {
        set files [NetFileEnum $opts(system) [file nativename $opts(basepath)] $opts(user) $level]
    } onerror {TWAPI_WIN32 2221} {
        # No files matching the user
        return [list ]
    }

    set retval [list ]
    foreach file $files {
        lappend retval [_format_lm_open_file $file opts]
    }

    return $retval
}

# Get information about an open LM file
proc twapi::get_lm_open_file_info {fid args} {
    array set opts [parseargs args {
        {system.arg ""}
        all
        permissions
        id
        lockcount
        path
        username
    } -maxleftover 0]

    # System name is specified. If NT, make sure it is UNC form
    if {![min_os_version 5]} {
        set opts(system) [_make_unc_computername $opts(system)]
    }
    
    set level 3
    if {! ($opts(all) || $opts(permissions) || $opts(lockcount) ||
           $opts(path) || $opts(username))} {
        # Only id's required. We actually already have this but don't
        # return it since we want to go ahead and make the call in case
        # the id does not exist
        set level 2
    }

    return [_format_lm_open_file [NetFileGetInfo $opts(system) $fid $level] opts]
}

# Close an open LM file
proc twapi::close_lm_open_file {fid args} {
    array set opts [parseargs args {
        {system.arg ""}
    } -maxleftover 0]
    try {
        NetFileClose $opts(system) $fid
    } onerror {TWAPI_WIN32 2314} {
        # No such fid. Ignore, perhaps it was closed in the meanwhile
    }
}


#
# Enumerate open connections
proc twapi::find_lm_connections args {
    array set opts [parseargs args {
        client.arg
        {system.arg ""}
        share.arg
        all
        id
        type
        opencount
        usercount
        activeseconds
        username
        clientname
        sharename
    } -maxleftover 0]

    if {![min_os_version 5]} {
        # System name is specified. If NT, make sure it is UNC form
        set opts(system) [_make_unc_computername $opts(system)]
    }
    
    if {! ([info exists opts(client)] || [info exists opts(share)])} {
        win32_error 87 "Must specify either -client or -share option."
    }

    if {[info exists opts(client)] && [info exists opts(share)]} {
        win32_error 87 "Must not specify both -client and -share options."
    }

    if {[info exists opts(client)]} {
        set qualifier [_make_unc_computername $opts(client)]
    } else {
        set qualifier $opts(share)
    }

    set level 1
    if {! ($opts(all) || $opts(type) || $opts(opencount) ||
           $opts(usercount) || $opts(username) ||
           $opts(activeseconds) || $opts(clientname) || $opts(sharename))} {
        # Only id's required
        set level 0
    }

    set conns [NetConnectionEnum $opts(system) $qualifier $level]

    set retval [list ]
    foreach conn $conns {
        set item [list ]
        foreach {opt fld} {
            id            id
            opencount     num_opens
            usercount     num_users
            activeseconds time
            username      username
        } {
            if {$opts(all) || $opts($opt)} {
                lappend item -$opt [kl_get $conn $fld]
            }
        }
        if {$opts(all) || $opts(type)} {
            lappend item -type [_share_type_code_to_symbols [kl_get $conn type]]
        }
        # What's returned in the netname field depends on what we
        # passed as the qualifier
        if {$opts(all) || $opts(clientname) || $opts(sharename)} {
            if {[info exists opts(client)]} {
                set sharename [kl_get $conn netname]
                set clientname [_make_unc_computername $opts(client)]
            } else {
                set sharename $opts(share)
                set clientname [_make_unc_computername [kl_get $conn netname]]
            }
            if {$opts(all) || $opts(clientname)} {
                lappend item -clientname $clientname
            }
            if {$opts(all) || $opts(sharename)} {
                lappend item -sharename $sharename
            }
        }
        lappend retval $item
    }

    return $retval
}


################################################################
# Utility functions

# Common code to figure out what SESSION_INFO level is required
# for the specified set of requested fields. v_opts is name
# of array indicating which fields are required
proc twapi::_calc_minimum_session_info_level {v_opts} {
    upvar $v_opts opts

    # Set the information level requested based on options specified.
    # We set the level to the one that requires the lowest possible
    # privilege level and still includes the data requested.
    if {$opts(all) || $opts(transport)} {
        return 502
    } elseif {$opts(clienttype)} {
        return 2
    } elseif {$opts(opencount) || $opts(attrs)} {
        return 1
    } elseif {$opts(clientname) || $opts(username) ||
        $opts(idleseconds) || $opts(activeseconds)} {
        return 10
    } else {
        return 0
    }
}

# Common code to format a session record. v_opts is name of array
# that controls which fields are returned
proc twapi::_format_lm_session {sess v_opts} {
    upvar $v_opts opts

    set retval [list ]
    foreach {opt fld} {
        transport     transport
        username      username
        opencount     num_opens
        idleseconds   idle_time
        activeseconds time
        clienttype    cltype_name
    } {
        if {$opts(all) || $opts($opt)} {
            lappend retval -$opt [kl_get $sess $fld]
        }
    }
    if {$opts(all) || $opts(clientname)} {
        # Since clientname is always required to be in UNC on input
        # also pass it back in UNC format
        lappend retval -clientname [_make_unc_computername [kl_get $sess cname]]
    }
    if {$opts(all) || $opts(attrs)} {
        set attrs [list ]
        set flags [kl_get $sess user_flags]
        if {$flags & 1} {
            lappend attrs guest
        }
        if {$flags & 2} {
            lappend attrs noencryption
        }
        lappend retval -attrs $attrs
    }
    return $retval
}

# Common code to format a lm open file record. v_opts is name of array
# that controls which fields are returned
proc twapi::_format_lm_open_file {file v_opts} {
    upvar $v_opts opts

    set retval [list ]
    foreach {opt fld} {
        id          id
        lockcount   num_locks
        path        pathname
        username    username
    } {
        if {$opts(all) || $opts($opt)} {
            lappend retval -$opt [kl_get $file $fld]
        }
    }

    if {$opts(all) || $opts(permissions)} {
        set permissions [list ]
        set perms [kl_get $file permissions]
        foreach {flag perm} {1 read 2 write 4 create} {
            if {$perms & $flag} {
                lappend permissions $perm
            }
        }
        lappend retval -permissions $permissions
    }

    return $retval
}

# NOTE: THIS ONLY MAPS FOR THE Net* functions, NOT THE WNet*
proc twapi::_share_type_symbols_to_code {typesyms {basetypeonly 0}} {
    variable windefs

    switch -exact -- [lindex $typesyms 0] {
        file    { set code $windefs(STYPE_DISKTREE) }
        printer { set code $windefs(STYPE_PRINTQ) }
        device  { set code $windefs(STYPE_DEVICE) }
        ipc     { set code $windefs(STYPE_IPC) }
        default {
            error "Unknown type network share type symbol [lindex $typesyms 0]"
        }
    }

    if {$basetypeonly} {
        return $code
    }

    set special 0
    foreach sym [lrange $typesyms 1 end] {
        switch -exact -- $sym {
            special   { setbits special $windefs(STYPE_SPECIAL) }
            temporary { setbits special $windefs(STYPE_TEMPORARY) }
            file    -
            printer -
            device  -
            ipc     {
                error "Base share type symbol '$sym' cannot be used as a share attribute type"
            }
            default {
                error "Unknown type network share type symbol '$sym'"
            }
        }
    }

    return [expr {$code | $special}]
}


# First element is always the base type of the share
# NOTE: THIS ONLY MAPS FOR THE Net* functions, NOT THE WNet*
proc twapi::_share_type_code_to_symbols {type} {
    variable windefs


    set special [expr {$type & ($windefs(STYPE_SPECIAL) | $windefs(STYPE_TEMPORARY))}]

    # We need the special cast to int because else operands get promoted
    # to 64 bits as the hex is treated as an unsigned value
    switch -exact -- [expr {int($type & ~ $special)}] \
        [list \
             $windefs(STYPE_DISKTREE) {set sym "file"} \
             $windefs(STYPE_PRINTQ)   {set sym "printer"} \
             $windefs(STYPE_DEVICE)   {set sym "device"} \
             $windefs(STYPE_IPC)      {set sym "ipc"} \
             default                  {set sym $type}
            ]

    set typesyms [list $sym]

    if {$special & $windefs(STYPE_SPECIAL)} {
        lappend typesyms special
    }

    if {$special & $windefs(STYPE_TEMPORARY)} {
        lappend typesyms temporary
    }
    
    return $typesyms
}

#
# Make sure a computer name is in unc format unless it is an empty
# string (local computer)
proc twapi::_make_unc_computername {name} {
    if {$name eq ""} {
        return ""
    } else {
        return "\\\\[string trimleft $name \\]"
    }
}
Added Binaries/Windows/twapi/shell.tcl.


























































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#
# Copyright (c) 2004-2006 Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

namespace eval twapi {
}


# Get the specified shell folder
proc twapi::get_shell_folder {csidl args} {
    variable csidl_lookup

    array set opts [parseargs args {create} -maxleftover 0]

    if {![info exists csidl_lookup]} {
        array set csidl_lookup {
            CSIDL_ADMINTOOLS 0x30
            CSIDL_COMMON_ADMINTOOLS 0x2f
            CSIDL_APPDATA 0x1a
            CSIDL_COMMON_APPDATA 0x23
            CSIDL_COMMON_DESKTOPDIRECTORY 0x19
            CSIDL_COMMON_DOCUMENTS 0x2e
            CSIDL_COMMON_FAVORITES 0x1f
            CSIDL_COMMON_MUSIC 0x35
            CSIDL_COMMON_PICTURES 0x36
            CSIDL_COMMON_PROGRAMS 0x17
            CSIDL_COMMON_STARTMENU 0x16
            CSIDL_COMMON_STARTUP 0x18
            CSIDL_COMMON_TEMPLATES 0x2d
            CSIDL_COMMON_VIDEO 0x37
            CSIDL_COOKIES 0x21
            CSIDL_DESKTOPDIRECTORY 0x10
            CSIDL_FAVORITES 0x6
            CSIDL_HISTORY 0x22
            CSIDL_INTERNET_CACHE 0x20
            CSIDL_LOCAL_APPDATA 0x1c
            CSIDL_MYMUSIC 0xd
            CSIDL_MYPICTURES 0x27
            CSIDL_MYVIDEO 0xe
            CSIDL_NETHOOD 0x13
            CSIDL_PERSONAL 0x5
            CSIDL_PRINTHOOD 0x1b
            CSIDL_PROFILE 0x28
            CSIDL_PROFILES 0x3e
            CSIDL_PROGRAMS 0x2
            CSIDL_PROGRAM_FILES 0x26
            CSIDL_PROGRAM_FILES_COMMON 0x2b
            CSIDL_RECENT 0x8
            CSIDL_SENDTO 0x9
            CSIDL_STARTMENU 0xb
            CSIDL_STARTUP 0x7
            CSIDL_SYSTEM 0x25
            CSIDL_TEMPLATES 0x15
            CSIDL_WINDOWS 0x24
        }
    }

    if {![string is integer $csidl]} {
        set csidl_key [string toupper $csidl]
        if {![info exists csidl_lookup($csidl_key)]} {
            # Try by adding a CSIDL prefix
            set csidl_key "CSIDL_$csidl_key"
            if {![info exists csidl_lookup($csidl_key)]} {
                error "Invalid CSIDL value '$csidl'"
            }
        }
        set csidl $csidl_lookup($csidl_key)
    }

    try {
        set path [SHGetSpecialFolderPath 0 $csidl $opts(create)]
    } onerror {} {
        # Try some other way to get the information
        set code $errorCode
        set msg $errorResult
        set info $errorInfo
        switch -exact -- [format %x $csidl] {
            1a { catch {set path $::env(APPDATA)} }
            2b { catch {set path $::env(CommonProgramFiles)} }
            26 { catch {set path $::env(ProgramFiles)} }
            24 { catch {set path $::env(windir)} }
            25 { catch {set path [file join $::env(systemroot) system32]} }
        }
        if {![info exists path]} {
            #error $msg $info $code
            return ""
        }
    }

    return $path
}

#
# Displays a shell property dialog for the given object
proc twapi::shell_object_properties_dialog {path args} {
    array set opts [parseargs args {
        {type.arg "" {"" file printer volume}}
        {hwin.int 0}
        {page.arg ""}
    } -maxleftover 0]

    if {$opts(type) eq ""} {
        # Try figure out object type
        if {[file exists $path]} {
            set opts(type) file
        } elseif {[lsearch -exact [string tolower [find_volumes]] [string tolower $path]] >= 0} {
            set opts(type) volume
        } else {
            # Check if printer
            foreach printer [enumerate_printers] {
                if {[string equal -nocase [kl_get $printer name] $path]} {
                    set opts(type) printer
                    break
                }
            }
            if {$opts(type) eq ""} {
                error "Could not figure out type of object '$path'"
            }
        }
    }


    if {$opts(type) eq "file"} {
        set path [file nativename [file normalize $path]]
    }

    SHObjectProperties $opts(hwin) \
        [string map {printer 1 file 2 volume 4} $opts(type)] \
        $path \
        $opts(page)
}


#
# Writes a shell shortcut
proc twapi::write_shortcut {link args} {
    
    array set opts [parseargs args {
        path.arg
        idl.arg
        args.arg
        desc.arg
        hotkey.arg
        iconpath.arg
        iconindex.int
        {showcmd.arg normal}
        workdir.arg
        relativepath.arg
    } -nulldefault -maxleftover 0]

    # Map hot key to integer if needed
    if {![string is integer -strict $opts(hotkey)]} {
        if {$opts(hotkey) eq ""} {
            set opts(hotkey) 0
        } else {
            # Try treating it as symbolic
            foreach {modifiers vk} [_hotkeysyms_to_vk $opts(hotkey)] break
            set opts(hotkey) $vk
            if {$modifiers & 1} {
                set opts(hotkey) [expr {$opts(hotkey) | (4<<8)}]
            }
            if {$modifiers & 2} {
                set opts(hotkey) [expr {$opts(hotkey) | (2<<8)}]
            }
            if {$modifiers & 4} {
                set opts(hotkey) [expr {$opts(hotkey) | (1<<8)}]
            }
            if {$modifiers & 8} {
                set opts(hotkey) [expr {$opts(hotkey) | (8<<8)}]
            }
        }
    }

    # IF a known symbol translate it. Note caller can pass integer
    # values as well which will be kept as they are. Bogus valuse and
    # symbols will generate an error on the actual call so we don't
    # check here.
    switch -exact -- $opts(showcmd) {
        minimized { set opts(showcmd) 7 }
        maximized { set opts(showcmd) 3 }
        normal    { set opts(showcmd) 1 }
        hidden    { set opts(showcmd) 0 }
    }

    Twapi_WriteShortcut $link $opts(path) $opts(idl) $opts(args) \
        $opts(desc) $opts(hotkey) $opts(iconpath) $opts(iconindex) \
        $opts(relativepath) $opts(showcmd) $opts(workdir)
}


#
# Read a shortcut
proc twapi::read_shortcut {link args} {
    array set opts [parseargs args {
        shortnames
        uncpath
        rawpath
        timeout.int
        {hwin.int 0}
        install
        nosearch
        notrack
        noui
        nolinkinfo
        anymatch
    } -maxleftover 0]

    set pathfmt 0
    foreach {opt val} {shortnames 1 uncpath 2 rawpath 4} {
        if {$opts($opt)} {
            setbits pathfmt $val
        }
    }

    set resolve_flags 4;                # SLR_UPDATE
    foreach {opt val} {
        install      128
        nolinkinfo    64
        notrack       32
        nosearch      16
        anymatch       2
        noui           1
    } {
        if {$opts($opt)} {
            setbits resolve_flags $val
        }
    }

    array set shortcut [twapi::Twapi_ReadShortcut $link $pathfmt $opts(hwin) $resolve_flags]

    switch -exact -- $shortcut(-showcmd) {
        1 { set shortcut(-showcmd) normal }
        3 { set shortcut(-showcmd) maximized }
        7 { set shortcut(-showcmd) minimized }
    }

    return [array get shortcut]
}



#
# Writes a url shortcut
proc twapi::write_url_shortcut {link url args} {
    
    array set opts [parseargs args {
        {missingprotocol.arg 0 {0 usedefault guess}}
    } -nulldefault -maxleftover 0]

    switch -exact -- $opts(missingprotocol) {
        guess { set opts(missingprotocol) 1 }
        usedefault { set opts(missingprotocol) 2 }
    }

    Twapi_WriteUrlShortcut $link $url $opts(missingprotocol)
}

#
# Read a url shortcut
proc twapi::read_url_shortcut {link} {
    return [Twapi_ReadUrlShortcut $link]
}

#
# Invoke a url shortcut
proc twapi::invoke_url_shortcut {link args} {
    
    array set opts [parseargs args {
        verb.arg
        {hwin.int 0}
        allowui
    } -maxleftover 0]

    set flags 0
    if {$opts(allowui)} {setbits flags 1}
    if {! [info exists opts(verb)]} {
        setbits flags 2
        set opts(verb) ""
    }
    

    Twapi_InvokeUrlShortcut $link $opts(verb) $flags $opts(hwin)
}
Added Binaries/Windows/twapi/synch.tcl.


















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#
# Copyright (c) 2004, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

namespace eval twapi {
}

#
# Create and return a handle to a mutex
proc twapi::create_mutex {args} {
    array set opts [parseargs args {
        {name.arg ""}
        {secd.arg ""}
        {inherit.bool 0}
        lock
    }]

    return [CreateMutex [_make_secattr $opts(secd) $opts(inherit)] $opts(lock) $opts(name)]
}

# Get handle to an existing mutex
proc twapi::get_mutex_handle {name args} {
    array set opts [parseargs args {
        {inherit.bool 0}
        {access.arg {mutex_all_access}}
    }]
    
    return [OpenMutex [_access_rights_to_mask $opts(access)] $opts(inherit) $name]
}

# Lock the mutex
proc twapi::lock_mutex {h args} {
    array set opts [parseargs args {
        {wait.int 1000}
    }]

    return [wait_on_handles [list $h] -wait $opts(wait)]
}


# Unlock the mutex
proc twapi::unlock_mutex {h} {
    ReleaseMutex $h
}

#
# Wait on multiple handles
proc twapi::wait_on_handles {hlist args} {
    array set opts [parseargs args {
        {all.bool 0}
        {wait.int 1000}
    }]

    return [WaitForMultipleObjects $hlist $opts(all) $opts(wait)]
}
Added Binaries/Windows/twapi/twapi.dll.

cannot compute difference between binary files

Added Binaries/Windows/twapi/twapi.tcl.














































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
#
# Copyright (c) 2003, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

# General definitions and procs used by all TWAPI modules

package require Tcl 8.4
package require registry

namespace eval twapi {
    variable nullptr "__null__"
    variable scriptdir [file dirname [info script]]

}

if {![info exists twapi::version]} {
    set dir $twapi::scriptdir;          # Needed by pkgIndex
    source [file join $twapi::scriptdir pkgIndex.tcl]
}

load [file join $twapi::scriptdir twapi.dll]


# Adds the specified Windows header defines into a global array
# deflist is a flat list of name value pairs
proc twapi::add_defines {deflist} {
    variable windefs
    array set windefs $deflist
}


twapi::add_defines {
    VER_NT_WORKSTATION              0x0000001
    VER_NT_DOMAIN_CONTROLLER        0x0000002
    VER_NT_SERVER                   0x0000003

    VER_SERVER_NT                       0x80000000
    VER_WORKSTATION_NT                  0x40000000
    VER_SUITE_SMALLBUSINESS             0x00000001
    VER_SUITE_ENTERPRISE                0x00000002
    VER_SUITE_BACKOFFICE                0x00000004
    VER_SUITE_COMMUNICATIONS            0x00000008
    VER_SUITE_TERMINAL                  0x00000010
    VER_SUITE_SMALLBUSINESS_RESTRICTED  0x00000020
    VER_SUITE_EMBEDDEDNT                0x00000040
    VER_SUITE_DATACENTER                0x00000080
    VER_SUITE_SINGLEUSERTS              0x00000100
    VER_SUITE_PERSONAL                  0x00000200
    VER_SUITE_BLADE                     0x00000400

    DELETE                         0x00010000
    READ_CONTROL                   0x00020000
    WRITE_DAC                      0x00040000
    WRITE_OWNER                    0x00080000
    SYNCHRONIZE                    0x00100000

    STANDARD_RIGHTS_REQUIRED       0x000F0000
    STANDARD_RIGHTS_READ           0x00020000
    STANDARD_RIGHTS_WRITE          0x00020000
    STANDARD_RIGHTS_EXECUTE        0x00020000
    STANDARD_RIGHTS_ALL            0x001F0000
    SPECIFIC_RIGHTS_ALL            0x0000FFFF

    GENERIC_READ                   0x80000000
    GENERIC_WRITE                  0x40000000
    GENERIC_EXECUTE                0x20000000
    GENERIC_ALL                    0x10000000

    DESKTOP_READOBJECTS         0x0001
    DESKTOP_CREATEWINDOW        0x0002
    DESKTOP_CREATEMENU          0x0004
    DESKTOP_HOOKCONTROL         0x0008
    DESKTOP_JOURNALRECORD       0x0010
    DESKTOP_JOURNALPLAYBACK     0x0020
    DESKTOP_ENUMERATE           0x0040
    DESKTOP_WRITEOBJECTS        0x0080
    DESKTOP_SWITCHDESKTOP       0x0100

    DF_ALLOWOTHERACCOUNTHOOK    0x0001

    WINSTA_ENUMDESKTOPS         0x0001
    WINSTA_READATTRIBUTES       0x0002
    WINSTA_ACCESSCLIPBOARD      0x0004
    WINSTA_CREATEDESKTOP        0x0008
    WINSTA_WRITEATTRIBUTES      0x0010
    WINSTA_ACCESSGLOBALATOMS    0x0020
    WINSTA_EXITWINDOWS          0x0040
    WINSTA_ENUMERATE            0x0100
    WINSTA_READSCREEN           0x0200

    WINSTA_ALL_ACCESS           0x37f

    FILE_READ_DATA                 0x00000001
    FILE_LIST_DIRECTORY            0x00000001
    FILE_WRITE_DATA                0x00000002
    FILE_ADD_FILE                  0x00000002
    FILE_APPEND_DATA               0x00000004
    FILE_ADD_SUBDIRECTORY          0x00000004
    FILE_CREATE_PIPE_INSTANCE      0x00000004
    FILE_READ_EA                   0x00000008
    FILE_WRITE_EA                  0x00000010
    FILE_EXECUTE                   0x00000020
    FILE_TRAVERSE                  0x00000020
    FILE_DELETE_CHILD              0x00000040
    FILE_READ_ATTRIBUTES           0x00000080
    FILE_WRITE_ATTRIBUTES          0x00000100

    FILE_ALL_ACCESS                0x001F01FF
    FILE_GENERIC_READ              0x00120089
    FILE_GENERIC_WRITE             0x00120116
    FILE_GENERIC_EXECUTE           0x001200A0

    FILE_SHARE_READ                    0x00000001  
    FILE_SHARE_WRITE                   0x00000002  
    FILE_SHARE_DELETE                  0x00000004  

    FILE_ATTRIBUTE_READONLY             0x00000001  
    FILE_ATTRIBUTE_HIDDEN               0x00000002  
    FILE_ATTRIBUTE_SYSTEM               0x00000004  
    FILE_ATTRIBUTE_DIRECTORY            0x00000010  
    FILE_ATTRIBUTE_ARCHIVE              0x00000020  
    FILE_ATTRIBUTE_DEVICE               0x00000040  
    FILE_ATTRIBUTE_NORMAL               0x00000080  
    FILE_ATTRIBUTE_TEMPORARY            0x00000100  
    FILE_ATTRIBUTE_SPARSE_FILE          0x00000200  
    FILE_ATTRIBUTE_REPARSE_POINT        0x00000400  
    FILE_ATTRIBUTE_COMPRESSED           0x00000800  
    FILE_ATTRIBUTE_OFFLINE              0x00001000  
    FILE_ATTRIBUTE_NOT_CONTENT_INDEXED  0x00002000  
    FILE_ATTRIBUTE_ENCRYPTED            0x00004000  

    FILE_NOTIFY_CHANGE_FILE_NAME    0x00000001   
    FILE_NOTIFY_CHANGE_DIR_NAME     0x00000002   
    FILE_NOTIFY_CHANGE_ATTRIBUTES   0x00000004   
    FILE_NOTIFY_CHANGE_SIZE         0x00000008   
    FILE_NOTIFY_CHANGE_LAST_WRITE   0x00000010   
    FILE_NOTIFY_CHANGE_LAST_ACCESS  0x00000020   
    FILE_NOTIFY_CHANGE_CREATION     0x00000040   
    FILE_NOTIFY_CHANGE_SECURITY     0x00000100   

    FILE_ACTION_ADDED                   0x00000001   
    FILE_ACTION_REMOVED                 0x00000002   
    FILE_ACTION_MODIFIED                0x00000003   
    FILE_ACTION_RENAMED_OLD_NAME        0x00000004   
    FILE_ACTION_RENAMED_NEW_NAME        0x00000005   

    FILE_CASE_SENSITIVE_SEARCH      0x00000001  
    FILE_CASE_PRESERVED_NAMES       0x00000002  
    FILE_UNICODE_ON_DISK            0x00000004  
    FILE_PERSISTENT_ACLS            0x00000008  
    FILE_FILE_COMPRESSION           0x00000010  
    FILE_VOLUME_QUOTAS              0x00000020  
    FILE_SUPPORTS_SPARSE_FILES      0x00000040  
    FILE_SUPPORTS_REPARSE_POINTS    0x00000080  
    FILE_SUPPORTS_REMOTE_STORAGE    0x00000100  
    FILE_VOLUME_IS_COMPRESSED       0x00008000  
    FILE_SUPPORTS_OBJECT_IDS        0x00010000  
    FILE_SUPPORTS_ENCRYPTION        0x00020000  
    FILE_NAMED_STREAMS              0x00040000  
    FILE_READ_ONLY_VOLUME           0x00080000  

    CREATE_NEW          1
    CREATE_ALWAYS       2
    OPEN_EXISTING       3
    OPEN_ALWAYS         4
    TRUNCATE_EXISTING   5


    KEY_QUERY_VALUE                0x00000001
    KEY_SET_VALUE                  0x00000002
    KEY_CREATE_SUB_KEY             0x00000004
    KEY_ENUMERATE_SUB_KEYS         0x00000008
    KEY_NOTIFY                     0x00000010
    KEY_CREATE_LINK                0x00000020
    KEY_WOW64_32KEY                0x00000200
    KEY_WOW64_64KEY                0x00000100
    KEY_WOW64_RES                  0x00000300

    KEY_READ                       0x00020019
    KEY_WRITE                      0x00020006
    KEY_EXECUTE                    0x00020019

    KEY_ALL_ACCESS                 0x000F003F

    SERVICE_QUERY_CONFIG           0x00000001
    SERVICE_CHANGE_CONFIG          0x00000002
    SERVICE_QUERY_STATUS           0x00000004
    SERVICE_ENUMERATE_DEPENDENTS   0x00000008
    SERVICE_START                  0x00000010
    SERVICE_STOP                   0x00000020
    SERVICE_PAUSE_CONTINUE         0x00000040
    SERVICE_INTERROGATE            0x00000080
    SERVICE_USER_DEFINED_CONTROL   0x00000100

    SERVICE_ALL_ACCESS             0x000F01FF

    POLICY_VIEW_LOCAL_INFORMATION   0x00000001
    POLICY_VIEW_AUDIT_INFORMATION   0x00000002
    POLICY_GET_PRIVATE_INFORMATION  0x00000004
    POLICY_TRUST_ADMIN              0x00000008
    POLICY_CREATE_ACCOUNT           0x00000010
    POLICY_CREATE_SECRET            0x00000020
    POLICY_CREATE_PRIVILEGE         0x00000040
    POLICY_SET_DEFAULT_QUOTA_LIMITS 0x00000080
    POLICY_SET_AUDIT_REQUIREMENTS   0x00000100
    POLICY_AUDIT_LOG_ADMIN          0x00000200
    POLICY_SERVER_ADMIN             0x00000400
    POLICY_LOOKUP_NAMES             0x00000800
    POLICY_NOTIFICATION             0x00001000

    POLICY_ALL_ACCESS               0X000F0FFF
    POLICY_READ                     0X00020006
    POLICY_WRITE                    0X000207F8
    POLICY_EXECUTE                  0X00020801


    PROCESS_TERMINATE              0x00000001
    PROCESS_CREATE_THREAD          0x00000002
    PROCESS_SET_SESSIONID          0x00000004
    PROCESS_VM_OPERATION           0x00000008
    PROCESS_VM_READ                0x00000010
    PROCESS_VM_WRITE               0x00000020
    PROCESS_DUP_HANDLE             0x00000040
    PROCESS_CREATE_PROCESS         0x00000080
    PROCESS_SET_QUOTA              0x00000100
    PROCESS_SET_INFORMATION        0x00000200
    PROCESS_QUERY_INFORMATION      0x00000400
    PROCESS_SUSPEND_RESUME         0x00000800

    PROCESS_ALL_ACCESS             0x001f0fff

    THREAD_TERMINATE               0x00000001
    THREAD_SUSPEND_RESUME          0x00000002
    THREAD_GET_CONTEXT             0x00000008
    THREAD_SET_CONTEXT             0x00000010
    THREAD_SET_INFORMATION         0x00000020
    THREAD_QUERY_INFORMATION       0x00000040
    THREAD_SET_THREAD_TOKEN        0x00000080
    THREAD_IMPERSONATE             0x00000100
    THREAD_DIRECT_IMPERSONATION    0x00000200

    THREAD_ALL_ACCESS              0x001f03ff

    EVENT_MODIFY_STATE             0x00000002
    EVENT_ALL_ACCESS               0x001F0003

    SEMAPHORE_MODIFY_STATE         0x00000002
    SEMAPHORE_ALL_ACCESS           0x001F0003
    
    MUTANT_QUERY_STATE             0x00000001
    MUTANT_ALL_ACCESS              0x001F0001

    MUTEX_MODIFY_STATE             0x00000001
    MUTEX_ALL_ACCESS               0x001F0001

    TIMER_QUERY_STATE              0x00000001
    TIMER_MODIFY_STATE             0x00000002
    TIMER_ALL_ACCESS               0x001F0003

    TOKEN_ASSIGN_PRIMARY           0x00000001
    TOKEN_DUPLICATE                0x00000002
    TOKEN_IMPERSONATE              0x00000004
    TOKEN_QUERY                    0x00000008
    TOKEN_QUERY_SOURCE             0x00000010
    TOKEN_ADJUST_PRIVILEGES        0x00000020
    TOKEN_ADJUST_GROUPS            0x00000040
    TOKEN_ADJUST_DEFAULT           0x00000080
    TOKEN_ADJUST_SESSIONID         0x00000100

    TOKEN_ALL_ACCESS_WINNT         0x000F00FF
    TOKEN_ALL_ACCESS_WIN2K         0x000F01FF
    TOKEN_READ                     0x00020008
    TOKEN_WRITE                    0x000200E0
    TOKEN_EXECUTE                  0x00020000

    OBJECT_INHERIT_ACE                0x1
    CONTAINER_INHERIT_ACE             0x2
    NO_PROPAGATE_INHERIT_ACE          0x4
    INHERIT_ONLY_ACE                  0x8
    INHERITED_ACE                     0x10
    VALID_INHERIT_FLAGS               0x1F

    ACL_REVISION     2
    ACL_REVISION_DS  4

    ACCESS_ALLOWED_ACE_TYPE                 0x0
    ACCESS_DENIED_ACE_TYPE                  0x1
    SYSTEM_AUDIT_ACE_TYPE                   0x2
    SYSTEM_ALARM_ACE_TYPE                   0x3
    ACCESS_ALLOWED_COMPOUND_ACE_TYPE        0x4
    ACCESS_ALLOWED_OBJECT_ACE_TYPE          0x5
    ACCESS_DENIED_OBJECT_ACE_TYPE           0x6
    SYSTEM_AUDIT_OBJECT_ACE_TYPE            0x7
    SYSTEM_ALARM_OBJECT_ACE_TYPE            0x8
    ACCESS_ALLOWED_CALLBACK_ACE_TYPE        0x9
    ACCESS_DENIED_CALLBACK_ACE_TYPE         0xA
    ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0xB
    ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE  0xC
    SYSTEM_AUDIT_CALLBACK_ACE_TYPE          0xD
    SYSTEM_ALARM_CALLBACK_ACE_TYPE          0xE
    SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE   0xF
    SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE   0x10

    OWNER_SECURITY_INFORMATION              0x00000001
    GROUP_SECURITY_INFORMATION              0x00000002
    DACL_SECURITY_INFORMATION               0x00000004
    SACL_SECURITY_INFORMATION               0x00000008
    PROTECTED_DACL_SECURITY_INFORMATION     0x80000000
    PROTECTED_SACL_SECURITY_INFORMATION     0x40000000
    UNPROTECTED_DACL_SECURITY_INFORMATION   0x20000000
    UNPROTECTED_SACL_SECURITY_INFORMATION   0x10000000

    TokenUser                      1
    TokenGroups                    2
    TokenPrivileges                3
    TokenOwner                     4
    TokenPrimaryGroup              5
    TokenDefaultDacl               6
    TokenSource                    7
    TokenType                      8
    TokenImpersonationLevel        9      
    TokenStatistics               10
    TokenRestrictedSids           11  
    TokenSessionId                12
    TokenGroupsAndPrivileges      13       
    TokenSessionReference         14    
    TokenSandBoxInert             15

    SE_GROUP_MANDATORY              0x00000001
    SE_GROUP_ENABLED_BY_DEFAULT     0x00000002
    SE_GROUP_ENABLED                0x00000004
    SE_GROUP_OWNER                  0x00000008
    SE_GROUP_USE_FOR_DENY_ONLY      0x00000010
    SE_GROUP_LOGON_ID               0xC0000000
    SE_GROUP_RESOURCE               0x20000000
    SE_PRIVILEGE_ENABLED_BY_DEFAULT 0x00000001
    SE_PRIVILEGE_ENABLED            0x00000002
    SE_PRIVILEGE_USED_FOR_ACCESS    0x80000000

    SC_MANAGER_CONNECT             0x00000001
    SC_MANAGER_CREATE_SERVICE      0x00000002
    SC_MANAGER_ENUMERATE_SERVICE   0x00000004
    SC_MANAGER_LOCK                0x00000008
    SC_MANAGER_QUERY_LOCK_STATUS   0x00000010
    SC_MANAGER_MODIFY_BOOT_CONFIG  0x00000020
    SC_MANAGER_ALL_ACCESS          0x000F003F    

    SERVICE_NO_CHANGE              0xffffffff

    SERVICE_KERNEL_DRIVER          0x00000001
    SERVICE_FILE_SYSTEM_DRIVER     0x00000002
    SERVICE_ADAPTER                0x00000004
    SERVICE_RECOGNIZER_DRIVER      0x00000008
    SERVICE_WIN32_OWN_PROCESS      0x00000010
    SERVICE_WIN32_SHARE_PROCESS    0x00000020

    SERVICE_INTERACTIVE_PROCESS    0x00000100

    SERVICE_BOOT_START             0x00000000
    SERVICE_SYSTEM_START           0x00000001
    SERVICE_AUTO_START             0x00000002
    SERVICE_DEMAND_START           0x00000003
    SERVICE_DISABLED               0x00000004

    SERVICE_ERROR_IGNORE           0x00000000
    SERVICE_ERROR_NORMAL           0x00000001
    SERVICE_ERROR_SEVERE           0x00000002
    SERVICE_ERROR_CRITICAL         0x00000003

    SERVICE_CONTROL_STOP                   0x00000001
    SERVICE_CONTROL_PAUSE                  0x00000002
    SERVICE_CONTROL_CONTINUE               0x00000003
    SERVICE_CONTROL_INTERROGATE            0x00000004
    SERVICE_CONTROL_SHUTDOWN               0x00000005
    SERVICE_CONTROL_PARAMCHANGE            0x00000006
    SERVICE_CONTROL_NETBINDADD             0x00000007
    SERVICE_CONTROL_NETBINDREMOVE          0x00000008
    SERVICE_CONTROL_NETBINDENABLE          0x00000009
    SERVICE_CONTROL_NETBINDDISABLE         0x0000000A
    SERVICE_CONTROL_DEVICEEVENT            0x0000000B
    SERVICE_CONTROL_HARDWAREPROFILECHANGE  0x0000000C
    SERVICE_CONTROL_POWEREVENT             0x0000000D
    SERVICE_CONTROL_SESSIONCHANGE          0x0000000E

    SERVICE_ACTIVE                 0x00000001
    SERVICE_INACTIVE               0x00000002
    SERVICE_STATE_ALL              0x00000003

    SERVICE_STOPPED                        0x00000001
    SERVICE_START_PENDING                  0x00000002
    SERVICE_STOP_PENDING                   0x00000003
    SERVICE_RUNNING                        0x00000004
    SERVICE_CONTINUE_PENDING               0x00000005
    SERVICE_PAUSE_PENDING                  0x00000006
    SERVICE_PAUSED                         0x00000007

    GA_PARENT       1
    GA_ROOT         2
    GA_ROOTOWNER    3

    GW_HWNDFIRST        0
    GW_HWNDLAST         1
    GW_HWNDNEXT         2
    GW_HWNDPREV         3
    GW_OWNER            4
    GW_CHILD            5
    GW_ENABLEDPOPUP     6

    GWL_WNDPROC         -4
    GWL_HINSTANCE       -6
    GWL_HWNDPARENT      -8
    GWL_STYLE           -16
    GWL_EXSTYLE         -20
    GWL_USERDATA        -21
    GWL_ID              -12

    SW_HIDE             0
    SW_SHOWNORMAL       1
    SW_NORMAL           1
    SW_SHOWMINIMIZED    2
    SW_SHOWMAXIMIZED    3
    SW_MAXIMIZE         3
    SW_SHOWNOACTIVATE   4
    SW_SHOW             5
    SW_MINIMIZE         6
    SW_SHOWMINNOACTIVE  7
    SW_SHOWNA           8
    SW_RESTORE          9
    SW_SHOWDEFAULT      10
    SW_FORCEMINIMIZE    11

    WS_OVERLAPPED       0x00000000
    WS_TILED            0x00000000
    WS_POPUP            0x80000000
    WS_CHILD            0x40000000
    WS_MINIMIZE         0x20000000
    WS_ICONIC           0x20000000
    WS_VISIBLE          0x10000000
    WS_DISABLED         0x08000000
    WS_CLIPSIBLINGS     0x04000000
    WS_CLIPCHILDREN     0x02000000
    WS_MAXIMIZE         0x01000000
    WS_BORDER           0x00800000
    WS_DLGFRAME         0x00400000
    WS_CAPTION          0x00C00000
    WS_VSCROLL          0x00200000
    WS_HSCROLL          0x00100000
    WS_SYSMENU          0x00080000
    WS_THICKFRAME       0x00040000
    WS_SIZEBOX          0x00040000
    WS_GROUP            0x00020000
    WS_TABSTOP          0x00010000

    WS_MINIMIZEBOX      0x00020000
    WS_MAXIMIZEBOX      0x00010000

    WS_EX_DLGMODALFRAME     0x00000001
    WS_EX_NOPARENTNOTIFY    0x00000004
    WS_EX_TOPMOST           0x00000008
    WS_EX_ACCEPTFILES       0x00000010
    WS_EX_TRANSPARENT       0x00000020
    WS_EX_MDICHILD          0x00000040
    WS_EX_TOOLWINDOW        0x00000080
    WS_EX_WINDOWEDGE        0x00000100
    WS_EX_CLIENTEDGE        0x00000200
    WS_EX_CONTEXTHELP       0x00000400

    WS_EX_RIGHT             0x00001000
    WS_EX_LEFT              0x00000000
    WS_EX_RTLREADING        0x00002000
    WS_EX_LTRREADING        0x00000000
    WS_EX_LEFTSCROLLBAR     0x00004000
    WS_EX_RIGHTSCROLLBAR    0x00000000

    WS_EX_CONTROLPARENT     0x00010000
    WS_EX_STATICEDGE        0x00020000
    WS_EX_APPWINDOW         0x00040000

    CS_VREDRAW          0x0001
    CS_HREDRAW          0x0002
    CS_DBLCLKS          0x0008
    CS_OWNDC            0x0020
    CS_CLASSDC          0x0040
    CS_PARENTDC         0x0080
    CS_NOCLOSE          0x0200
    CS_SAVEBITS         0x0800
    CS_BYTEALIGNCLIENT  0x1000
    CS_BYTEALIGNWINDOW  0x2000
    CS_GLOBALCLASS      0x4000

    SWP_NOSIZE          0x0001
    SWP_NOMOVE          0x0002
    SWP_NOZORDER        0x0004
    SWP_NOREDRAW        0x0008
    SWP_NOACTIVATE      0x0010
    SWP_FRAMECHANGED    0x0020
    SWP_DRAWFRAME       0x0020
    SWP_SHOWWINDOW      0x0040
    SWP_HIDEWINDOW      0x0080
    SWP_NOCOPYBITS      0x0100
    SWP_NOOWNERZORDER   0x0200
    SWP_NOREPOSITION    0x0200
    SWP_NOSENDCHANGING  0x0400

    SWP_DEFERERASE      0x2000
    SWP_ASYNCWINDOWPOS  0x4000

    SMTO_NORMAL         0x0000
    SMTO_BLOCK          0x0001
    SMTO_ABORTIFHUNG    0x0002

    HWND_TOP         0
    HWND_BOTTOM      1
    HWND_TOPMOST    -1
    HWND_NOTOPMOST   2


    WM_NULL                         0x0000
    WM_CREATE                       0x0001
    WM_DESTROY                      0x0002
    WM_MOVE                         0x0003
    WM_SIZE                         0x0005
    WM_ACTIVATE                     0x0006
    WM_SETFOCUS                     0x0007
    WM_KILLFOCUS                    0x0008
    WM_ENABLE                       0x000A
    WM_SETREDRAW                    0x000B
    WM_SETTEXT                      0x000C
    WM_GETTEXT                      0x000D
    WM_GETTEXTLENGTH                0x000E
    WM_PAINT                        0x000F
    WM_CLOSE                        0x0010
    WM_QUERYENDSESSION              0x0011
    WM_QUERYOPEN                    0x0013
    WM_ENDSESSION                   0x0016
    WM_QUIT                         0x0012
    WM_ERASEBKGND                   0x0014
    WM_SYSCOLORCHANGE               0x0015
    WM_SHOWWINDOW                   0x0018
    WM_WININICHANGE                 0x001A
    WM_SETTINGCHANGE                WM_WININICHANGE
    WM_DEVMODECHANGE                0x001B
    WM_ACTIVATEAPP                  0x001C
    WM_FONTCHANGE                   0x001D
    WM_TIMECHANGE                   0x001E
    WM_CANCELMODE                   0x001F
    WM_SETCURSOR                    0x0020
    WM_MOUSEACTIVATE                0x0021
    WM_CHILDACTIVATE                0x0022
    WM_QUEUESYNC                    0x0023
    WM_GETMINMAXINFO                0x0024

    PERF_DETAIL_NOVICE          100
    PERF_DETAIL_ADVANCED        200
    PERF_DETAIL_EXPERT          300
    PERF_DETAIL_WIZARD          400

    PDH_FMT_RAW     0x00000010
    PDH_FMT_ANSI    0x00000020
    PDH_FMT_UNICODE 0x00000040
    PDH_FMT_LONG    0x00000100
    PDH_FMT_DOUBLE  0x00000200
    PDH_FMT_LARGE   0x00000400
    PDH_FMT_NOSCALE 0x00001000
    PDH_FMT_1000    0x00002000
    PDH_FMT_NODATA  0x00004000
    PDH_FMT_NOCAP100 0x00008000

    PERF_DETAIL_COSTLY   0x00010000
    PERF_DETAIL_STANDARD 0x0000FFFF

    UF_SCRIPT                          0x0001
    UF_ACCOUNTDISABLE                  0x0002
    UF_HOMEDIR_REQUIRED                0x0008
    UF_LOCKOUT                         0x0010
    UF_PASSWD_NOTREQD                  0x0020
    UF_PASSWD_CANT_CHANGE              0x0040
    UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED 0x0080
    UF_TEMP_DUPLICATE_ACCOUNT       0x0100
    UF_NORMAL_ACCOUNT               0x0200
    UF_INTERDOMAIN_TRUST_ACCOUNT    0x0800
    UF_WORKSTATION_TRUST_ACCOUNT    0x1000
    UF_SERVER_TRUST_ACCOUNT         0x2000
    UF_DONT_EXPIRE_PASSWD           0x10000
    UF_MNS_LOGON_ACCOUNT            0x20000
    UF_SMARTCARD_REQUIRED           0x40000
    UF_TRUSTED_FOR_DELEGATION       0x80000
    UF_NOT_DELEGATED               0x100000
    UF_USE_DES_KEY_ONLY            0x200000
    UF_DONT_REQUIRE_PREAUTH        0x400000
    UF_PASSWORD_EXPIRED            0x800000
    UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION 0x1000000

    FILE_CASE_PRESERVED_NAMES       0x00000002  
    FILE_UNICODE_ON_DISK            0x00000004  
    FILE_PERSISTENT_ACLS            0x00000008  
    FILE_FILE_COMPRESSION           0x00000010  
    FILE_VOLUME_QUOTAS              0x00000020  
    FILE_SUPPORTS_SPARSE_FILES      0x00000040  
    FILE_SUPPORTS_REPARSE_POINTS    0x00000080  
    FILE_SUPPORTS_REMOTE_STORAGE    0x00000100  
    FILE_VOLUME_IS_COMPRESSED       0x00008000  
    FILE_SUPPORTS_OBJECT_IDS        0x00010000  
    FILE_SUPPORTS_ENCRYPTION        0x00020000  
    FILE_NAMED_STREAMS              0x00040000  
    FILE_READ_ONLY_VOLUME           0x00080000  

    KEYEVENTF_EXTENDEDKEY 0x0001
    KEYEVENTF_KEYUP       0x0002
    KEYEVENTF_UNICODE     0x0004
    KEYEVENTF_SCANCODE    0x0008

    MOUSEEVENTF_MOVE        0x0001
    MOUSEEVENTF_LEFTDOWN    0x0002
    MOUSEEVENTF_LEFTUP      0x0004
    MOUSEEVENTF_RIGHTDOWN   0x0008
    MOUSEEVENTF_RIGHTUP     0x0010
    MOUSEEVENTF_MIDDLEDOWN  0x0020
    MOUSEEVENTF_MIDDLEUP    0x0040
    MOUSEEVENTF_XDOWN       0x0080
    MOUSEEVENTF_XUP         0x0100
    MOUSEEVENTF_WHEEL       0x0800
    MOUSEEVENTF_VIRTUALDESK 0x4000
    MOUSEEVENTF_ABSOLUTE    0x8000

    XBUTTON1      0x0001
    XBUTTON2      0x0002

    VK_BACK           0x08
    VK_TAB            0x09
    VK_CLEAR          0x0C
    VK_RETURN         0x0D
    VK_SHIFT          0x10
    VK_CONTROL        0x11
    VK_MENU           0x12
    VK_PAUSE          0x13
    VK_CAPITAL        0x14
    VK_KANA           0x15
    VK_HANGEUL        0x15
    VK_HANGUL         0x15
    VK_JUNJA          0x17
    VK_FINAL          0x18
    VK_HANJA          0x19
    VK_KANJI          0x19
    VK_ESCAPE         0x1B
    VK_CONVERT        0x1C
    VK_NONCONVERT     0x1D
    VK_ACCEPT         0x1E
    VK_MODECHANGE     0x1F
    VK_SPACE          0x20
    VK_PRIOR          0x21
    VK_NEXT           0x22
    VK_END            0x23
    VK_HOME           0x24
    VK_LEFT           0x25
    VK_UP             0x26
    VK_RIGHT          0x27
    VK_DOWN           0x28
    VK_SELECT         0x29
    VK_PRINT          0x2A
    VK_EXECUTE        0x2B
    VK_SNAPSHOT       0x2C
    VK_INSERT         0x2D
    VK_DELETE         0x2E
    VK_HELP           0x2F
    VK_LWIN           0x5B
    VK_RWIN           0x5C
    VK_APPS           0x5D
    VK_SLEEP          0x5F
    VK_NUMPAD0        0x60
    VK_NUMPAD1        0x61
    VK_NUMPAD2        0x62
    VK_NUMPAD3        0x63
    VK_NUMPAD4        0x64
    VK_NUMPAD5        0x65
    VK_NUMPAD6        0x66
    VK_NUMPAD7        0x67
    VK_NUMPAD8        0x68
    VK_NUMPAD9        0x69
    VK_MULTIPLY       0x6A
    VK_ADD            0x6B
    VK_SEPARATOR      0x6C
    VK_SUBTRACT       0x6D
    VK_DECIMAL        0x6E
    VK_DIVIDE         0x6F
    VK_F1             0x70
    VK_F2             0x71
    VK_F3             0x72
    VK_F4             0x73
    VK_F5             0x74
    VK_F6             0x75
    VK_F7             0x76
    VK_F8             0x77
    VK_F9             0x78
    VK_F10            0x79
    VK_F11            0x7A
    VK_F12            0x7B
    VK_F13            0x7C
    VK_F14            0x7D
    VK_F15            0x7E
    VK_F16            0x7F
    VK_F17            0x80
    VK_F18            0x81
    VK_F19            0x82
    VK_F20            0x83
    VK_F21            0x84
    VK_F22            0x85
    VK_F23            0x86
    VK_F24            0x87
    VK_NUMLOCK        0x90
    VK_SCROLL         0x91
    VK_LSHIFT         0xA0
    VK_RSHIFT         0xA1
    VK_LCONTROL       0xA2
    VK_RCONTROL       0xA3
    VK_LMENU          0xA4
    VK_RMENU          0xA5
    VK_BROWSER_BACK        0xA6
    VK_BROWSER_FORWARD     0xA7
    VK_BROWSER_REFRESH     0xA8
    VK_BROWSER_STOP        0xA9
    VK_BROWSER_SEARCH      0xAA
    VK_BROWSER_FAVORITES   0xAB
    VK_BROWSER_HOME        0xAC
    VK_VOLUME_MUTE         0xAD
    VK_VOLUME_DOWN         0xAE
    VK_VOLUME_UP           0xAF
    VK_MEDIA_NEXT_TRACK    0xB0
    VK_MEDIA_PREV_TRACK    0xB1
    VK_MEDIA_STOP          0xB2
    VK_MEDIA_PLAY_PAUSE    0xB3
    VK_LAUNCH_MAIL         0xB4
    VK_LAUNCH_MEDIA_SELECT 0xB5
    VK_LAUNCH_APP1         0xB6
    VK_LAUNCH_APP2         0xB7

    SND_SYNC            0x0000
    SND_ASYNC           0x0001
    SND_NODEFAULT       0x0002
    SND_MEMORY          0x0004
    SND_LOOP            0x0008
    SND_NOSTOP          0x0010
    SND_NOWAIT      0x00002000
    SND_ALIAS       0x00010000
    SND_ALIAS_ID    0x00110000
    SND_FILENAME    0x00020000
    SND_RESOURCE    0x00040004
    SND_PURGE           0x0040
    SND_APPLICATION     0x0080


    STYPE_DISKTREE          0
    STYPE_PRINTQ            1
    STYPE_DEVICE            2
    STYPE_IPC               3
    STYPE_TEMPORARY         0x40000000
    STYPE_SPECIAL           0x80000000

    LOGON32_LOGON_INTERACTIVE       2
    LOGON32_LOGON_NETWORK           3
    LOGON32_LOGON_BATCH             4
    LOGON32_LOGON_SERVICE           5
    LOGON32_LOGON_UNLOCK            7
    LOGON32_LOGON_NETWORK_CLEARTEXT 8
    LOGON32_LOGON_NEW_CREDENTIALS   9

    LOGON32_PROVIDER_DEFAULT    0
    LOGON32_PROVIDER_WINNT35    1
    LOGON32_PROVIDER_WINNT40    2
    LOGON32_PROVIDER_WINNT50    3

}

#
# Returns a list of raw Windows API functions supported
proc twapi::list_raw_api {} {
    set rawapi [list ]
    foreach fn [info commands ::twapi::*] {
         if {[regexp {^::twapi::([A-Z][^_]*)$} $fn ignore fn]} {
             lappend rawapi $fn
         }
    }
    return $rawapi
}


#
# Close a handle
proc twapi::close_handles {args} {
    foreach h [concat $args] {
        if {[catch {CloseHandle $h} msg]} {
            set erinfo $::errorInfo
            set ercode $::errorCode
            set ermsg $msg
        }
    }
    if {[info exists erinfo]} {
        error $msg $erinfo $ercode
    }
}

#
# Get the handle for a Tcl channel
proc twapi::get_tcl_channel_handle {chan direction} {
    set direction [expr {[string equal $direction "write"] ? 1 : 0}]
    return [Tcl_GetChannelHandle $chan $direction]
}

#
# Wait for $wait_ms milliseconds or until $script returns $guard. $gap_ms is
# time between retries to call $script
# TBD - write a version that will allow other events to be processed
proc twapi::wait {script guard wait_ms {gap_ms 10}} {
    if {$gap_ms == 0} {
        set gap_ms 10
    }
    set end_ms [expr {[clock clicks -milliseconds] + $wait_ms}]
    while {[clock clicks -milliseconds] < $end_ms} {
        set script_result [uplevel $script]
        if {[string equal $script_result $guard]} {
            return 1
        }
        after $gap_ms
    }
    # Reached limit, one last try
    return [string equal [uplevel $script] $guard]
}

#
# Get tcl version
proc twapi::get_version {args} {
    array set opts [parseargs args {patchlevel}]
    if {$opts(patchlevel)} {
        return "${twapi::version}${twapi::patchlevel}"
    } else {
        return $twapi::version
    }
}



# Set all elements of the array to specified value
proc twapi::_array_set_all {v_arr val} {
    upvar $v_arr arr
    foreach e [array names arr] {
        set arr($e) $val
    }
}

# Check if any of the specified array elements are non-0
proc twapi::_array_non_zero_entry {v_arr indices} {
    upvar $v_arr arr
    foreach i $indices {
        if {$arr($i)} {
            return 1
        }
    }
    return 0
}

# Check if any of the specified array elements are non-0
# and return them as a list of options (preceded with -)
proc twapi::_array_non_zero_switches {v_arr indices all} {
    upvar $v_arr arr
    set result [list ]
    foreach i $indices {
        if {$all || ([info exists arr($i)] && $arr($i))} {
            lappend result -$i
        }
    }
    return $result
}

#
# Return a list of the form "field value field value..." for all
# fields in a SWIG generated struct
proc twapi::swig_struct_fields {structptr structname} {
    set result [list ]
    foreach fieldcmd [info commands :::twapi::${structname}_*_get] {
        if {[catch {$fieldcmd $structptr} fieldval] == 0} {
            regexp "${structname}_(.*)_get" $fieldcmd dontcare fieldname
            lappend result $fieldname $fieldval
        }
 
    }
    return $result
}


#
# Bitmask operations on 32bit values
# The int() casts are to deal with hex-decimal sign extension issues
proc twapi::setbits {v_bits mask} {
    upvar $v_bits bits
    set bits [expr {int($bits) | int($mask)}]
    return $bits
}
proc twapi::resetbits {v_bits mask} {
    upvar $v_bits bits
    set bits [expr {int($bits) & int(~ $mask)}]
    return $bits
}
proc twapi::assignbits {v_bits value {mask -1}} {
    upvar $v_bits bits
    set bits [expr {(int($bits) & int(~ $mask)) | (int($value) & int($mask))}]
    return $bits
}

#
# Return a bitmask corresponding to a list of symbolic and integer values
# If symvals is a single item, it is an array else a list of sym bitmask pairs
proc twapi::_parse_symbolic_bitmask {syms symvals} {
    if {[llength $symvals] == 1} {
        upvar $symvals lookup
    } else {
        array set lookup $symvals
    }
    set bits 0
    foreach sym $syms {
        if {[info exists lookup($sym)]} {
            set bits [expr {$bits | $lookup($sym)}]
        } else {
            set bits [expr {$bits | $sym}]
        }
    }
    return $bits
}

#
# Return a list of symbols corresponding to a bitmask
proc twapi::_make_symbolic_bitmask {bits symvals} {
    if {[llength $symvals] == 1} {
        upvar $symvals lookup
        set map [array get lookup]
    } else {
        set map $symvals
    }
    set symbits 0
    set symmask [list ]
    foreach {sym val} $map {
        if {$bits & $val} {
            set symbits [expr {$symbits | $val}]
            lappend symmask $sym
        }
    }

    # Get rid of bits that mapped to symbols
    set bits [expr {$bits & ~$symbits}]
    # If any left over, add them
    # TBD - should we list individual bits?
    if {$bits} {
        lappend symmask $bits
    }
    return $symmask
}

#
# Return a bitmask corresponding to a list of symbolic and integer values
# If symvals is a single item, it is an array else a list of sym bitmask pairs
# Ditto for switches - an array or flat list of switch boolean pairs
proc twapi::_switches_to_bitmask {switches symvals {bits 0}} {
    if {[llength $symvals] == 1} {
        upvar $symvals lookup
    } else {
        array set lookup $symvals
    }
    if {[llength $switches] == 1} {
        upvar $switches swtable
    } else {
        array set swtable $switches
    }

    foreach {switch bool} [array get swtable] {
        if {$bool} {
            set bits [expr {$bits | $lookup($switch)}]
        } else {
            set bits [expr {$bits & ~ $lookup($switch)}]
        }
    }
    return $bits
}

#
# Return a list of switche bool pairs corresponding to a bitmask
proc twapi::_bitmask_to_switches {bits symvals} {
    if {[llength $symvals] == 1} {
        upvar $symvals lookup
        set map [array get lookup]
    } else {
        set map $symvals
    }
    set symbits 0
    set symmask [list ]
    foreach {sym val} $map {
        if {$bits & $val} {
            set symbits [expr {$symbits | $val}]
            lappend symmask $sym 1
        } else {
            lappend symmask $sym 0
        }
    }

    return $symmask
}

# Make and return a keyed list
proc twapi::kl_create {args} {
    if {[llength $args] & 1} {
        error "No value specified for keyed list field [lindex $args end]. A keyed list must have an even number of elements."
    }
    return $args
}

# Return a field from a keyed list or a default if not present
# This routine is now obsolete since the C version of kl_get takes
# an optional default parameter
# kl_get_default KEYEDLIST KEY DEFAULT
interp alias {} ::twapi::kl_get_default {} ::twapi::kl_get

# Set a key value
proc twapi::kl_set {kl field newval} {
   set i 0
   foreach {fld val} $kl {
        if {[string equal $fld $field]} {
            incr i
            return [lreplace $kl $i $i $newval]
        }
        incr i 2
    }
    lappend kl $field $newval
    return $kl
}

# Check if a field exists in the keyed list
proc twapi::kl_vget {kl field varname} {
    upvar $varname var
    return [expr {! [catch {set var [kl_get $kl $field]}]}]
}

# Remote/unset a key value
proc twapi::kl_unset {kl field} {
    array set arr $kl
    unset -nocomplain arr($field)
    return [array get arr]
}

# Compare two keyed lists
proc twapi::kl_equal {kl_a kl_b} {
    array set a $kl_a
    foreach {kb valb} $kl_b {
        if {[info exists a($kb)] && ($a($kb) == $valb)} {
            unset a($kb)
        } else {
            return 0
        }
    }
    if {[array size a]} {
        return 0
    } else {
        return 1
    }
}

# Return the field names in a keyed list
proc twapi::kl_fields {kl} {
    set fields [list ]
    foreach {fld val} $kl {
        lappend fields $fld
    }
    return $fld
}


# Print the specified fields of a keyed list
proc twapi::_kl_print {kl args} {
    # If only one arg, just print value without label
    if {[llength $args] == 1} {
        puts [kl_get $kl [lindex $args 0]]
        return
    }
    if {[llength $args] == 0} {
        set args [kl_fields $kl]
    }
    foreach field $args {
        puts "$field: [kl_get $kl $field]"
    }
    return
}


#
# Return an array as a list of -index value pairs
proc twapi::get_array_as_options {v_arr} {
    upvar $v_arr arr
    set result [list ]
    foreach {index value} [array get arr] {
        lappend result -$index $value
    }
    return $result
}

# Return 1 if $p is a SWIG pointer or handle
# TBD - need more robust way
proc twapi::_is_swig_ptr {p} {
    return [regexp {^_[[:xdigit:]]{8}_p_} $p]
}

#
# Parse a list of two integers or a x,y pair and return a list of two integers
# Generate exception on format error using msg
proc twapi::_parse_integer_pair {pair {msg "Invalid integer pair"}} {
    if {[llength $pair] == 2} {
        foreach {first second} $pair break
        if {[string is integer -strict $first] &&
            [string is integer -strict $second]} {
            return [list $first $second]
        }
    } elseif {[regexp {^([[:digit:]]+),([[:digit:]]+)$} $pair dummy first second]} {
        return [list $first $second]
    }

    error "$msg: '$pair'. Should be a list of two integers or in the form 'x,y'"
}


#
# Map console color name to integer attribute
proc twapi::_map_console_color {colors background} {
    set attr 0
    foreach color $colors {
        switch -exact -- $color {
            blue   {setbits attr 1}
            green  {setbits attr 2}
            red    {setbits attr 4}
            white  {setbits attr 7}
            bright {setbits attr 8}
            black  { }
            default {error "Unknown color name $color"}
        }
    }
    if {$background} {
        set attr [expr {$attr << 4}]
    }
    return $attr
}


# Convert file names by substituting \SystemRoot and \??\ sequences
proc twapi::_normalize_path {path} {
    global env
    
    # Get rid of \??\ prefixes
    regsub {^[\\/]\?\?[\\/](.*)} $path {\1} path

    # Replace leading \SystemRoot with real system root
    catch {set systemroot $env(WINDIR)}
    catch {set systemroot $env(SYSTEMROOT)}
    regsub -nocase {^[\\/]systemroot([\\/].*)} $path "${systemroot}\\1" path

    # If not a full path, make it a full path - TBD
    # should we return [file normalize $path]

    return $path
}

# Convert a LARGE_INTEGER time value (100ns since 1601) to a formatted date
# time
interp alias {} twapi::large_system_time_to_secs {} twapi::large_system_time_to_secs_since_1970
proc twapi::large_system_time_to_secs_since_1970 {ns100 {fraction false}} {
    # No. 100ns units between 1601 to 1970 = 116444736000000000
    set ns100_since_1970 [expr {wide($ns100)-wide(116444736000000000)}]

    if {0} {
        set secs_since_1970 [expr {wide($ns100_since_1970)/wide(10000000)}]
        if {$fraction} {
            append secs_since_1970 .[expr {wide($ns100_since_1970)%wide(10000000)}]
        }
    } else {
        # Equivalent to above but faster
        if {[string length $ns100_since_1970] > 7} {
            set secs_since_1970 [string range $ns100_since_1970 0 end-7]
            if {$fraction} {
                set frac [string range $ns100_since_1970 end-6 end]
                append secs_since_1970 .$frac
            }
        } else {
            set secs_since_1970 0
            if {$fraction} {
                set frac [string range "0000000${ns100_since_1970}" end-6 end]
                append secs_since_1970 .$frac
            }
        }
    }
    return $secs_since_1970
}

proc twapi::secs_since_1970_to_large_system_time {secs} {
    # No. 100ns units between 1601 to 1970 = 116444736000000000
    set ns100 "${secs}0000000"
    return [expr {$ns100 + wide(116444736000000000)}]
}

interp alias {} ::twapi::get_system_time {} ::twapi::GetSystemTimeAsFileTime

#
# Convert seconds to a list {Year Month Day Hour Min Sec Ms}
# (Ms will always be zero). Always return local time 
proc twapi::_seconds_to_timelist {secs} {
    # For each field, we need to trim the leading zeroes
    set result [list ]
    foreach x [clock format $secs -format "%Y %m %e %k %M %S 0" -gmt false] {
        lappend result [scan $x %d]
    }
    return $result
}

#
# Convert local time list {Year Month Day Hour Min Sec Ms} to seconds
# (Ms field is ignored)
proc twapi::_timelist_to_seconds {timelist} {
    return [clock scan [_timelist_to_timestring $timelist] -gmt false]
}

#
# Convert local time list {Year Month Day Hour Min Sec Ms} to a time string
# (Ms field is ignored)
proc twapi::_timelist_to_timestring {timelist} {
    if {[llength $timelist] < 6} {
        error "Invalid time list format"
    }

    return "[lindex $timelist 0]-[lindex $timelist 1]-[lindex $timelist 2] [lindex $timelist 3]:[lindex $timelist 4]:[lindex $timelist 5]"
}

# Convert a time string to a time list
proc twapi::_timestring_to_timelist {timestring} {
    return [_seconds_to_timelist [clock scan $timestring -gmt false]]
}



#
# TBD - debug_puts
proc twapi::debug_puts {msg} {
    puts $msg
}

foreach sfile {
    pdh.tcl
    osinfo.tcl
    process.tcl
    disk.tcl
    ui.tcl
    services.tcl
    security.tcl
    share.tcl
    eventlog.tcl
    network.tcl
    clipboard.tcl
    console.tcl
    synch.tcl
    shell.tcl
    desktop.tcl
    nls.tcl
    printer.tcl
    com.tcl
    mstask.tcl
} {
    source [file join [file dirname [info script]] $sfile]
}

namespace eval twapi {
    # Get a handle to ourselves. This handle never need be closed
    variable my_process_handle [GetCurrentProcess]


    # Figure out what to export
    foreach twapi_proc [info commands] {
        if {![regexp {^[_A-Z]} $twapi_proc]} {
            lappend public_procs $twapi_proc
        }
    }

    foreach twapi_alias [interp aliases] {
        if {[string match "twapi::*" $twapi_alias]} {
            lappend public_procs [string range $twapi_alias 7 end]
        }
    }

    eval namespace export $public_procs
}

proc twapi::_import {} {
    uplevel namespace import twapi::*
}

package provide twapi $twapi::version

if {[llength [info commands tkcon*]]} {
    twapi::_import
}
Added Binaries/Windows/twapi/ui.tcl.












































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
#
# Copyright (c) 2003, 2004, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

# TBD - define a C function and way to implement window callback so
# that SetWindowLong(GWL_WNDPROC) can be implemente
#


# TBD  - document the following class names
#  SciCalc            CALC.EXE
#  CalWndMain         CALENDAR.EXE
#  Cardfile           CARDFILE.EXE
#  Clipboard          CLIPBOARD.EXE
#  Clock              CLOCK.EXE
#  CtlPanelClass      CONTROL.EXE
#  XLMain             EXCEL.EXE
#  Session            MS-DOS.EXE
#  Notepad            NOTEPAD.EXE
#  pbParent           PBRUSH.EXE
#  Pif                PIFEDIT.EXE
#  PrintManager       PRINTMAN.EXE
#  Progman            PROGMAN.EXE   (Windows Program Manager)
#  Recorder           RECORDER.EXE
#  Reversi            REVERSI.EXE
#  #32770             SETUP.EXE
#  Solitaire          SOL.EXE
#  Terminal           TERMINAL.EXE
#  WFS_Frame          WINFILE.EXE
#  MW_WINHELP         WINHELP.EXE
#  #32770             WINVER.EXE
#  OpusApp            WINWORD.EXE
#  MSWRITE_MENU       WRITE.EXE
#  OMain  Microsoft Access
#  XLMAIN  Microsoft Excel
#  rctrl_renwnd32  Microsoft Outlook
#  PP97FrameClass  Microsoft PowerPoint
#  OpusApp  Microsoft Word


namespace eval twapi {
    variable null_hwin ""
}

# Enumerate toplevel windows
proc twapi::get_toplevel_windows {args} {

    array set opts [parseargs args {
        {pid.arg}
    }]

    set toplevels [twapi::EnumWindows]

    if {![info exists opts(pid)]} {
        return $toplevels
    }

    if {[string is integer $opts(pid)]} {
        set match_pids [list $opts(pid)]
    } else {
        # Treat opts(pid) as the name of the process
        set match_pids [list ]
        foreach pid [get_process_ids] {
            if {[string equal -nocase $opts(pid) [get_process_name $pid]]} {
                lappend match_pids $pid
            }
        }
        if {[llength $match_pids] == 0} {
            # No matching pids, so no matching toplevels
            return [list ]
        }
    }

    # match_pids is the list of pids to match
    set process_toplevels [list ]
    foreach toplevel $toplevels {
        set pid [get_window_process $toplevel]
        if {[lsearch -exact $match_pids $pid] >= 0} {
            lappend process_toplevels $toplevel
        }
    }

    return $process_toplevels
}


#
# Find a window based on given criteria
proc twapi::find_windows {args} {
    # TBD - would incorporating FindWindowEx be faster

    array set opts [parseargs args {
        {ancestor.int 0}
        caption.bool
        child.bool
        class.arg
        {match.arg string {string glob regexp}}
        maximize.bool
        maximizebox.bool
        minimize.bool
        minimizebox.bool
        overlapped.bool
        pids.arg
        popup.bool
        single
        style.arg
        text.arg
        toplevel.bool
        visible.bool
    }]

    if {[info exists opts(style)]
        ||[info exists opts(overlapped)]
        || [info exists opts(popup)]
        || [info exists opts(child)]
        || [info exists opts(minimizebox)]
        || [info exists opts(maximizebox)] 
        || [info exists opts(minimize)]
        || [info exists opts(maximize)] 
        || [info exists opts(visible)] 
        || [info exists opts(caption)] 
    } {
        set need_style 1
    } else {
        set need_style 0
    }

    # Figure out the type of match if -text specified
    if {[info exists opts(text)]} {
        switch -exact -- $opts(match) {
            glob {
                set text_compare [list string match -nocase $opts(text)]
            }
            string {
                set text_compare [list string equal -nocase $opts(text)]
            }
            regexp {
                set text_compare [list regexp -nocase $opts(text)]
            }
            default {
                error "Invalid value '$opts(match)' specified for -match option"
            }
        }
    }

    # If only interested in toplevels, just start from there
    if {[info exists opts(toplevel)]} {
        if {$opts(toplevel)} {
            set candidates [get_toplevel_windows]
            if {$opts(ancestor)} {
                error "Option -ancestor may not be specified together with -toplevel true"
            }
        } else {
            # We do not want windows to be toplevels. Remember list
            # so we can check below.
            set toplevels [get_toplevel_windows]
        }
    }

    if {![info exists candidates]} {
        # -toplevel TRuE not specified. 
        # If ancestor is not specified, we start from the desktop window
        # Note ancestor, if specified, is never included in the search
        if {$opts(ancestor)} {
            set candidates [get_descendent_windows $opts(ancestor)]
        } else {
            set desktop [get_desktop_window]
            set candidates [concat [list $desktop] [get_descendent_windows $desktop]]
        }
    }

    # TBD - make use of FindWindowEx function if possible

    set matches [list ]
    foreach win $candidates {

        set status [catch {
            if {[info exists toplevels]} {
                # We do NOT want toplevels
                if {[lsearch -exact -integer $toplevels $win] >= 0} {
                    # This is toplevel, which we don't want
                    continue
                }
            }

            # TBD - what is the right order to check from a performance
            # point of view

            if {$need_style} {
                set win_styles [get_window_style $win]
                set win_style [lindex $win_styles 0]
                set win_exstyle [lindex $win_styles 1]
                set win_styles [lrange $win_styles 2 end]
            }

            if {[info exists opts(style)] && [llength $opts(style)]} {
                foreach {style exstyle} $opts(style) break
                if {[string length $style] && ($style != $win_style)} continue
                if {[string length $exstyle] && ($exstyle != $win_exstyle)} continue
            }

            set match 1
            foreach opt {visible overlapped popup child minimizebox
                maximizebox minimize maximize caption
            } {
                if {[info exists opts($opt)]} {
                    if {(! $opts($opt)) == ([lsearch -exact $win_styles $opt] >= 0)} {
                        set match 0
                        break
                    }
                }
            }
            if {! $match} continue

            # TBD - should we use get_window_class or get_window_real_class
            if {[info exists opts(class)] &&
                [string compare -nocase $opts(class) [get_window_class $win]]} {
                continue
            }

            if {[info exists opts(pids)]} {
                set pid [get_window_process $win]
                if {[lsearch -exact -integer $opts(pids) $pid] < 0} continue
            }

            if {[info exists opts(text)]} {
                set text [get_window_text $win]
                if {![eval $text_compare [list [get_window_text $win]]]} continue
            }
            # Matches all criteria. If we only want one, return it, else
            # add to match list
            if {$opts(single)} {
                return [list $win]
            }
            lappend matches $win
        } result ]

        switch -exact -- $status {
            0 {
                # No error, just keep going
            }
            1 {
                # Error, see if error code is no window and if so, ignore
                foreach {subsystem code msg} $::errorCode { break }
                if {$subsystem == "TWAPI_WIN32" && $code == 2} {
                    # Window has disappeared so just do not include it
                } else {
                    error $result $::errorInfo $::errorCode
                }
            }
            2 {
                return $result;         # Block executed a return
            }
            3 {
                break;                  # Block executed a break
            }
            4 {
                continue;               # Block executed a continue
            }
        }
    }        

    return $matches
    
}


# Return all descendent windows
proc twapi::get_descendent_windows {parent_hwin} {
    return [EnumChildWindows $parent_hwin]
}

#
# Return the parent window
proc twapi::get_parent_window {hwin} {
    # Note - we use GetAncestor and not GetParent because the latter
    # will return the owner in the case of a toplevel window
    return [_return_window [GetAncestor $hwin $twapi::windefs(GA_PARENT)]]
}

#
# Return owner window
proc twapi::get_owner_window {hwin} {
    return [_return_window [twapi::GetWindow $hwin \
                                $twapi::windefs(GW_OWNER)]]
}

#
# Return immediate children of a window (not all children)
proc twapi::get_child_windows {hwin} {
    set children [list ]
    # TBD - maybe get_first_child/get_next_child would be more efficient
    foreach w [get_descendent_windows $hwin] {
        if {[_same_window $hwin [get_parent_window $w]]} {
            lappend children $w
        }
    }
    return $children
}

#
# Return first child in z-order
proc twapi::get_first_child {hwin} {
    return [_return_window [twapi::GetWindow $hwin \
                                $twapi::windefs(GW_CHILD)]]
}


#
# Return the next sibling window in z-order
proc twapi::get_next_sibling_window {hwin} {
    return [_return_window [twapi::GetWindow $hwin \
                                $twapi::windefs(GW_HWNDNEXT)]]
}

#
# Return the previous sibling window in z-order
proc twapi::get_prev_sibling_window {hwin} {
    return [_return_window [twapi::GetWindow $hwin \
                                $twapi::windefs(GW_HWNDPREV)]]
}

#
# Return the sibling window that is highest in z-order
proc twapi::get_first_sibling_window {hwin} {
    return [_return_window [twapi::GetWindow $hwin \
                                $twapi::windefs(GW_HWNDFIRST)]]
}

#
# Return the sibling window that is lowest in z-order
proc twapi::get_last_sibling_window {hwin} {
    return [_return_window [twapi::GetWindow $hwin \
                                $twapi::windefs(GW_HWNDLAST)]]
}

#
# Return the desktop window
proc twapi::get_desktop_window {} {
    return [_return_window [twapi::GetDesktopWindow]]
}

#
# Return the shell window
proc twapi::get_shell_window {} {
    return [_return_window [twapi::GetShellWindow]]
}

# Return the pid for a window
proc twapi::get_window_process {hwin} {
    return [lindex [GetWindowThreadProcessId $hwin] 1]
}

# Return the thread for a window
proc twapi::get_window_thread {hwin} {
    return [lindex [GetWindowThreadProcessId $hwin] 0]
}

# Return the style of the window. Returns a list of two integers
# the first contains the style bits, the second the extended style bits
proc twapi::get_window_style {hwin} {
    set style   [GetWindowLong $hwin $twapi::windefs(GWL_STYLE)]
    set exstyle [GetWindowLong $hwin $twapi::windefs(GWL_EXSTYLE)]
    return [concat [list $style $exstyle] [_style_mask_to_symbols $style $exstyle]]
}


# Set the style of the window. Returns a list of two integers
# the first contains the original style bits, the second the 
# original extended style bits
proc twapi::set_window_style {hwin style exstyle} {
    set style [SetWindowLong $hwin $twapi::windefs(GWL_STYLE) $style]
    set exstyle [SetWindowLong $hwin $twapi::windefs(GWL_EXSTYLE) $exstyle]

    redraw_window_frame $hwin
    return
}


# Return the class of the window
proc twapi::get_window_class {hwin} {
    return [_return_window [GetClassName $hwin]]
}

# Return the real class of the window
proc twapi::get_window_real_class {hwin} {
    return [_return_window [RealGetWindowClass $hwin]]
}

# Return the long value at the given index
# This is a raw function, and should generally be used only to get
# non-system defined indices
proc twapi::get_window_long {hwin index} {
    return [GetWindowLong $hwin $index]
}


# Set the long value at the given index and return the previous value
# This is a raw function, and should generally be used only to get
# non-system defined indices
proc twapi::set_window_long {hwin index val} {
    set oldval [SetWindowLong $hwin $index $val]
}

#
# Return the identifier corrpsonding to the application instance
proc twapi::get_window_application {hwin} {
    return [format "0x%x" [GetWindowLong $hwin $twapi::windefs(GWL_HINSTANCE)]]
}

#
# Return the window id (this is different from the handle!)
proc twapi::get_window_id {hwin} {
    return [format "0x%x" [GetWindowLong $hwin $twapi::windefs(GWL_ID)]]
}

#
# Return the user data associated with a window
proc twapi::get_window_userdata {hwin} {
    return [GetWindowLong $hwin $twapi::windefs(GWL_USERDATA)]
}


#
# Set the user data associated with a window. Returns the previous value
proc twapi::set_window_userdata {hwin val} {
    return [SetWindowLong $hwin $twapi::windefs(GWL_USERDATA) $val]
}


#
# Get the foreground window
proc twapi::get_foreground_window {} {
    return [_return_window [GetForegroundWindow]]
}

#
# Set the foreground window - returns 1/0 on success/fail
proc twapi::set_foreground_window {hwin} {
    return [SetForegroundWindow $hwin]
}


#
# Activate a window - this is only brought the foreground if its application
# is in the foreground
proc twapi::set_active_window_for_thread {hwin} {
    return [_return_window [_attach_hwin_and_eval $hwin {SetActiveWindow $hwin}]]
}

#
# Get active window for an application
proc twapi::get_active_window_for_thread {tid} {
    return [_return_window [_get_gui_thread_info $tid hwndActive]]
}


#
# Get focus window for an application
proc twapi::get_focus_window_for_thread {tid} {
    return [_get_gui_thread_info $tid hwndFocus]
}

#
# Get active window for current thread
proc twapi::get_active_window_for_current_thread {} {
    return [_return_window [GetActiveWindow]]
}

#
# Update the frame - needs to be called after setting certain style bits
proc twapi::redraw_window_frame {hwin} {
    variable windefs

    set flags [expr {$windefs(SWP_ASYNCWINDOWPOS) | $windefs(SWP_NOACTIVATE) |
                     $windefs(SWP_NOMOVE) | $windefs(SWP_NOSIZE) |
                     $windefs(SWP_NOZORDER) | $windefs(SWP_FRAMECHANGED)}]
    SetWindowPos $hwin 0 0 0 0 0 $flags
}

#
# Redraw the window
proc twapi::redraw_window {hwin {opt ""}} {
    variable windefs

    if {[string length $opt]} {
        if {[string compare $opt "-force"]} {
            error "Invalid option '$opt'"
        }
        invalidate_screen_region -hwin $hwin -rect [list ] -bgerase
    }

    UpdateWindow $hwin
}

#
# Set the window position
proc twapi::move_window {hwin x y args} {
    variable windefs

    array set opts [parseargs args {
        {sync}
    }]

    # Not using MoveWindow because that will require knowing the width
    # and height (or retrieving it)
    set flags [expr {$windefs(SWP_NOACTIVATE) |
                     $windefs(SWP_NOSIZE) | $windefs(SWP_NOZORDER)}]
    if {! $opts(sync)} {
        setbits flags $windefs(SWP_ASYNCWINDOWPOS)
    }
    SetWindowPos $hwin 0 $x $y 0 0 $flags
}

#
# Resize window
proc twapi::resize_window {hwin w h args} {
    variable windefs

    array set opts [parseargs args {
        {sync}
    }]
    

    # Not using MoveWindow because that will require knowing the x and y pos
    # (or retrieving them)
    set flags [expr {$windefs(SWP_NOACTIVATE) |
                     $windefs(SWP_NOMOVE) | $windefs(SWP_NOZORDER)}]
    if {! $opts(sync)} {
        setbits flags $windefs(SWP_ASYNCWINDOWPOS)
    }
    SetWindowPos $hwin 0 0 0 $w $h $flags
}

#
# Sets the window's z-order position
# pos is either window handle or a symbol
proc twapi::set_window_zorder {hwin pos} {
    variable windefs

    switch -exact -- $pos {
        top       { set pos $windefs(HWND_TOP) }
        bottom    { set pos $windefs(HWND_BOTTOM) }
        toplayer   { set pos $windefs(HWND_TOPMOST) }
        bottomlayer { set pos $windefs(HWND_NOTOPMOST) }
    }
    
    set flags [expr {$windefs(SWP_ASYNCWINDOWPOS) | $windefs(SWP_NOACTIVATE) |
                     $windefs(SWP_NOSIZE) | $windefs(SWP_NOMOVE)}]
    SetWindowPos $hwin $pos 0 0 0 0 $flags
}


#
# Show the given window. Returns 1 if window was previously visible, else 0
proc twapi::show_window {hwin args} {
    array set opts [parseargs args {sync activate normal startup}]

    set show 0
    if {$opts(startup)} {
        set show $twapi::windefs(SW_SHOWDEFAULT)
    } else {
        if {$opts(activate)} {
            if {$opts(normal)} {
                set show $twapi::windefs(SW_SHOWNORMAL)
            } else {
                set show $twapi::windefs(SW_SHOW)
            }
        } else {
            if {$opts(normal)} {
                set show $twapi::windefs(SW_SHOWNOACTIVATE)
            } else {
                set show $twapi::windefs(SW_SHOWNA)
            }
        }
    }

    _show_window $hwin $show $opts(sync)
}

#
# Hide the given window. Returns 1 if window was previously visible, else 0
proc twapi::hide_window {hwin args} {
    array set opts [parseargs args {sync}]
    _show_window $hwin $twapi::windefs(SW_HIDE) $opts(sync)
}

#
# Restore the given window. Returns 1 if window was previously visible, else 0
proc twapi::restore_window {hwin args} {
    array set opts [parseargs args {sync activate}]
    if {$opts(activate)} {
        _show_window $hwin $twapi::windefs(SW_RESTORE) $opts(sync)
    } else {
        OpenIcon $hwin
    }
}

#
# Maximize the given window. Returns 1 if window was previously visible, else 0
proc twapi::maximize_window {hwin args} {
    array set opts [parseargs args {sync}]
    _show_window $hwin $twapi::windefs(SW_SHOWMAXIMIZED) $opts(sync)
}


#
# Minimize the given window. Returns 1 if window was previously visible, else 0
proc twapi::minimize_window {hwin args} {
    array set opts [parseargs args {sync activate shownext}]

    # TBD - when should we use SW_FORCEMINIMIZE ?
    # TBD - do we need to attach to the window's thread?
    # TBD - when should we use CloseWindow instead?

    if $opts(activate) {
        set show $twapi::windefs(SW_SHOWMINIMIZED)
    } else {
        if {$opts(shownext)} {
            set show $twapi::windefs(SW_MINIMIZE)
        } else {
            set show $twapi::windefs(SW_SHOWMINNOACTIVE)
        }
    }

    _show_window $hwin $show $opts(sync)
}


#
# Hides popup windows
proc twapi::hide_owned_popups {hwin} {
    ShowOwnedPopups $hwin 0
}

#
# Show hidden popup windows
proc twapi::show_owned_popups {hwin} {
    ShowOwnedPopups $hwin 1
}

#
# Enable window input
proc twapi::enable_window_input {hwin} {
    return [expr {[EnableWindow $hwin 1] != 0}]
}

#
# Disable window input
proc twapi::disable_window_input {hwin} {
    return [expr {[EnableWindow $hwin 0] != 0}]
}

#
# Close a window
proc twapi::close_window {hwin args} {
    variable windefs
    array set opts [parseargs args {
        block
        {wait.int 10}
    }]

    if {$opts(block)} {
        set block [expr {$windefs(SMTO_BLOCK) | $windefs(SMTO_ABORTIFHUNG)}]
    } else {
        set block [expr {$windefs(SMTO_NORMAL) | $windefs(SMTO_ABORTIFHUNG)}]
    }

    if {[catch {SendMessageTimeout $hwin $windefs(WM_CLOSE) 0 0 $block $opts(wait)} msg]} {
        # Do no treat timeout as an error
        set erCode $::errorCode
        set erInfo $::errorInfo
        if {[lindex $erCode 0] != "TWAPI_WIN32" ||
            ([lindex $erCode 1] != 0 && [lindex $erCode 1] != 1460)} {
            error $msg $erInfo $erCode
        }
    }
}

#
# CHeck if window is minimized
proc twapi::window_minimized {hwin} {
    return [IsIconic $hwin]
}

#
# CHeck if window is maximized
proc twapi::window_maximized {hwin} {
    return [IsZoomed $hwin]
}

#
# Check if window is visible
proc twapi::window_visible {hwin} {
    return [IsWindowVisible $hwin]
}

#
# Check if a window exists
proc twapi::window_exists {hwin} {
    return [IsWindow $hwin]
}

# CHeck if window input is enabled 
proc twapi::window_unicode_enabled {hwin} {
    return [IsWindowUnicode $hwin]
}

#
# CHeck if window input is enabled 
proc twapi::window_input_enabled {hwin} {
    return [IsWindowEnabled $hwin]
}

#
# Check if child is a child of parent
proc twapi::window_is_child {parent child} {
    return [IsChild $parent $child]
}

#
# Set the focus to the given window
proc twapi::set_focus {hwin} {
    return [_return_window [_attach_hwin_and_eval $hwin {SetFocus $hwin}]]
}

#
# Flash the given window
proc twapi::flash_window_caption {hwin args} {
    eval set [parseargs args {toggle}]

    return [FlashWindow $hwin $toggle]
}

#
# Show/hide window caption buttons. hwin must be a toplevel
proc twapi::configure_window_titlebar {hwin args} {
    variable windefs

    # The minmax buttons are 

    array set opts [parseargs args {
        visible.bool
        sysmenu.bool
        minimizebox.bool
        maximizebox.bool
        contexthelp.bool
    } -maxleftover 0]

    # Get the current style setting
    foreach {style exstyle} [get_window_style $hwin] {break}

    # See if each option is specified. Else use current setting
    foreach {opt def} {
        sysmenu WS_SYSMENU
        minimizebox WS_MINIMIZEBOX
        maximizebox WS_MAXIMIZEBOX
        visible  WS_CAPTION
    } {
        if {[info exists opts($opt)]} {
            set $opt [expr {$opts($opt) ? $windefs($def) : 0}]
        } else {
            set $opt [expr {$style & $windefs($def)}]
        }
    }

    # Ditto for extended style and context help
    if {[info exists opts(contexthelp)]} {
        set contexthelp [expr {$opts(contexthelp) ? $windefs(WS_EX_CONTEXTHELP) : 0}]
    } else {
        set contexthelp [expr {$exstyle & $windefs(WS_EX_CONTEXTHELP)}]
    }

    # The min/max/help buttons all depend on sysmenu being set.
    if {($minimizebox || $maximizebox || $contexthelp) && ! $sysmenu} {
        # Don't bother raising error, since the underlying API allows it
        #error "Cannot enable minimize, maximize and context help buttons unless system menu is present"
    }

    set style [expr {($style & ~($windefs(WS_SYSMENU) | $windefs(WS_MINIMIZEBOX) | $windefs(WS_MAXIMIZEBOX) | $windefs(WS_CAPTION))) | ($sysmenu | $minimizebox | $maximizebox | $visible)}]
    set exstyle [expr {($exstyle & ~ $windefs(WS_EX_CONTEXTHELP)) | $contexthelp}]

    #puts "setting window style to $style ([format %x $style]), $exstyle ([format %x $exstyle])"
    set_window_style $hwin $style $exstyle
}

#
# Generate sound for the specified duration
proc twapi::beep {args} {
    array set opts [parseargs args {
        {frequency.int 1000}
        {duration.int 100}
        {type.arg}
    }]

    if {[info exists opts(type)]} {
        switch -exact -- $opts(type) {
            ok           {MessageBeep 0}
            hand         {MessageBeep 0x10}
            question     {MessageBeep 0x20}
            exclaimation {MessageBeep 0x30}
            exclamation {MessageBeep 0x30}
            asterisk     {MessageBeep 0x40}
            default      {error "Unknown sound type '$opts(type)'"}
        }
        return
    }
    Beep $opts(frequency) $opts(duration)
    return
}


# Arrange window icons
proc twapi::arrange_icons {{hwin ""}} {
    if {$hwin == ""} {
        set hwin [get_desktop_window]
    }
    ArrangeIconicWindows $hwin
}

#
# Get the window text/caption
proc twapi::get_window_text {hwin} {
    twapi::GetWindowText $hwin
}

#
# Set the window text/caption
proc twapi::set_window_text {hwin text} {
    twapi::SetWindowText $hwin $text
}

#
# Get size of client area
proc twapi::get_window_client_area_size {hwin} {
    return [lrange [GetClientRect $hwin] 2 3]
}

#
# Get window coordinates
proc twapi::get_window_coordinates {hwin} {
    return [GetWindowRect $hwin]
}

#
# Get the window under the point
proc twapi::get_window_at_location {x y} {
    return [WindowFromPoint [list $x $y]]
}

#
# Marks a screen region as invalid forcing a redraw
proc twapi::invalidate_screen_region {args} {
    array set opts [parseargs args {
        {hwin.int 0}
        rect.arg
        bgerase
    } -nulldefault]

    InvalidateRect $opts(hwin) $opts(rect) $opts(bgerase)
}

#
# Get the caret blink time
proc twapi::get_caret_blink_time {} {
    return [GetCaretBlinkTime]
}

#
# Set the caret blink time
proc twapi::set_caret_blink_time {ms} {
    return [SetCaretBlinkTime $ms]
}

#
# Hide the caret
proc twapi::hide_caret {} {
    HideCaret 0
}

#
# Show the caret
proc twapi::show_caret {} {
    ShowCaret 0
}

#
# Get the caret position
proc twapi::get_caret_location {} {
    return [GetCaretPos]
}

#
# Get the caret position
proc twapi::set_caret_location {point} {
    return [SetCaretPos [lindex $point 0] [lindex $point 1]]
}


#
# Get display size
proc twapi::get_display_size {} {
    return [lrange [get_window_coordinates [get_desktop_window]] 2 3]
}


#
# Get path to the desktop wallpaper
interp alias {} twapi::get_desktop_wallpaper {} twapi::get_system_parameters_info SPI_GETDESKWALLPAPER


#
# Set desktop wallpaper
proc twapi::set_desktop_wallpaper {path args} {
    
    array set opts [parseargs args {
        persist
    }]

    if {$opts(persist)} {
        set flags 3;                    # Notify all windows + persist
    } else {
        set flags 2;                    # Notify all windows
    }

    if {$path == "default"} {
        SystemParametersInfo 0x14 0 NULL 0
        return
    }

    if {$path == "none"} {
        set path ""
    }

    set mem_size [expr {2 * ([string length $path] + 1)}]
    set mem [malloc $mem_size]
    try {
        twapi::Twapi_WriteMemoryUnicode $mem 0 $mem_size $path
        SystemParametersInfo 0x14 0 $mem $flags
    } finally {
        free $mem
    }
}

#
# Get desktop work area
interp alias {} twapi::get_desktop_workarea {} twapi::get_system_parameters_info SPI_GETWORKAREA


#
# Simulate user input
proc twapi::send_input {inputlist} {
    variable windefs

    set inputs [list ]
    foreach input $inputlist {
        if {[string equal [lindex $input 0] "mouse"]} {
            foreach {mouse xpos ypos} $input {break}
            set mouseopts [lrange $input 3 end]
            array unset opts
            array set opts [parseargs mouseopts {
                relative moved
                ldown lup rdown rup mdown mup x1down x1up x2down x2up
                wheel.int
            }]
            set flags 0
            if {! $opts(relative)} {
                set flags $windefs(MOUSEEVENTF_ABSOLUTE)
            }
            
            if {[info exists opts(wheel)]} {
                if {($opts(x1down) || $opts(x1up) || $opts(x2down) || $opts(x2up))} {
                    error "The -wheel input event attribute may not be specified with -x1up, -x1down, -x2up or -x2down events"
                }
                set mousedata $opts(wheel)
                set flags $windefs(MOUSEEVENTF_WHEEL)
            } else {
                if {$opts(x1down) || $opts(x1up)} {
                    if {$opts(x2down) || $opts(x2up)} {
                        error "The -x1down, -x1up mouse input attributes are mutually exclusive with -x2down, -x2up attributes"
                    }
                    set mousedata $windefs(XBUTTON1)
                } else {
                    if {$opts(x2down) || $opts(x2up)} {
                        set mousedata $windefs(XBUTTON2)
                    } else {
                        set mousedata 0
                    }
                }
            }
            foreach {opt flag} {
                moved MOVE
                ldown LEFTDOWN
                lup   LEFTUP
                rdown RIGHTDOWN
                rup   RIGHTUP
                mdown MIDDLEDOWN
                mup   MIDDLEUP
                x1down XDOWN
                x1up   XUP
                x2down XDOWN
                x2up   XUP
            } {
                if {$opts($opt)} {
                    set flags [expr {$flags | $windefs(MOUSEEVENTF_$flag)}]
                }
            }
                
            lappend inputs [list mouse $xpos $ypos $mousedata $flags]

        } else {
            foreach {inputtype vk scan keyopts} $input {break}
            if {[lsearch -exact $keyopts "-extended"] < 0} {
                set extended 0
            } else {
                set extended $windefs(KEYEVENTF_EXTENDEDKEY)
            }
            if {[lsearch -exact $keyopts "-usescan"] < 0} {
                set usescan 0
            } else {
                set usescan $windefs(KEYEVENTF_SCANCODE)
            }
            switch -exact -- $inputtype {
                keydown {
                    lappend inputs [list key $vk $scan [expr {$extended|$usescan}]]
                }
                keyup {
                    lappend inputs [list key $vk $scan \
                                        [expr {$extended
                                               | $usescan
                                               | $windefs(KEYEVENTF_KEYUP)
                                           }]]
                }
                key {
                    lappend inputs [list key $vk $scan [expr {$extended|$usescan}]]
                    lappend inputs [list key $vk $scan \
                                        [expr {$extended
                                               | $usescan
                                               | $windefs(KEYEVENTF_KEYUP)
                                           }]]
                }
                unicode {
                    lappend inputs [list key 0 $scan $windefs(KEYEVENTF_UNICODE)]
                    lappend inputs [list key 0 $scan \
                                        [expr {$windefs(KEYEVENTF_UNICODE)
                                               | $windefs(KEYEVENTF_KEYUP)
                                           }]]
                }
                default {
                    error "Unknown input type '$inputtype'" 
                }
            }
        }
    }

    SendInput $inputs
}

#
# Block the input
proc twapi::block_input {} {
    return [BlockInput 1]
}

#
# Unblock the input
proc twapi::unblock_input {} {
    return [BlockInput 0]
}

#
# Send the given set of characters to the input queue
proc twapi::send_input_text {s} {
    return [Twapi_SendUnicode $s]
}

#
# send_keys - uses same syntax as VB SendKeys function
proc twapi::send_keys {keys} {
    set inputs [_parse_send_keys $keys]
    send_input $inputs
}


#
# Register a hotkey
proc twapi::register_hotkey {hotkey script} {
    foreach {modifiers vk} [_hotkeysyms_to_vk $hotkey] break

    RegisterHotKey $modifiers $vk $script
}

proc twapi::unregister_hotkey {id} {
    UnregisterHotKey $id
}


#
# Simulate clicking a mouse button
proc twapi::click_mouse_button {button} {
    switch -exact -- $button {
        1 -
        left { set down -ldown ; set up -lup}
        2 -
        right { set down -rdown ; set up -rup}
        3 -
        middle { set down -mdown ; set up -mup}
        x1     { set down -x1down ; set up -x1up}
        x2     { set down -x2down ; set up -x2up}
        default {error "Invalid mouse button '$button' specified"}
    }

    send_input [list \
                    [list mouse 0 0 $down] \
                    [list mouse 0 0 $up]]
    return
}

#
# Simulate mouse movement
proc twapi::move_mouse {xpos ypos {mode ""}} {
    # If mouse trails are enabled, it leaves traces when the mouse is
    # moved and does not clear them until mouse is moved again. So
    # we temporarily disable mouse trails

    if {[min_os_version 5 1]} {
        set trail [get_system_parameters_info SPI_GETMOUSETRAILS]
        set_system_parameters_info SPI_SETMOUSETRAILS 0
    }
    switch -exact -- $mode {
        -relative {
            lappend cmd -relative
            foreach {curx cury} [GetCursorPos] break
            incr xpos $curx
            incr ypos $cury
        }
        -absolute -
        ""        { }
        default   { error "Invalid mouse movement mode '$mode'" }
    }
    
    SetCursorPos $xpos $ypos
        
    # Restore trail setting
    if {[min_os_version 5 1]} {
        set_system_parameters_info SPI_SETMOUSETRAILS $trail
    }
}

#
# Simulate turning of the mouse wheel
proc twapi::turn_mouse_wheel {wheelunits} {
    send_input [list [list mouse 0 0 -relative -wheel $wheelunits]]
    return
}


#
# Get the mouse/cursor position
proc twapi::get_mouse_location {} {
    return [GetCursorPos]
}


################################################################
# Sound functions

#
# Play the specified sound
proc twapi::play_sound {name args} {
    variable windefs

    array set opts [parseargs args {
        alias
        async
        loop
        nodefault
        wait
        nostop
    }]
    
    if {$opts(alias)} {
        set flags $windefs(SND_ALIAS)
    } else {
        set flags $windefs(SND_FILENAME)
    }
    if {$opts(loop)} {
        # Note LOOP requires ASYNC 
        setbits flags [expr {$windefs(SND_LOOP) | $windefs(SND_ASYNC)}]
    } else {
        if {$opts(async)} {
            setbits flags $windefs(SND_ASYNC)
        } else {
            setbits flags $windefs(SND_SYNC)
        }
    }

    if {$opts(nodefault)} {
        setbits flags $windefs(SND_NODEFAULT)
    }    

    if {! $opts(wait)} {
        setbits flags $windefs(SND_NOWAIT)
    }    

    if {$opts(nostop)} {
        setbits flags $windefs(SND_NOSTOP)
    }    

    return [PlaySound $name 0 $flags]
}

#
#
proc twapi::stop_sound {} {
    PlaySound "" 0 $twapi::windefs(SND_PURGE)
}


#
# Get the color depth of the display
proc twapi::get_color_depth {{hwin 0}} {
    set h [GetDC $hwin]
    try {
        return [GetDeviceCaps $h 12]
    } finally {
        ReleaseDC $hwin $h
    }
}


################################################################
# Utility routines

#
# Attaches to the thread queue of the thread owning $hwin and executes
# script in the caller's scope
proc twapi::_attach_hwin_and_eval {hwin script} {
    set me [get_current_thread_id]
    set hwin_tid [get_window_thread $hwin]
    if {$hwin_tid == 0} {
        error "Window $hwin does not exist or could not get its thread owner"
    }

    # Cannot (and no need to) attach to oneself so just exec script directly
    if {$me == $hwin_tid} {
        return [uplevel 1 $script]
    }

    try {
        if {![AttachThreadInput $me $hwin_tid 1]} {
            error "Could not attach to thread input for window $hwin"
        }
        set result [uplevel 1 $script]
    } finally {
        AttachThreadInput $me $hwin_tid 0
    }

    return $result
}

#
# Helper function to wrap GetGUIThreadInfo
# Returns the value of the given fields. If a single field is requested,
# returns it as a scalar else returns a flat list of FIELD VALUE pairs
proc twapi::_get_gui_thread_info {tid args} {
    set gtinfo [GUITHREADINFO]
    try {
        GetGUIThreadInfo $tid $gtinfo
        set result [list ]
        foreach field $args {
            set value [$gtinfo cget -$field]
            switch -exact -- $field {
                cbSize { }
                rcCaret {
                    set value [list [$value cget -left] \
                                   [$value cget -top] \
                                   [$value cget -right] \
                                   [$value cget -bottom]]
                }
                default { set value [format 0x%x $value] }
            }
            lappend result $value
        }
    } finally {
        $gtinfo -delete
    }

    if {[llength $args] == 1} {
        return [lindex $result 0]
    } else {
        return $result
    }
}


#
# if $hwin corresponds to a null window handle, returns an empty string
proc twapi::_return_window {hwin} {
    if {$hwin == 0} {
        return $twapi::null_hwin
    }
    return $hwin
}

#
# Return 1 if same window
proc twapi::_same_window {hwin1 hwin2} {
    # If either is a null handle, no match
    if {[string length $hwin1] == 0 || [string length $hwin2] == 0} {
        return 0
    }
    if {$hwin1 == 0 || $hwin2 == 0} {
        return 0
    }

    # Need integer compare
    return [expr {$hwin1==$hwin2}]
}

#
# Helper function for showing/hiding windows
proc twapi::_show_window {hwin cmd {wait 0}} {
    # If either our thread owns the window or we want to wait for it to
    # process the command, use the synchrnous form of the function
    if {$wait || ([get_window_thread $hwin] == [get_current_thread_id])} {
        ShowWindow $hwin $cmd
    } else {
        ShowWindowAsync $hwin $cmd
    }
}


# Initialize the virtual key table
proc twapi::_init_vk_map {} {
    variable windefs
    variable vk_map

    if {![info exists vk_map]} {
        array set vk_map [list \
                              "+" [list $windefs(VK_SHIFT) 0]\
                              "^" [list $windefs(VK_CONTROL) 0] \
                              "%" [list $windefs(VK_MENU) 0] \
                              "BACK" [list $windefs(VK_BACK) 0] \
                              "BACKSPACE" [list $windefs(VK_BACK) 0] \
                              "BS" [list $windefs(VK_BACK) 0] \
                              "BKSP" [list $windefs(VK_BACK) 0] \
                              "TAB" [list $windefs(VK_TAB) 0] \
                              "CLEAR" [list $windefs(VK_CLEAR) 0] \
                              "RETURN" [list $windefs(VK_RETURN) 0] \
                              "ENTER" [list $windefs(VK_RETURN) 0] \
                              "SHIFT" [list $windefs(VK_SHIFT) 0] \
                              "CONTROL" [list $windefs(VK_CONTROL) 0] \
                              "MENU" [list $windefs(VK_MENU) 0] \
                              "ALT" [list $windefs(VK_MENU) 0] \
                              "PAUSE" [list $windefs(VK_PAUSE) 0] \
                              "BREAK" [list $windefs(VK_PAUSE) 0] \
                              "CAPITAL" [list $windefs(VK_CAPITAL) 0] \
                              "CAPSLOCK" [list $windefs(VK_CAPITAL) 0] \
                              "KANA" [list $windefs(VK_KANA) 0] \
                              "HANGEUL" [list $windefs(VK_HANGEUL) 0] \
                              "HANGUL" [list $windefs(VK_HANGUL) 0] \
                              "JUNJA" [list $windefs(VK_JUNJA) 0] \
                              "FINAL" [list $windefs(VK_FINAL) 0] \
                              "HANJA" [list $windefs(VK_HANJA) 0] \
                              "KANJI" [list $windefs(VK_KANJI) 0] \
                              "ESCAPE" [list $windefs(VK_ESCAPE) 0] \
                              "ESC" [list $windefs(VK_ESCAPE) 0] \
                              "CONVERT" [list $windefs(VK_CONVERT) 0] \
                              "NONCONVERT" [list $windefs(VK_NONCONVERT) 0] \
                              "ACCEPT" [list $windefs(VK_ACCEPT) 0] \
                              "MODECHANGE" [list $windefs(VK_MODECHANGE) 0] \
                              "SPACE" [list $windefs(VK_SPACE) 0] \
                              "PRIOR" [list $windefs(VK_PRIOR) 0] \
                              "PGUP" [list $windefs(VK_PRIOR) 0] \
                              "NEXT" [list $windefs(VK_NEXT) 0] \
                              "PGDN" [list $windefs(VK_NEXT) 0] \
                              "END" [list $windefs(VK_END) 0] \
                              "HOME" [list $windefs(VK_HOME) 0] \
                              "LEFT" [list $windefs(VK_LEFT) 0] \
                              "UP" [list $windefs(VK_UP) 0] \
                              "RIGHT" [list $windefs(VK_RIGHT) 0] \
                              "DOWN" [list $windefs(VK_DOWN) 0] \
                              "SELECT" [list $windefs(VK_SELECT) 0] \
                              "PRINT" [list $windefs(VK_PRINT) 0] \
                              "PRTSC" [list $windefs(VK_SNAPSHOT) 0] \
                              "EXECUTE" [list $windefs(VK_EXECUTE) 0] \
                              "SNAPSHOT" [list $windefs(VK_SNAPSHOT) 0] \
                              "INSERT" [list $windefs(VK_INSERT) 0] \
                              "INS" [list $windefs(VK_INSERT) 0] \
                              "DELETE" [list $windefs(VK_DELETE) 0] \
                              "DEL" [list $windefs(VK_DELETE) 0] \
                              "HELP" [list $windefs(VK_HELP) 0] \
                              "LWIN" [list $windefs(VK_LWIN) 0] \
                              "RWIN" [list $windefs(VK_RWIN) 0] \
                              "APPS" [list $windefs(VK_APPS) 0] \
                              "SLEEP" [list $windefs(VK_SLEEP) 0] \
                              "NUMPAD0" [list $windefs(VK_NUMPAD0) 0] \
                              "NUMPAD1" [list $windefs(VK_NUMPAD1) 0] \
                              "NUMPAD2" [list $windefs(VK_NUMPAD2) 0] \
                              "NUMPAD3" [list $windefs(VK_NUMPAD3) 0] \
                              "NUMPAD4" [list $windefs(VK_NUMPAD4) 0] \
                              "NUMPAD5" [list $windefs(VK_NUMPAD5) 0] \
                              "NUMPAD6" [list $windefs(VK_NUMPAD6) 0] \
                              "NUMPAD7" [list $windefs(VK_NUMPAD7) 0] \
                              "NUMPAD8" [list $windefs(VK_NUMPAD8) 0] \
                              "NUMPAD9" [list $windefs(VK_NUMPAD9) 0] \
                              "MULTIPLY" [list $windefs(VK_MULTIPLY) 0] \
                              "ADD" [list $windefs(VK_ADD) 0] \
                              "SEPARATOR" [list $windefs(VK_SEPARATOR) 0] \
                              "SUBTRACT" [list $windefs(VK_SUBTRACT) 0] \
                              "DECIMAL" [list $windefs(VK_DECIMAL) 0] \
                              "DIVIDE" [list $windefs(VK_DIVIDE) 0] \
                              "F1" [list $windefs(VK_F1) 0] \
                              "F2" [list $windefs(VK_F2) 0] \
                              "F3" [list $windefs(VK_F3) 0] \
                              "F4" [list $windefs(VK_F4) 0] \
                              "F5" [list $windefs(VK_F5) 0] \
                              "F6" [list $windefs(VK_F6) 0] \
                              "F7" [list $windefs(VK_F7) 0] \
                              "F8" [list $windefs(VK_F8) 0] \
                              "F9" [list $windefs(VK_F9) 0] \
                              "F10" [list $windefs(VK_F10) 0] \
                              "F11" [list $windefs(VK_F11) 0] \
                              "F12" [list $windefs(VK_F12) 0] \
                              "F13" [list $windefs(VK_F13) 0] \
                              "F14" [list $windefs(VK_F14) 0] \
                              "F15" [list $windefs(VK_F15) 0] \
                              "F16" [list $windefs(VK_F16) 0] \
                              "F17" [list $windefs(VK_F17) 0] \
                              "F18" [list $windefs(VK_F18) 0] \
                              "F19" [list $windefs(VK_F19) 0] \
                              "F20" [list $windefs(VK_F20) 0] \
                              "F21" [list $windefs(VK_F21) 0] \
                              "F22" [list $windefs(VK_F22) 0] \
                              "F23" [list $windefs(VK_F23) 0] \
                              "F24" [list $windefs(VK_F24) 0] \
                              "NUMLOCK" [list $windefs(VK_NUMLOCK) 0] \
                              "SCROLL" [list $windefs(VK_SCROLL) 0] \
                              "SCROLLLOCK" [list $windefs(VK_SCROLL) 0] \
                              "LSHIFT" [list $windefs(VK_LSHIFT) 0] \
                              "RSHIFT" [list $windefs(VK_RSHIFT) 0 -extended] \
                              "LCONTROL" [list $windefs(VK_LCONTROL) 0] \
                              "RCONTROL" [list $windefs(VK_RCONTROL) 0 -extended] \
                              "LMENU" [list $windefs(VK_LMENU) 0] \
                              "LALT" [list $windefs(VK_LMENU) 0] \
                              "RMENU" [list $windefs(VK_RMENU) 0 -extended] \
                              "RALT" [list $windefs(VK_RMENU) 0 -extended] \
                              "BROWSER_BACK" [list $windefs(VK_BROWSER_BACK) 0] \
                              "BROWSER_FORWARD" [list $windefs(VK_BROWSER_FORWARD) 0] \
                              "BROWSER_REFRESH" [list $windefs(VK_BROWSER_REFRESH) 0] \
                              "BROWSER_STOP" [list $windefs(VK_BROWSER_STOP) 0] \
                              "BROWSER_SEARCH" [list $windefs(VK_BROWSER_SEARCH) 0] \
                              "BROWSER_FAVORITES" [list $windefs(VK_BROWSER_FAVORITES) 0] \
                              "BROWSER_HOME" [list $windefs(VK_BROWSER_HOME) 0] \
                              "VOLUME_MUTE" [list $windefs(VK_VOLUME_MUTE) 0] \
                              "VOLUME_DOWN" [list $windefs(VK_VOLUME_DOWN) 0] \
                              "VOLUME_UP" [list $windefs(VK_VOLUME_UP) 0] \
                              "MEDIA_NEXT_TRACK" [list $windefs(VK_MEDIA_NEXT_TRACK) 0] \
                              "MEDIA_PREV_TRACK" [list $windefs(VK_MEDIA_PREV_TRACK) 0] \
                              "MEDIA_STOP" [list $windefs(VK_MEDIA_STOP) 0] \
                              "MEDIA_PLAY_PAUSE" [list $windefs(VK_MEDIA_PLAY_PAUSE) 0] \
                              "LAUNCH_MAIL" [list $windefs(VK_LAUNCH_MAIL) 0] \
                              "LAUNCH_MEDIA_SELECT" [list $windefs(VK_LAUNCH_MEDIA_SELECT) 0] \
                              "LAUNCH_APP1" [list $windefs(VK_LAUNCH_APP1) 0] \
                              "LAUNCH_APP2" [list $windefs(VK_LAUNCH_APP2) 0] \
                             ]
    }
    
}


#
# Constructs a list of input events by parsing a string in the format
# used by Visual Basic's SendKeys function
proc twapi::_parse_send_keys {keys {inputs ""}} {
    variable vk_map

    _init_vk_map

    set n [string length $keys]
    set trailer [list ]
    for {set i 0} {$i < $n} {incr i} {
        set key [string index $keys $i]
        switch -exact -- $key {
            "+" -
            "^" -
            "%" {
                lappend inputs [concat keydown $vk_map($key)]
                set trailer [linsert $trailer 0 [concat keyup $vk_map($key)]]
            }
            "~" {
                lappend inputs [concat key $vk_map(RETURN)]
                set inputs [concat $inputs $trailer]
                set trailer [list ]
            }
            "(" {
                # Recurse for paren expression
                set nextparen [string first ")" $keys $i]
                if {$nextparen == -1} {
                    error "Invalid key sequence - unterminated ("
                }
                set inputs [concat $inputs [_parse_send_keys [string range $keys [expr {$i+1}] [expr {$nextparen-1}]]]]
                set inputs [concat $inputs $trailer]
                set trailer [list ]
                set i $nextparen
            }
            "\{" {
                set nextbrace [string first "\}" $keys $i]
                if {$nextbrace == -1} {
                    error "Invalid key sequence - unterminated $key"
                }

                if {$nextbrace == ($i+1)} {
                    # Look for the next brace
                    set nextbrace [string first "\}" $keys $nextbrace]
                    if {$nextbrace == -1} {
                        error "Invalid key sequence - unterminated $key"
                    }
                }

                set key [string range $keys [expr {$i+1}] [expr {$nextbrace-1}]]
                set bracepat [string toupper $key]
                if {[info exists vk_map($bracepat)]} {
                    lappend inputs [concat key $vk_map($bracepat)]
                } else {
                    # May be pattern of the type {C} or {C N} where
                    # C is a single char and N is a count
                    set c [string index $key 0]
                    set count [string trim [string range $key 1 end]]
                    scan $c %c unicode
                    if {[string length $count] == 0} {
                        set count 1
                    } else {
                        # Note if $count is not an integer, an error
                        # will be generated as we want
                        incr count 0
                        if {$count < 0} {
                            error "Negative character count specified in braced key input"
                        }
                    }
                    for {set j 0} {$j < $count} {incr j} {
                        lappend inputs [list unicode 0 $unicode]
                    }
                }
                set inputs [concat $inputs $trailer]
                set trailer [list ]
                set i $nextbrace
            }
            default {
                scan $key %c unicode
                # Alphanumeric keys are treated separately so they will
                # work correctly with control modifiers
                if {$unicode >= 0x61 && $unicode <= 0x7A} {
                    # Lowercase letters
                    lappend inputs [list key [expr {$unicode-32}] 0]
                } elseif {$unicode >= 0x30 && $unicode <= 0x39} {
                    # Digits
                    lappend inputs [list key $unicode 0]
                } else {
                    lappend inputs [list unicode 0 $unicode]
                }
                set inputs [concat $inputs $trailer]
                set trailer [list ]
            }
        }
    }
    return $inputs
}

#
# Map style bits to a style symbol list
proc twapi::_style_mask_to_symbols {style exstyle} {
    variable windefs

    set attrs [list ]
    if {$style & $windefs(WS_POPUP)} {
        lappend attrs popup
        if {$style & $windefs(WS_GROUP)} { lappend attrs group }
        if {$style & $windefs(WS_TABSTOP)} { lappend attrs tabstop }
    } else {
        if {$style & $windefs(WS_CHILD)} {
            lappend attrs child
        } else {
            lappend attrs overlapped
        }
        if {$style & $windefs(WS_MINIMIZEBOX)} { lappend attrs minimizebox }
        if {$style & $windefs(WS_MAXIMIZEBOX)} { lappend attrs maximizebox }
    }
    
    # Note WS_BORDER, WS_DLGFRAME and WS_CAPTION use same bits
    if {$style & $windefs(WS_CAPTION)} {
        lappend attrs caption
    } else {
        if {$style & $windefs(WS_BORDER)} { lappend attrs border }
        if {$style & $windefs(WS_DLGFRAME)} { lappend attrs dlgframe }
    }

    foreach mask {
        WS_MINIMIZE WS_VISIBLE WS_DISABLED WS_CLIPSIBLINGS
        WS_CLIPCHILDREN WS_MAXIMIZE WS_VSCROLL WS_HSCROLL WS_SYSMENU
        WS_THICKFRAME
    } {
        if {$style & $windefs($mask)} {
            lappend attrs [string tolower [string range $mask 3 end]]
        }
    }

    if {$exstyle & $windefs(WS_EX_RIGHT)} {
        lappend attrs right
    } else {
        lappend attrs left
    }
    if {$exstyle & $windefs(WS_EX_RTLREADING)} {
        lappend attrs rtlreading
    } else {
        lappend attrs ltrreading
    }
    if {$exstyle & $windefs(WS_EX_LEFTSCROLLBAR)} {
        lappend attrs leftscrollbar
    } else {
        lappend attrs rightscrollbar
    }

    foreach mask {
        WS_EX_DLGMODALFRAME WS_EX_NOPARENTNOTIFY WS_EX_TOPMOST
        WS_EX_ACCEPTFILES WS_EX_TRANSPARENT WS_EX_MDICHILD WS_EX_TOOLWINDOW
        WS_EX_WINDOWEDGE WS_EX_CLIENTEDGE WS_EX_CONTEXTHELP WS_EX_CONTROLPARENT
        WS_EX_STATICEDGE WS_EX_APPWINDOW
    } {
        if {$exstyle & $windefs($mask)} {
            lappend attrs [string tolower [string range $mask 6 end]]
        }
    }
    
    return $attrs
}


#
# Test proc for displaying all colors for a class
proc twapi::_show_theme_colors {class part {state ""}} {
    set w [toplevel .themetest$class$part$state]

    set h [OpenThemeData [winfo id $w] $class]
    wm title $w "$class Colors"

    label $w.title -text "$class, $part, $state" -bg white
    grid $w.title -

    set part [::twapi::TwapiThemeDefineValue $part]
    set state [::twapi::TwapiThemeDefineValue $state]

    foreach x {BORDERCOLOR FILLCOLOR TEXTCOLOR EDGELIGHTCOLOR EDGESHADOWCOLOR EDGEFILLCOLOR TRANSPARENTCOLOR GRADIENTCOLOR1 GRADIENTCOLOR2 GRADIENTCOLOR3 GRADIENTCOLOR4 GRADIENTCOLOR5 SHADOWCOLOR GLOWCOLOR TEXTBORDERCOLOR TEXTSHADOWCOLOR GLYPHTEXTCOLOR FILLCOLORHINT BORDERCOLORHINT ACCENTCOLORHINT BLENDCOLOR} {
        set prop [::twapi::TwapiThemeDefineValue TMT_$x]
        if {![catch {twapi::GetThemeColor $h $part $state $prop} color]} {
            label $w.l-$x -text $x
            label $w.c-$x -text $color -bg $color
            grid $w.l-$x $w.c-$x
        }
    }
    CloseThemeData $h
}

#
# Test proc for displaying all fonts for a class
proc twapi::_show_theme_fonts {class part {state ""}} {
    set w [toplevel .themetest$class$part$state]

    set h [OpenThemeData [winfo id $w] $class]
    wm title $w "$class fonts"

    label $w.title -text "$class, $part, $state" -bg white
    grid $w.title -

    set part [::twapi::TwapiThemeDefineValue $part]
    set state [::twapi::TwapiThemeDefineValue $state]

    foreach x {GLYPHTYPE FONT} {
        set prop [::twapi::TwapiThemeDefineValue TMT_$x]
        if {![catch {twapi::GetThemeFont $h NULL $part $state $prop} font]} {
            label $w.l-$x -text $x
            label $w.c-$x -text $font
            grid $w.l-$x $w.c-$x
        }
    }
    CloseThemeData $h
}

# TBD - do we document this?
proc twapi::write_bmp_file {filename bmp} {
    # Assumes $bmp is clipboard content in format 8 (CF_DIB)
    
    # First parse the bitmap data to collect header information
    binary scan $bmp "iiissiiiiii" size width height planes bitcount compression sizeimage xpelspermeter ypelspermeter clrused clrimportant

    # We only handle BITMAPINFOHEADER right now (size must be 40)
    if {$size != 40} {
        error "Unsupported bitmap format. Header size=$size"
    }

    # We need to figure out the offset to the actual bitmap data
    # from the start of the file header. For this we need to know the
    # size of the color table which directly follows the BITMAPINFOHEADER
    if {$bitcount == 0} {
        error "Unsupported format: implicit JPEG or PNG"
    } elseif {$bitcount == 1} {
        set color_table_size 2
    } elseif {$bitcount == 4} {
        # TBD - Not sure if this is the size or the max size
        set color_table_size 16
    } elseif {$bitcount == 8} {
        # TBD - Not sure if this is the size or the max size
        set color_table_size 256
    } elseif {$bitcount == 16 || $bitcount == 32} {
        if {$compression == 0} {
            # BI_RGB
            set color_table_size $clrused
        } elseif {$compression == 3} {
            # BI_BITFIELDS
            set color_table_size 3
        } else {
            error "Unsupported compression type '$compression' for bitcount value $bitcount"
        }
    } elseif {$bitcount == 24} {
        set color_table_size $clrused
    } else {
        error "Unsupported value '$bitcount' in bitmap bitcount field"
    }

    set filehdr_size 14;                # sizeof(BITMAPFILEHEADER)
    set bitmap_file_offset [expr {$filehdr_size+$size+($color_table_size*4)}]
    set filehdr [binary format "a2 i x2 x2 i" "BM" [expr {$filehdr_size + [string length $bmp]}] $bitmap_file_offset]

    set fd [open $filename w]
    fconfigure $fd -translation binary

    puts -nonewline $fd $filehdr
    puts -nonewline $fd $bmp

    close $fd
}

#
# utility procedure to map symbolic hotkey to {modifiers virtualkey}
proc twapi::_hotkeysyms_to_vk {hotkey} {
    variable vk_map
    
    _init_vk_map

    set keyseq [split [string tolower $hotkey] -]
    set key [lindex $keyseq end]

    # Convert modifiers to bitmask
    set modifiers 0
    foreach modifier [lrange $keyseq 0 end-1] {
        switch -exact -- [string tolower $modifier] {
            ctrl -
            control {
                setbits modifiers 2
            }

            alt -
            menu {
                setbits modifiers 1
            }

            shift {
                setbits modifiers 4
            }

            win {
                setbits modifiers 8
            }

            default {
                error "Unknown key modifier $modifier"
            }
        }
    }
    # Map the key to a virtual key code
    if {[string length $key] == 1} {
        # Single character
        scan $key %c unicode
        
        # Only allow alphanumeric keys and a few punctuation symbols
        # since keyboard layouts are not standard
        if {$unicode >= 0x61 && $unicode <= 0x7A} {
            # Lowercase letters - change to upper case virtual keys
            set vk [expr {$unicode-32}]
        } elseif {($unicode >= 0x30 && $unicode <= 0x39)
                  || ($unicode >= 0x41 && $unicode <= 0x5A)} {
            # Digits or upper case
            set vk $unicode
        } else {
            error "Only alphanumeric characters may be specified for the key. For non-alphanumeric characters, specify the virtual key code"
        }
    } elseif {[info exists vk_map($key)]} {
        # It is a virtual key name
        set vk [lindex $vk_map($key) 0]
    } elseif {[info exists vk_map([string toupper $key])]} {
        # It is a virtual key name
        set vk [lindex $vk_map([string toupper $key]) 0]
    } elseif {[string is integer $key]} {
        # Actual virtual key specification
        set vk $key
    } else {
        error "Unknown or invalid key specifier '$key'"            
    }

    return [list $modifiers $vk]
}
Added ChangeLog.
































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
2010-10-29  Damon Courtney <damon@installjammer.com>  [c2cf97c]
    *** InstallJammer 1.2.15 RELEASED ***

2010-10-29  Damon Courtney <damon@installjammer.com>  [c2cf97c]
    Correct the location of xdg-utils.

2010-10-28  Damon Courtney <damon@installjammer.com>  [48259ad]
    Update version to 1.2.15 for release.

2010-10-28  Damon Courtney <damon@installjammer.com>  [953ffe7]
    Update docs for release.

2010-10-28  Damon Courtney <damon@installjammer.com>  [deae0ef]
    Fixed a bug where kdesu was not found under KDE4.

2010-10-28  Damon Courtney <damon@installjammer.com>  [ab200b2]
    Konsole no longer supports -T title.  Remove it.

2010-10-11  Damon Courtney <damon@installjammer.com>  [5d15e54]
    Small change for loading the new TWAPI.

2010-10-08  Damon Courtney <damon@installjammer.com>  [8a21075]
    Debugging output in the console is now enabled by default if the
    ShowConsole is true.

2010-10-08  Damon Courtney <damon@installjammer.com>  [8994d36]
    Add some debugging output when storing version files.

2010-10-08  Damon Courtney <damon@installjammer.com>  [11466f6]
    Use the build directory as temp when storing LZMA files.

2010-10-08  Damon Courtney <damon@installjammer.com>  [beeebd0]
    Fixed a bug in building separate archives that would cause a non-numeric
    string error.

2010-10-07  Damon Courtney <damon@installjammer.com>  [b829b72]
    Fixed a bug where non-ASCII strings would not display properly in the
    uninstaller.

2010-08-25  Damon Courtney <damon@installjammer.com>  [64055a4]
    Fix double popup on delete bug.
    
    Fixed a bug where using the Delete button on the keyboard to delete from
    the file group, component or setup type tree would popup two confirmation
    dialogs.

2010-08-25  Damon Courtney <damon@installjammer.com>  [8f47d4f]
    Add Directory Test Condition.
    
    Added a new Directory Test Condition for testing directories.

2010-08-25  Damon Courtney <damon@installjammer.com>  [8b2faa0]
    Try to cleanup a Company dir on uninstall.
    
    Fixed a bug where a Company directory would not get cleaned up during
    uninstallation even if the directory was left empty.

2010-08-24  Damon Courtney <damon@installjammer.com>  [072d9c0]
    Update ReadInstalInfo API to add bits of ReadPreviousInstall.
    
    Modifed the ReadInstallInfo API to be more like the Check for Previous
    Install action.  The API now has a -prefix option and always sets the
    common properties.  See the docs for the new behavior if you're using this
    API.
    
    The Check for Previous Install action no longer caches its information
    with the first run.  This means that subsequent calls to this action will
    rebuild the virtual text variables, but it will not delete variables set
    by previous invocations.
    
    Rewrote the ReadPreviousInstall call to use the new API.  Maintaining the
    PreviousInstallInfo array for people who were previously using this
    internal call.
    
    Rewrote the Get Previous Install Info action to use the API better.

2010-08-24  Damon Courtney <damon@installjammer.com>  [c12869e]
    Added Add to Uninstall property to Create File Link action.
    
    Added a new Add to Uninstall property to the Create File Link action.  The
    default is yes, which is slightly incompatible with the older version
    since the link will now automatically be part of the uninstaller where it
    wasn't before.

2010-08-18  Damon Courtney <damon@installjammer.com>  [5c11991]
    Fixed a bug where a user's umask could mess up file permissions when
    installing files on non-Windows platforms.

2010-08-18  Damon Courtney <damon@installjammer.com>  [086f681]
    Fixed a bug where copy would not work in readonly text widgets.
    
    Made all text widgets respect Control/Command-a as select all text.

2010-08-18  Damon Courtney <damon@installjammer.com>  [da394a2]
    Added a new Stop action to stop movement of the wizard and stop actions
    from executing.
    
    Added a new Skip Pane action to skip the current pane or add some other
    pane to a list of panes to be skipped in the future.
    
    Added a new Stop API call.
    
    Added a new SkipPane API call.

2010-08-18  Damon Courtney <damon@installjammer.com>  [08c50ff]
    If --build-log-file is passed, attempt to make the directory containing
    the log file before starting the build if it doesn't exist.

2010-08-16  Damon Courtney <damon@installjammer.com>  [84d2bf4]
    Update version to 1.2.15b1 for release.

2010-08-16  Damon Courtney <damon@installjammer.com>  [36c3d3b]
    Update docs.

2010-08-16  Damon Courtney <damon@installjammer.com>  [16f52c1]
    Delete some files that are no longer kept in the repo.

2010-07-21  Damon Courtney <damon@installjammer.com>  [4ef9861]
    Remove symbolic color names from the source.  Use hex rgb values instead.

2010-07-19  Damon Courtney <damon@installjammer.com>  [6c278df]
    Fixed a bug that allowed illegal characters in the installer executable
    name.

2010-07-19  Damon Courtney <damon@installjammer.com>  [cf726ba]
    Made the cancel button of the language dialog behave as the X close
    button.

2010-07-19  Damon Courtney <damon@installjammer.com>  [dbf2e5f]
    Removed the hard-coded directory is not empty message.
    
    Moved the message into the English message catalog as
    DirectoryNotEmptyText.

2010-07-19  Damon Courtney <damon@installjammer.com>  [5e5cb5d]
    Made /tmp the default TempRoot instead of /usr/tmp.

2010-07-19  Damon Courtney <damon@installjammer.com>  [6781e01]
    Adding a basic test harness to build regressions on top of.

2010-06-20  Damon Courtney <damon@installjammer.com>  [543a5ed]
    Fixed a hard-coded error title string in the condition failure popups.

2010-05-19  Damon Courtney <damon@installjammer.com>  [365722e]
    Fix a bug where you could not select setup type in the Classic Wizard.

2010-05-16  Damon Courtney <damon@installjammer.com>  [77f3b33]
    Fixed a bug where console fallback mode was failing because of a bind
    error.

2010-05-13  Damon Courtney <damon@installjammer.com>  [12beac7]
    Update the install info before displaying the selected component so that
    components can have virtual text containing space required and actually
    display properly.

2010-05-13  Damon Courtney <damon@installjammer.com>  [cefa2cf]
    Make sure the install information is updated before we redraw the setup
    type description.  This fixes a bug where a setup type description that
    includes space required would not show properly because the space had not
    been updated before the text was changed.

2010-05-13  Damon Courtney <damon@installjammer.com>  [6071cc5]
    Assign widget names to the User Name and Company entries on the User Info
    pane.

2010-03-30  Damon Courtney <damon@installjammer.com>  [1c61eb4]
    Make sure the uninstaller is encoded as UTF-8.

2010-03-13  Damon Courtney <damon@installjammer.com>  [ff7422a]
    Update the README on where to find binaries.

2010-03-13  Damon Courtney <damon@installjammer.com>  [afececb]
    Remove all of the platform binaries from the source repo.

2010-03-13  Damon Courtney <damon@installjammer.com>  [3595fed]
    Delete binaries from the repo.  They will be added in the snapshot.

2010-02-25  Damon Courtney <damon@installjammer.com>  [e6c4532]
    Fixed a bug in the chmod of the installkit on startup that could cause
    errors if the root user owned the installation.

2010-02-25  Damon Courtney <damon@installjammer.com>  [d207a19]
    Fixed a bug in the builder where text would show up blank if the system
    language was not a language supported by InstallJammer.

2010-02-25  Damon Courtney <damon@installjammer.com>  [fc8a7de]
    Added a new DecodeURL API call.
    
    Fixed a bug with file URLs dropped from Nautilus not being decoded, so the
    builder doesn't recognize files with spaces because they show up as %20.

2010-02-25  Damon Courtney <damon@installjammer.com>  [062473b]
    Fixed a bug in launching the file explorer on UNIX with no selected group.
    
    Fixed a bug in dragging and dropping files on UNIX with no selected group.

2010-03-09  Damon Courtney <damon@installjammer.com>  [4668f80]
    Fixed a bug where non-ASCII filenames were not supported in the installer.
    This could produce an incompatibility with anyone using a custom UTF-8
    message catalog.
    
    Fixed a bug in the uninstaller where a permissions error could happen on
    Windows if the installation wasn't cleaned up completely.

2010-03-01  Damon Courtney <damon@installjammer.com>  [42f6963]
    Fixed a bug where the GetSelectedFiles API was appending an extra
    directory tail onto each directory object returned.

2010-03-01  Damon Courtney <damon@installjammer.com>  [89f7017]
    Modifying the title of an object nows sets the alias to that title if the
    alias is currently empty or equal to the current title.

2010-02-28  Damon Courtney <damon@installjammer.com>  [84f4197]
    Added a new Display Name property to file groups.
    
    Added a new GetDisplayText API call.
    
    Updated Populate Components and Populate Setup Types to use the new
    GetDisplayText API.

2010-02-28  Damon Courtney <damon@installjammer.com>  [4a51fa6]
    Cleanup the Grab command to handle destruction of windows and a corrupt
    stack.

2010-02-23  Damon Courtney <damon@installjammer.com>  [f74f78f]
    Fix a bug where the exit dialog on Linux was not modal enough.  The dialog
    will not be completely modal in the sense that people are used to on
    Windows, but the user shouldn't be able to click the X a second time and
    cause an error.

2010-02-01  Damon Courtney <damon@installjammer.com>  [c48cd6b]
    Add Windows7 to the <%WindowsPlatform%> virtual text.

2010-01-31  Damon Courtney <damon@installjammer.com>  [5ac2ce1]
    Added a new executed property to action objects.
    
    Added a new passed property to condition objects.
    
    Added a new getobj proc for use in scripts and finding objects either by
    alias or by name.

2010-01-29  Damon Courtney <damon@installjammer.com>  [f832a39]
    Just add a debug message to Unpack Stored File.

2010-01-28  Damon Courtney <damon@installjammer.com>  [7cc0984]
    Check all the platforms in the disk builder pane so that adding new
    platforms doesn't mysteriously not get built and make the user think they
    need to restart the builder to get their new platform built.

2010-01-20  Damon Courtney <damon@installjammer.com>  [872f4fc]
    Fixed a bug in building archives where it would fail on some platforms.

2010-01-11  Damon Courtney <damon@installjammer.com>  [0fd7748]
    Fixed a bug in Uninstall Selected Files where trying to uninstall a file
    that doesn't exist would cause an error.

2009-12-08  Damon Courtney <damon@installjammer.com>  [7f94627]
    Made the default text widget for all text panes readonly instead of them
    being editable and then turning disabled when they're first updated.
    
    Fixed the movement keys for text widgets in a readonly state so that they
    scroll properly.

2009-12-07  Damon Courtney <damon@installjammer.com>  [03c2dc2]
    Fixed a bug where the Copy Value from the right-click menu would copy a
    blank value and clear the buffer.

2009-12-07  Damon Courtney <damon@installjammer.com>  [2a6ffb3]
    If a Move to Pane action attempts to move to the current pane it's already
    on, the pane will reload and rerun its actions instead of just doing
    nothing.

2009-12-07  Damon Courtney <damon@installjammer.com>  [8da2948]
    Fixed a bug where nested action groups would cause an error when executed.

2009-12-04  Damon Courtney <damon@installjammer.com>  [f115571]
    Fix a bug in the Add Widget action from a previous commit.

2009-12-04  Damon Courtney <damon@installjammer.com>  [91479f2]
    Added a new -separator option to the PropertyFileAPI.  Defaults to =.

2009-12-04  Damon Courtney <damon@installjammer.com>  [b824022]
    Added a "show hidden directories" checkbutton to the choose file dialog on
    platforms that don't use a native dialog.

2009-12-04  Damon Courtney <damon@installjammer.com>  [92fa74f]
    Fixed a bug in uninstall cleanup where a permissions error could occur on
    some systems as the uninstaller exits.

2009-12-04  Damon Courtney <damon@installjammer.com>  [88077f5]
    Hitting space in the component tree during installation will now toggle
    the current component.

2009-12-04  Damon Courtney <damon@installjammer.com>  [59c3636]
    Add a Description field to the Windows shortcut actions.  This sets the
    Comments field and tooltip of the shortcut created on Windows.

2009-12-03  Damon Courtney <damon@installjammer.com>  [1ea37af]
    Changed build and quick build shortcuts.  Control-b is now quick build and
    Control-Shift-b is a full build.  Moved the menu around a bit to reflect
    the changes.

2009-12-03  Damon Courtney <damon@installjammer.com>  [8b3d6ca]
    Fixed a bug in the Add Widget action where browse entry widgets did not
    fire an action when Select was chosen as a validate option.  When Select
    is part of the validate list, the action will now fire after the user has
    chosen the file or directory from the dialog.

2009-12-03  Damon Courtney <damon@installjammer.com>  [8fa8e4c]
    Convert loaded projects by removing the -command option from install
    components as they are loaded.

2009-12-03  Damon Courtney <damon@installjammer.com>  [2a8ee8d]
    Fixed a bug where saved install components would sometimes include a bogus
    -command option.  This option is no longer used and it just serves to add
    garbage to the project file.

2009-12-03  Damon Courtney <damon@installjammer.com>  [d0cb766]
    Fixed a bug where the uninstaller would fail with an error trying to
    delete a directory like a file.  Added safety checks to make sure what we
    are deleting is what it's supposed to be.

2009-12-03  Damon Courtney <damon@installjammer.com>  [cc21e8d]
    Fixed a bug in saving projects with unmatched braces.

2009-12-02  Damon Courtney <damon@installjammer.com>  [ac3f42e]
    Pull the build version from git.

2009-11-01  Damon Courtney <damon@installjammer.com>  [ccca9d1]
    Fixed a couple of uninstall bugs.
    
    Fixed a bug where running an uninstall without calling Uninstall Selected
    Files would cause an error because of missing variables.
    
    Fixed a bug where the uninstall cleanup might error after finish because
    it
    failed to delete a directory.

2009-10-28  Damon Courtney <damon@installjammer.com>  [e9a3beb]
    Fixup file executable permissions.

2009-10-28  Damon Courtney <damon@installjammer.com>  [07f3979]
    Import InstallJammer 1.2 HEAD.

2009-10-28  Damon Courtney <damon@installjammer.com>  [0b84cdb]
    Import InstallJammer 1.2.14.

2009-10-28  Damon Courtney <damon@installjammer.com>  [5f71c3d]
    Import InstallJammer 1.2.13.

2009-10-28  Damon Courtney <damon@installjammer.com>  [6b93fef]
    Initial import of InstallJammer 1.2.12.
Added Images/Classic/SetupClassic13.gif.

cannot compute difference between binary files

Added Images/Classic/Small/Install & Setup Icons.txt.














































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
	     __  ___  ____ _____   ___    ____  _  __
	    /  |/  / / __ \__  /  /   |  /  _/ | |/ /
	   / /|_/ / / / / / / /  / /| |  / /   |   / 
	  / /  / / / /_/ / / /__/ ___ |_/ /   /   |  
	 /_/  /_/  \____/ /____/_/  |_|___/  /_/|_|  

          Infinite Advances | Infinite Innovations   

 		      www.mozaix.com                 


--------------------------------------------------------------------
		 Mozaix Install & Setup Icons 1.0                   
--------------------------------------------------------------------

	The enclosed files are useful replacements for the default 
icons used in common installation and setup programs. While many of
these executables use generic 16 color pallets, Install & Setup 
Icons come in 256 colors and include 32X32 and 16X16 resolutions. 



WWW.MOZAIX.COM   -   GET MORE FREE STUFF FROM MOZAIX... 
--------------------------------------------------------------------
	If you like these icons, you'll love the complete collection 
available at the Mozaix Website. Go to www.mozaix.com and click on 
the free stuff link to get more exciting desktop enhancements.



INSTRUCTIONS FOR SETTING UP ICONS...
--------------------------------------------------------------------
	In order to set up an icon to match a file extension, that 
extension must be listed in the Windows registry. You can browse the
extension list through Explorer:

	Launch Windows Explorer, go to 'VIEW / OPTIONS' and click 
the 'FILE TYPE' tab. Find the file extension you want to change and 
click 'EDIT', then click 'CHANGE ICON', Browse to the Setup & Install
Icons folder and select the new icon. 

	To replace an icon stored in an executable file (.exe, .dll,
 .ocx, etc...) you need resource editing program. Recommend is 
Impact Software's Microangelo available at www.impactsoft.com. If 
you are a developer, consult your compilers feature set for 
instructions on building these icons into your own programs. 



DISPLAYING ICONS IN HIGH COLOR...
--------------------------------------------------------------------
	If you have not already set your computer to display icons 
in high color you may do so by clicking on the "Set Icons to 16 Bit 
High Color.reg" file included in this archive. This will merge 
the key 'Shell Icon Bpp' into the Windows Resistry. You must restart
you computer to active this change. 



ABOUT MOZAIX NEW MEDIA...
--------------------------------------------------------------------
WEB:   		http://www.mozaix.com/
E-MAIL: 	design@mozaix.com

	Mozaix is an internet solutions firm dedicated to State of 
the Art World Wide Web Design and Graphics. We offer advanced 
consulting, development and hosting services at affordable prices. 
If you are interested in our services please let us know.



COPYRIGHT INFORMATION...
--------------------------------------------------------------------
THESE  FILES ARE COPYRIGHT  ©1998-1999  TO  MOZAIX NEW MEDIA. MOZAIX
GRANTS TO YOU A PERSONAL,  NON-TRANSFERABLE  AND NON-EXCLUSIVE RIGHT
TO USE THE FILES  INCLUDED WITHIN THE 'INSTALL & SETUP ICON' PACKAGE
FREE OF CHARGE.  NO  PART  OF  THIS  ARCHIVE MAY BE ALTERED, COPIED,
REPRODUCED OR  OTHERWISE  TRANSMITTED  WITHOUT  THIS  DOCUMENTATION.
MOZAIX IS NOT RESPONSIBLE FOR BROKEN LINKS, TYPOGRAPHICAL  ERRORS OF
MISSING CONTENT  AND RESERVE  THE RIGHT TO  CHANGE  THIS INFORMATION
WITHOUT NOTICE. THE MOZAIX NAME, LOGO AND SLOGAN  ARE  TRADEMARKS OF
MOZAIX NEW MEDIA.  ALL RIGHTS RESERVED. ANY   PRODUCT AND/OR SERVICE
NAMES MENTIONED  ARE  COPYRIGHT TO THEIR RESPECTFUL HOLDERS.        


____________________________________________________________________
6/21/1999                                               mzx-isi1.zip
Added Images/Classic/Small/Setup Blue Screen.gif.

cannot compute difference between binary files

Added Images/License.txt.






































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Wizard Images for Inno Setup
Copyright (C) 1999-2003 Kornél Pál
E-mail: kornelpal@hotmail.com
Hungarian Inno Setup home page: http://kornelpal.aom.hu/innosetup/

This wizard image collection is freeware.

You are allowed to use and redistribute this package under the terms and
conditions of the License of the latest release of Inno Setup with some
restictions.
Available at http://www.jrsoftware.org/files/is/license.txt

You are allowed to distribute only the original package.
If you want to add some wizard image to the collection, please send it me and
I will put it to the collection.

A lot of wizard images was not created by me, but I modified them to have the
right size and to look better.
Some of the wizard images were created by me.
Added Images/Modern/SetupModern01.gif.

cannot compute difference between binary files

Added Images/Modern/Small/SetupModernSmall01.gif.

cannot compute difference between binary files

Added Images/Windows Icons/CD Package.ico.

cannot compute difference between binary files

Added Images/Windows Icons/ISU Uninstall Log.ico.

cannot compute difference between binary files

Added Images/Windows Icons/Install & Setup Icons.txt.














































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
	     __  ___  ____ _____   ___    ____  _  __
	    /  |/  / / __ \__  /  /   |  /  _/ | |/ /
	   / /|_/ / / / / / / /  / /| |  / /   |   / 
	  / /  / / / /_/ / / /__/ ___ |_/ /   /   |  
	 /_/  /_/  \____/ /____/_/  |_|___/  /_/|_|  

          Infinite Advances | Infinite Innovations   

 		      www.mozaix.com                 


--------------------------------------------------------------------
		 Mozaix Install & Setup Icons 1.0                   
--------------------------------------------------------------------

	The enclosed files are useful replacements for the default 
icons used in common installation and setup programs. While many of
these executables use generic 16 color pallets, Install & Setup 
Icons come in 256 colors and include 32X32 and 16X16 resolutions. 



WWW.MOZAIX.COM   -   GET MORE FREE STUFF FROM MOZAIX... 
--------------------------------------------------------------------
	If you like these icons, you'll love the complete collection 
available at the Mozaix Website. Go to www.mozaix.com and click on 
the free stuff link to get more exciting desktop enhancements.



INSTRUCTIONS FOR SETTING UP ICONS...
--------------------------------------------------------------------
	In order to set up an icon to match a file extension, that 
extension must be listed in the Windows registry. You can browse the
extension list through Explorer:

	Launch Windows Explorer, go to 'VIEW / OPTIONS' and click 
the 'FILE TYPE' tab. Find the file extension you want to change and 
click 'EDIT', then click 'CHANGE ICON', Browse to the Setup & Install
Icons folder and select the new icon. 

	To replace an icon stored in an executable file (.exe, .dll,
 .ocx, etc...) you need resource editing program. Recommend is 
Impact Software's Microangelo available at www.impactsoft.com. If 
you are a developer, consult your compilers feature set for 
instructions on building these icons into your own programs. 



DISPLAYING ICONS IN HIGH COLOR...
--------------------------------------------------------------------
	If you have not already set your computer to display icons 
in high color you may do so by clicking on the "Set Icons to 16 Bit 
High Color.reg" file included in this archive. This will merge 
the key 'Shell Icon Bpp' into the Windows Resistry. You must restart
you computer to active this change. 



ABOUT MOZAIX NEW MEDIA...
--------------------------------------------------------------------
WEB:   		http://www.mozaix.com/
E-MAIL: 	design@mozaix.com

	Mozaix is an internet solutions firm dedicated to State of 
the Art World Wide Web Design and Graphics. We offer advanced 
consulting, development and hosting services at affordable prices. 
If you are interested in our services please let us know.



COPYRIGHT INFORMATION...
--------------------------------------------------------------------
THESE  FILES ARE COPYRIGHT  ©1998-1999  TO  MOZAIX NEW MEDIA. MOZAIX
GRANTS TO YOU A PERSONAL,  NON-TRANSFERABLE  AND NON-EXCLUSIVE RIGHT
TO USE THE FILES  INCLUDED WITHIN THE 'INSTALL & SETUP ICON' PACKAGE
FREE OF CHARGE.  NO  PART  OF  THIS  ARCHIVE MAY BE ALTERED, COPIED,
REPRODUCED OR  OTHERWISE  TRANSMITTED  WITHOUT  THIS  DOCUMENTATION.
MOZAIX IS NOT RESPONSIBLE FOR BROKEN LINKS, TYPOGRAPHICAL  ERRORS OF
MISSING CONTENT  AND RESERVE  THE RIGHT TO  CHANGE  THIS INFORMATION
WITHOUT NOTICE. THE MOZAIX NAME, LOGO AND SLOGAN  ARE  TRADEMARKS OF
MOZAIX NEW MEDIA.  ALL RIGHTS RESERVED. ANY   PRODUCT AND/OR SERVICE
NAMES MENTIONED  ARE  COPYRIGHT TO THEIR RESPECTFUL HOLDERS.        


____________________________________________________________________
6/21/1999                                               mzx-isi1.zip
Added Images/Windows Icons/Modern Setup Screen.ico.

cannot compute difference between binary files

Added Images/Windows Icons/Packager For The Web.ico.

cannot compute difference between binary files

Added Images/Windows Icons/SFX Cab.ico.

cannot compute difference between binary files

Added Images/Windows Icons/SFX RAR.ico.

cannot compute difference between binary files

Added Images/Windows Icons/SFX ZIP.ico.

cannot compute difference between binary files

Added Images/Windows Icons/Setup Blue Screen.ico.

cannot compute difference between binary files

Added Images/Windows Icons/Setup Green Screen.ico.

cannot compute difference between binary files

Added Images/Windows Icons/Uninstall Blue Screen.ico.

cannot compute difference between binary files

Added Images/Windows Icons/Uninstall Trash Can.ico.

cannot compute difference between binary files

Added LICENSE.txt.














































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
SPECIAL EXCEPTION FOR INSTALLERS:

The binary installkit and InstallJammer code that is embedded
in each installer is built using code from InstallJammer and contains
code that falls under my copyright.  The terms of the GPL still apply
to the code contained in the installers.

Hereby, Damon Courtney grants you special permission to freely use
and distribute any installer built with InstallJammer (including commercial
ones) without having to make available the source code of InstallJammer
or any code that is contained within your installer.  Any changes made to
the InstallJammer or the installkit source code must still follow the GPL
license.


		    GNU GENERAL PUBLIC LICENSE
		       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

			    NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

		     END OF TERMS AND CONDITIONS
Added README-orig.txt.






















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
~ About:

InstallJammer is a multiplatform GUI installer and builder designed
to be completely cross-platform and function on Windows and most all
version of UNIX with eventual support for Mac OS X.


~ Features:

* A full-featured install builder.
* Installs are packaged in single binary executables for each platform
  making web distribution easy.
* Support for multiple install themes.
* Default install themes that resemble popular, commercial installers.
* A high level of configurability.
* Built-in support for Windows install conventions.
* Automatic creation of an uninstaller.
* Easily extended to new platforms.


~ Installing:

If you downloaded the source from the website as a release or as a snapshot,
you're already done.  InstallJammer only needs to be unpacked, and it's
ready to go.  If you have binaries available for your platform, you can
type: ./installjammer to get going.

If you checked out a copy of the source from the source repository, you have
all of the code to run InstallJammer, but you don't have the binaries for
your platform to be able to actually run anything.  You'll need to download
at least the binaries for the platform you are running on to get going.
You can find them at:

http://downloads.installjammer.com/installkit/1.2/


~ Availability:

Home Page:
http://www.installjammer.com/

Downloads:
http://www.installjammer.com/download/
Added README.md.






































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# What's that

 It's a bit changed [installjammer](https://github.com/damoncourtney/installjammer) project, regretfully not maintained now.

# Changes

 The changes are:

 - changing colors of Themes/Modern_Wizard

 - commenting out *tk_setPalette* line of *gui-unix.tcl*

 These changes make the [installjammer](https://github.com/aplsimple/installjammer) to be more or less usable in the dark themed KDE.

 And even more important is that the resulting installers look fine in the dark themed KDE.

# See also

 The original *README-orig.txt*.
Added ReleaseLog.






















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
1.2.15 (October 29th, 2010)

This release contains minor bug fixes and enhancements.


Minor Bug Fixes
Fixed a bug in building separate archives that would cause a non-numeric string error.
Fixed a bug where non-ASCII strings would not display properly in the uninstaller.
Fixed a bug where using the Delete button on the keyboard to delete from the file group, component or setup type tree would popup two confirmation dialogs.
Fixed a bug where a Company directory would not get cleaned up during uninstallation even if the directory was left empty.
Fixed a bug where a user's umask could mess up file permissions when installing files on non-Windows platforms.
Fixed a bug where copy would not work in readonly text widgets.
Fixed a bug that allowed illegal characters in the installer executable name.
Made /tmp the default TempRoot instead of /usr/tmp.
Fixed a hard-coded error title string in the condition failure popups.
Make sure the install information is updated before we redraw the setup type description.  This fixes a bug where a setup type description that includes space required would not show properly because the space had not been updated before the text was changed.
Fixed a bug in the chmod of the installkit on startup that could cause errors if the root user owned the installation.
Fixed a bug in the builder where text would show up blank if the system language was not a language supported by InstallJammer.
Fixed a bug in launching the file explorer on UNIX with no selected group.
Fixed a bug in dragging and dropping files on UNIX with no selected group.
Fixed a bug where non-ASCII filenames were not supported in the installer.  This could produce an incompatibility with anyone using a custom UTF-8 message catalog.
Fixed a bug in the uninstaller where a permissions error could happen on Windows if the installation wasn't cleaned up completely.
Fixed a bug where the GetSelectedFiles API was appending an extra directory tail onto each directory object returned.
Fix a bug where the exit dialog on Linux was not modal enough.  The dialog will not be completely modal in the sense that people are used to on Windows, but the user shouldn't be able to click the X a second time and cause an error.
Fixed a bug in building archives where it would fail on some platforms.
Fixed the movement keys for text widgets in a readonly state so that they scroll properly.
Fixed a bug where the Copy Value from the right-click menu would copy a blank value and clear the buffer.
Fixed a bug where nested action groups would cause an error when executed.
Fixed a bug in uninstall cleanup where a permissions error could occur on some systems as the uninstaller exits.
Add a Description field to the Windows shortcut actions.  This sets the Comments field and tooltip of the shortcut created on Windows.
Changed build and quick build shortcuts.  Control-b is now quick build and Control-Shift-b is a full build.  Moved the menu around a bit to reflect the changes.
Fixed a bug in the Add Widget action where browse entry widgets did not fire an action when Select was chosen as a validate option.  When Select is part of the validate list, the action will now fire after the user has chosen the file or directory from the dialog.
Fixed a bug where saved install components would sometimes include a bogus -command option.  This option is no longer used and it just serves to add garbage to the project file.
Fixed a bug where the uninstaller would fail with an error trying to delete a directory like a file.  Added safety checks to make sure what we are deleting is what it's supposed to be.
Fixed a bug in saving projects with unmatched braces.
Fixed a bug where running an uninstall without calling Uninstall Selected
Fixed a bug where the uninstall cleanup might error after finish because it

Minor Enhancements
Fixed a bug where kdesu was not found under KDE4.
Debugging output in the console is now enabled by default if the ShowConsole is true.
Added a new Directory Test Condition for testing directories.
Modifed the ReadInstallInfo API to be more like the Check for Previous Install action.  The API now has a -prefix option and always sets the common properties.  See the docs for the new behavior if you're using this API.
The Check for Previous Install action no longer caches its information with the first run.  This means that subsequent calls to this action will rebuild the virtual text variables, but it will not delete variables set by previous invocations.
Added a new Add to Uninstall property to the Create File Link action.  The default is yes, which is slightly incompatible with the older version since the link will now automatically be part of the uninstaller where it wasn't before.
Added a new Stop action to stop movement of the wizard and stop actions from executing.
Added a new Skip Pane action to skip the current pane or add some other pane to a list of panes to be skipped in the future.
Added a new Stop API call.
Added a new SkipPane API call.
Added a new DecodeURL API call.
Fixed a bug with file URLs dropped from Nautilus not being decoded, so the builder doesn't recognize files with spaces because they show up as %20.
Modifying the title of an object nows sets the alias to that title if the alias is currently empty or equal to the current title.
Added a new Display Name property to file groups.
Added a new GetDisplayText API call.
Made the default text widget for all text panes readonly instead of them being editable and then turning disabled when they're first updated.
If a Move to Pane action attempts to move to the current pane it's already on, the pane will reload and rerun its actions instead of just doing nothing.
Added a new -separator option to the PropertyFileAPI.  Defaults to =.
Added a "show hidden directories" checkbutton to the choose file dialog on platforms that don't use a native dialog.
Hitting space in the component tree during installation will now toggle the current component.
Added Themes/Classic_Wizard/Common/CustomBlankPane1.pane.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane CustomBlankPane1 "Custom Blank Pane 1"

Order 100

Property Active boolean "Active" "No"
Property Icon image "Icon" "<%Icon%>"
Property Image image "Image" "<%Image%>"
Property Buttons buttons "Buttons" "Back/Next/Cancel"

Text Title
Text BackButton   "Back Button"   1
Text NextButton   "Next Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Classic_Wizard/Common/CustomBlankPane1.tcl.












































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.CustomBlankPane1 { wizard id } {
    set base [$wizard widget get $id]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 1 -weight 1

    label $base.image -relief sunken -bd 2 -width 0 -height 0
    grid  $base.image -row 0 -column 0 -rowspan 2 -sticky nw -padx 15 -pady 15
    $id widget set Image -widget $base.image -type image

    frame $base.clientArea
    grid  $base.clientArea -row 0 -column 1 -padx [list 0 10] -pady 15 \
        -sticky news
    $id widget set ClientArea -widget $base.clientArea -type frame
}
Added Themes/Classic_Wizard/Common/CustomTextPane1.pane.












































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane CustomTextPane1 "Custom Text Pane 1"

Order 101

Property Active boolean "Active" "No"
Property Icon image "Icon" "<%Icon%>"
Property Image image "Image" "<%Image%>"
Property Buttons buttons "Buttons" "Back/Next/Cancel"

Text Title
Text Caption
Text Message
Text BackButton   "Back Button"   1
Text NextButton   "Next Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Classic_Wizard/Common/CustomTextPane1.tcl.






































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.CustomTextPane1 { wizard id } {
    set base [$wizard widget get $id]

    grid rowconfigure    $base 1 -weight 1
    grid columnconfigure $base 1 -weight 1

    label $base.image -relief sunken -bd 2 -width 0 -height 0
    grid  $base.image -row 0 -column 0 -rowspan 2 -sticky nw -padx 15 -pady 15
    $id widget set Image -widget $base.image -type image

    frame $base.frame
    grid  $base.frame -row 0 -column 1 -padx [list 0 10] -pady 15 -sticky ew

    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 1 -weight 1

    label $base.frame.icon -height 0 -width 0
    grid  $base.frame.icon -row 0 -column 0 -padx [list 0 10] -sticky w
    $id widget set Icon -widget $base.frame.icon -type image

    Label $base.frame.caption -autowrap 1 -anchor nw -justify left
    grid  $base.frame.caption -row 0 -column 1 -sticky new
    $id widget set Caption -widget $base.frame.caption

    Label $base.message -autowrap 1 -anchor nw -justify left
    grid  $base.message -row 1 -column 1 -sticky new -padx [list 0 10] -pady 5
    $id widget set Message -widget $base.message
}
Added Themes/Classic_Wizard/Common/CustomTextPane2.pane.














































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane CustomTextPane2 "Custom Text Pane 2"

Order 102

Include CustomBlankPane1

Property Active boolean "Active" "No"
Property Image image "Image" "<%Image%>"
Property Buttons buttons "Buttons" "Back/Next/Cancel"

Text Title
Text Caption
Text Text         "Text"               0
Text NextButton   "Next Button"        1
Text BackButton   "Back Button"        1
Text CancelButton "Cancel Button"      1
Added Themes/Classic_Wizard/Common/CustomTextPane2.tcl.














































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.CustomTextPane2 { wizard id } {
    CreateWindow.CustomBlankPane1 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 1 -weight 1
    grid columnconfigure $base 0 -weight 1

    Label $base.caption -autowrap 1 -anchor nw -justify left
    grid  $base.caption -row 0 -column 0 -sticky new -pady [list 0 5]
    $id widget set Caption -widget $base.caption

    frame $base.frame
    grid  $base.frame -row 1 -column 0 -sticky news

    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 0 -weight 1

    text $base.frame.text \
        -state disabled -wrap word -highlightthickness 0 \
        -yscrollcommand [list $base.frame.vs set] \
        -xscrollcommand [list $base.frame.hs set]
    grid $base.frame.text -row 0 -column 0 -sticky news
    $id widget set Text -widget $base.frame.text

    ttk::scrollbar $base.frame.vs -command [list $base.frame.text yview]
    grid $base.frame.vs -row 0 -column 1 -sticky ns

    ttk::scrollbar $base.frame.hs -command [list $base.frame.text xview] \
        -orient horizontal
    grid $base.frame.hs -row 1 -column 0 -sticky ew
}
Added Themes/Classic_Wizard/Common/CustomTextPane3.pane.














































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane CustomTextPane3 "Custom Text Pane 3"

Order 103

Property Active boolean "Active" "No"
Property Icon image "Icon" "<%Icon%>"
Property Buttons buttons "Buttons" "Back/Next/Cancel"

Text Title
Text Caption
Text Message
Text Text
Text AcceptCheck  "Accept Checkbox"     0
Text NextButton   "Next Button"         1
Text BackButton   "Back Button"         1
Text CancelButton "Cancel Button"       1
Added Themes/Classic_Wizard/Common/CustomTextPane3.tcl.


















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.CustomTextPane3 { wizard id } {
    set base [$wizard widget get $id]

    grid rowconfigure    $base 1 -weight 1
    grid columnconfigure $base 1 -weight 1

    label $base.icon -height 0 -width 0 
    grid  $base.icon -row 0 -column 0 -pady 10 -padx 10
    $id widget set Icon -widget $base.icon -type image

    Label $base.caption -autowrap 1 -anchor nw -justify left
    grid  $base.caption -row 0 -column 1 -sticky new -pady 10
    $id widget set Caption -widget $base.caption

    frame $base.frame
    grid  $base.frame -row 1 -column 0 -columnspan 2 -sticky news -padx 10

    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 0 -weight 1

    text $base.frame.text \
        -state disabled -wrap word -highlightthickness 0 \
        -yscrollcommand [list $base.frame.vs set]
    grid $base.frame.text -row 0 -column 0 -sticky news
    $id widget set Text -widget $base.frame.text

    ttk::scrollbar $base.frame.vs -command [list $base.frame.text yview]
    grid $base.frame.vs -row 0 -column 1 -sticky ns

    Label $base.message -autowrap 1 -anchor nw -justify left
    grid  $base.message -row 2 -column 0 -columnspan 2 -sticky ew \
        -padx [list 12 10] -pady 5
    $id widget set Message -widget $base.message
}
Added Themes/Classic_Wizard/Common/defaults.tcl.


















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

SafeSet info(Icon)  "Classic/Small/Setup Blue Screen.gif"
SafeSet info(Image) "Classic/SetupClassic13.gif"
Added Themes/Classic_Wizard/Common/setup.tcl.












































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ThemeSetup {} {
    if {$::tcl_platform(platform) ne "windows"} {
        option add *font                TkTextFont
	option add *background          [style default . -background]
	option add *selectForeground    [style default . -selectforeground]
	option add *selectBackground    [style default . -selectbackground]

	option add *Listbox.background  #FFFFFF

	option add *Entry.background    #FFFFFF
	option add *Entry.borderWidth   1

	option add *Text.background     #FFFFFF
    }
}
Added Themes/Classic_Wizard/Common/utils.tcl.












































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc RaiseStep { wizard id } {
    $wizard itemconfigure $id -title [::InstallJammer::GetText $id Title]
}

namespace eval ::Progressbar {
    variable options
    variable initialized 0
}

proc ::Progressbar::Init {} {
    variable initialized
    variable options

    if {$initialized} { return }
    set initialized 1

    option add *Progressbar.borderWidth	1	widgetDefault
    option add *Progressbar.relief	sunken	widgetDefault

    array set options {
	-troughcolor	"#FFFFFF"
	-value  	0
	-text		"0%"
	-foreground	"#000000"
	-showtext	1
	-doneforeground	"#FFFFFF"
	-background	"#1B009C"
	-height		20
	-width		200
    }
}

proc ::Progressbar::New {w args} {
    variable options

    ::Progressbar::Init

    namespace eval ::Progressbar::$w {
	variable w
	variable percent
	variable options
    }

    upvar #0 ::Progressbar::${w}::options widgetOptions

    array set widgetOptions [array get options]

    foreach {opt val} $args {
	switch -- $opt {
	    "-fg"     { set widgetOptions(-foreground) $val }
	    "-bg"     { set widgetOptions(-background) $val }
	    "-donefg" { set widgetOptions(-doneforeground) $val }
	    default   {
		if {[info exists options($opt)]} {
		    set widgetOptions($opt) $val
		}
	    }
	}
    }

    uplevel 1 [list eval frame $w -class Progressbar]

    set varname ::Progressbar::${w}::percent

    frame $w.l \
    	-borderwidth 0 \
    	-background $widgetOptions(-troughcolor)
    label $w.l.l -textvariable $varname -borderwidth 0 \
	    -foreground $widgetOptions(-foreground) \
    	    -background $widgetOptions(-troughcolor)
    $w.l configure -height [expr {int([winfo reqheight $w.l.l]+2)}]
    frame $w.l.fill -background $widgetOptions(-background)
    label $w.l.fill.l -textvariable $varname -borderwidth 0 \
	    -foreground $widgetOptions(-doneforeground) \
    	    -background $widgetOptions(-background)

    bind $w.l <Configure> [namespace code [list ProgressConf $w "%w"]]

    pack  $w.l -fill both -expand 1
    place $w.l.l -relx 0.5 -rely 0.5 -anchor center
    place $w.l.fill -x 0 -y 0 -relheight 1 -relwidth 0
    place $w.l.fill.l -x 0 -rely 0.5 -anchor center

    rename $w ::Progressbar::${w}::w
    interp alias {} ::$w {} ::Progressbar::WidgetProc $w

    $w configure -value 0 -height $widgetOptions(-height) \
    	-width $widgetOptions(-width)

    return $w
}

proc ::Progressbar::ProgressConf {widget width} {
    place configure $widget.l.fill.l -x [expr {int($width/2)}]
}

proc ::Progressbar::WidgetProc {widget cmd args} {
    set w ::Progressbar::${widget}::w
    upvar #0 ::Progressbar::${widget}::options options

    switch -- $cmd {
	"configure" {
	    set realOpts {}
	    foreach {opt val} $args {
		switch -- $opt {
		    "-value" {
			if {$val > 100} { set val 100 }
			set progress [expr {int(100*$val)/int(100)}]
			set relwidth [expr {double($val)/double(100)}]
			place configure $widget.l.fill -relwidth $relwidth
			if {$options(-showtext)} {
			    set [$widget.l.l cget -textvariable] $val%
			}
		    }
		    "-height" {
			$widget.l configure -height $options(-height)
		    }
		    "-width" {
			$widget.l configure -width $options(-width)
		    }
		    "-troughcolor" {
			$widget.l configure -background $val
			$widget.l.l configure -background $val
		    }
		    "-bg" - "-background" {
			$widget.l.fill configure -background $val
			$widget.l.fill.l configure -background $val
		    }
		    "-fg" - "-foreground" {
			$widget.l.l configure -foreground $val
		    }
		    "-donefg" - "-doneforeground" {
			$widget.l.fill.l configure -foreground $val
		    }
		    "-textvariable" {
			$widget.l.l configure -textvariable $val
			$widget.l.fill.l configure -textvariable $val
		    }
		    "-text" {
			set [$widget.l.l cget -textvariable] $val
		    }
		    "-showtext" {
			set options(-showtext) $val
		    }

		    default {
			lappend realOpts $opt $val
		    }
		}
	    }
	    if {[llength $args] > 0 && [llength $realOpts] == 0} { return }
	    eval $w configure $realOpts
	}

	default {
	    eval $w $cmd $args
	}
    }
}
Added Themes/Classic_Wizard/Install/Background.pane.














































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Window Background "Background Window"

InstallTypes Common

Property Active boolean "Active" No
Property Image image "Image"
Property ShowTitleBar yesno "Show Title Bar" Yes
Property HideProgramManager yesno "Hide Program Manager" No
Property TitleFont font "Title Font" "Arial 36 bold"
Property TextColor color "Text Color" "#ffffff"
Property BackgroundGradient1 color "Background Gradient 1" "darkblue"
Property BackgroundGradient2 color "Background Gradient 2" "royalblue"
Property GradientAxis choice "Gradient Axis" "vertical" {vertical horizontal}

Text Text
Text Title
Added Themes/Classic_Wizard/Install/Background.tcl.






























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.Background { wizard id } {
    variable images

    proc ::InstallJammer::DrawGradient { win axis col1Str col2Str } {
        if {[winfo class $win] ne "Canvas"} {
            return -code error "$win must be a canvas widget"
        }

        $win delete gradient

        set width  [winfo reqwidth $win]
        set height [winfo reqheight $win]
        switch -- $axis {
            "x" { set max $width;  set x 1 }
            "y" { set max $height; set x 0 }
            default {
                return -code error "Invalid axis $axis: must be x or y"
            }
        }

        if {[catch {winfo rgb $win $col1Str} color1]} {
            return -code error "Invalid color $col1Str"
        }

        if {[catch {winfo rgb $win $col2Str} color2]} {
            return -code error "Invalid color $col2Str"
        }

        foreach {r1 g1 b1} $color1 break
        foreach {r2 g2 b2} $color2 break
        set rRange [expr $r2.0 - $r1]
        set gRange [expr $g2.0 - $g1]
        set bRange [expr $b2.0 - $b1]

        set rRatio [expr $rRange / $max]
        set gRatio [expr $gRange / $max]
        set bRatio [expr $bRange / $max]

        for {set i 0} {$i < $max} {incr i} {
            set nR [expr int( $r1 + ($rRatio * $i) )]
            set nG [expr int( $g1 + ($gRatio * $i) )]
            set nB [expr int( $b1 + ($bRatio * $i) )]

            set col [format {%4.4x} $nR]
            append col [format {%4.4x} $nG]
            append col [format {%4.4x} $nB]
            if {$x} {
                $win create line $i 0 $i $height -tags gradient -fill #${col}
            } else {
                $win create line 0 $i $width $i -tags gradient -fill #${col}
            }
        }

        $win lower gradient

        return $win
    }

    set base [$id window]

    lassign [wm maxsize .] w h

    $id get ShowTitleBar showTitleBar
    $id get HideProgramManager hideProgramManager

    toplevel     $base
    wm withdraw  $base
    update idletasks
    wm transient $base .
    wm protocol  $base WM_DELETE_WINDOW exit

    if {!$showTitleBar} {
    	wm overrideredirect $base 1

        if {$::tcl_platform(platform) ne "windows"} {
            incr w 15
        }

	incr h 10
    } else {
        if {$::tcl_platform(platform) eq "windows"} {
            incr w -10
        } else {
            incr w 5
            incr h -15
        }

        incr h -20
    }

    if {$hideProgramManager} { incr h 100 }

    wm geometry  $base ${w}x${h}+0+0
    wm resizable $base 0 0

    ::InstallJammer::SetTitle $base $id

    set gradient   0
    set background "#FFFFFF"
    $id get TitleFont font
    $id get TextColor foreground
    $id get BackgroundGradient1 gradient1
    $id get BackgroundGradient2 gradient2
    $id get GradientAxis axis
    $id get Image image

    if {(![lempty $gradient1] && [lempty $gradient2])
    	|| ($gradient1 == $gradient2)} {
	## Background color only.
	set background $gradient1
    } else {
	if {![lempty $gradient1] && ![lempty $gradient2]} { set gradient 1 }
    }

    canvas $base.c -background $background -bd 0 -highlightthickness 0 \
        -width $w -height $h
    pack $base.c -expand 1 -fill both

    if {$gradient} {
	switch -- $axis {
	    "horizontal" { set axis x }
	    default      { set axis y }
	}
	::InstallJammer::DrawGradient $base.c $axis $gradient1 $gradient2
    }

    if {![lempty $image]} {
	$base.c create image 40 10 -anchor nw -image $image
    } else {
	$base.c create text 40 10 -anchor nw \
	    -font $font -fill $foreground \
            -text [::InstallJammer::GetText $id Text]
    }

    wm deiconify $base
}
Added Themes/Classic_Wizard/Install/ChooseComponents.pane.




























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane ChooseComponents "Choose Components"

Order 10

Include CustomBlankPane1

Condition StringEqualCondition \
    String1 "<%InstallType%>" Operation "equals" String2 "Custom"

Property Active boolean "Active" No
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Image image "Image" "<%Image%>"

Action PopulateComponents ExecuteAction "Before Pane is Displayed"

Text Caption
Text Title
Text ComponentLabel     "Component Label"      0
Text DescriptionLabel   "Description Label"    0
Text SpaceRequiredLabel "Space Required Label" 1
Text NextButton         "Next Button"          1
Text BackButton         "Back Button"          1
Text CancelButton       "Cancel Button"        1
Added Themes/Classic_Wizard/Install/ChooseComponents.tcl.










































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.ChooseComponents { wizard id } {
    CreateWindow.CustomBlankPane1 $wizard $id

    set base [$id widget get ClientArea]
    set tree $base.frame.tree

    grid rowconfigure    $base 2 -weight 1
    grid columnconfigure $base 0 -weight 1

    Label $base.caption -autowrap 1 -anchor nw -justify left
    grid  $base.caption -row 0 -column 0 -sticky ew -pady [list 0 5]
    $id widget set Caption -widget $base.caption

    Label $base.label -autowrap 1 -anchor nw -justify left
    grid  $base.label -row 1 -column 0 -sticky ew
    $id widget set ComponentLabel -widget $base.label

    frame $base.frame -bd 2 -relief sunken
    grid  $base.frame -row 2 -column 0 -sticky news

    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 0 -weight 1

    OptionTree $tree -bg #FFFFFF -relief flat -toggleselect 0 \
        -yscrollcommand [list $base.frame.vs set]
    grid $tree -row 0 -column 0 -sticky news
    $id widget set ComponentTree -widget $base.frame.tree -type tree

    ttk::scrollbar $base.frame.vs -command [list $tree yview]
    grid $base.frame.vs -row 0 -column 1 -sticky ns

    labelframe $base.descframe -bd 2 -relief ridge
    grid $base.descframe -row 3 -column 0 -sticky ew -pady 5
    $id widget set DescriptionLabel -widget $base.descframe

    grid rowconfigure    $base.descframe 0 -weight 1
    grid columnconfigure $base.descframe 0 -weight 1

    Label $base.descframe.desc -autowrap 1 -anchor nw -justify left -height 5
    grid  $base.descframe.desc -row 0 -column 0 -sticky news -padx 5 -pady 5
    $id widget set DescriptionText -widget $base.descframe.desc

    label $base.spacereq
    grid  $base.spacereq -row 4 -column 0 -sticky w -padx 5
    $id widget set SpaceRequiredLabel -widget $base.spacereq
}
Added Themes/Classic_Wizard/Install/CopyFiles.pane.






















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Window CopyFiles "Copying Files"

Order 13

InstallTypes Standard Default

Action ExecuteAction Action "Install Actions"
Action MoveForward

Property Anchor anchor "Anchor" "s"
Property Icon image "Icon" "<%Icon%>"
Property AllowUserToCancel boolean "Allow User to Cancel" Yes

Property Grab hidden "Grab Window" No

Text Title
Text Caption
Text Message
Text ProgressValue "Progress Value" 1
Text CancelButton  "Cancel Button"  1
Added Themes/Classic_Wizard/Install/CopyFiles.tcl.
























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.CopyFiles { wizard id } {
    set base [Toplevel $id 347x110]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 1 -weight 1

    $id get AllowUserToCancel allowCancel
    if {$allowCancel} {
	wm protocol $base WM_DELETE_WINDOW exit
    } else {
	wm protocol $base WM_DELETE_WINDOW noop
    }

    label $base.icon
    grid  $base.icon -row 0 -column 0 -rowspan 3 -sticky nw -padx 15 -pady 15
    $id widget set Icon -type image -widget $base.icon

    label $base.caption -anchor w
    grid  $base.caption -row 0 -column 1 -columnspan 2 -sticky nw \
        -padx [list 0 15] -pady 15
    $id widget set Caption -widget $base.caption

    label $base.message -anchor w
    grid  $base.message -row 1 -column 1 -columnspan 2 -sticky nw
    $id widget set Message -widget $base.message

    ::Progressbar::New $base.progress
    grid $base.progress -row 2 -column 1 -sticky ew -pady [list 0 10]
    $id widget set ProgressValue -widget $base.progress -type progress

    if {$allowCancel} {
	ttk::button $base.cancel -text "Cancel" -width 10 \
            -command [list ::InstallJammer::exit 1]
        grid $base.cancel -row 2 -column 2 -padx 5 -pady [list 0 10]
        $id widget set CancelButton -widget $base.cancel
    }
}
Added Themes/Classic_Wizard/Install/License.pane.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane License "License Agreement"

Order 5

Include CustomTextPane3

Property Active boolean "Active" No
Property Icon image "Icon" "<%Icon%>"
Property Buttons buttons "Buttons" "Back/Next/Cancel"

Action ModifyWidget Widget "NextButton" State "disabled" \
    ExecuteAction "Before Pane is Displayed"
Condition StringIsCondition Operator "false" String "<%LicenseAccepted%>"

Text Title
Text Caption
Text Message
Text Text
Text AcceptCheck  "Accept Checkbox"     0
Text NextButton   "Next Button"         1
Text BackButton   "Back Button"         1
Text CancelButton "Cancel Button"       1
Added Themes/Classic_Wizard/Install/License.tcl.














































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.License { wizard id } {
    set base [$wizard widget get $id]

    CreateWindow.CustomTextPane3 $wizard $id

    ttk::checkbutton $base.accept -variable ::info(LicenseAccepted) -command {
        if {$::info(LicenseAccepted)} {
            $::info(Wizard) itemconfigure next -state normal
        } else {
            $::info(Wizard) itemconfigure next -state disabled
        }
    }

    grid $base.accept -columnspan 2 -sticky w -padx 10
    $id widget set AcceptCheck -widget $base.accept
}
Added Themes/Classic_Wizard/Install/Readme.pane.












































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane Readme "Readme Information"

Order 6

Include CustomTextPane2

Property Active boolean "Active" No
Property Image image "Image" "<%Image%>"
Property Buttons buttons "Buttons" "Back/Next/Cancel"

Text Title
Text Text
Text NextButton   "Next Button"        1
Text BackButton   "Back Button"        1
Text CancelButton "Cancel Button"      1
Added Themes/Classic_Wizard/Install/Readme.tcl.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.Readme { wizard id } {
    CreateWindow.CustomTextPane2 $wizard $id

    set base [$id widget get ClientArea]
    grid remove $base.caption
}
Added Themes/Classic_Wizard/Install/SelectDestination.pane.






















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane SelectDestination "Select Destination"

Order 8

Include CustomBlankPane1

Condition FilePermissionCondition Filename {<%InstallDir%>} \
    CheckCondition "Before Next Pane is Displayed" Permission "can create" \
    FailureMessage "<%DirectoryPermissionText%>"

Property Image image "Image" "<%Image%>"
Property Buttons buttons "Buttons" "Back/Next/Cancel"

Text Title
Text Caption
Text DestinationLabel "Destination Label" 0
Text BrowseButton     "Browse Button"     1
Text NextButton       "Next Button"       1
Text BackButton       "Back Button"       1
Text CancelButton     "Cancel Button"     1
Added Themes/Classic_Wizard/Install/SelectDestination.tcl.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.SelectDestination { wizard id } {
    CreateWindow.CustomBlankPane1 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 0 -weight 1

    Label $base.caption -autowrap 1 -anchor nw -justify left
    grid  $base.caption -row 0 -column 0 -sticky news
    $id widget set Caption -widget $base.caption

    labelframe $base.frame -bd 2 -relief ridge
    grid $base.frame -row 1 -column 0 -sticky ew -padx [list 0 5] -pady 10
    $id widget set DestinationLabel -widget $base.frame

    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 0 -weight 1

    Label $base.frame.label -anchor w -textvariable info(InstallDir) \
        -elide 1 -ellipsis {[...]} -elideside center
    grid  $base.frame.label -row 0 -column 0 -sticky ew
    $id widget set Destination -widget $base.frame.label

    ttk::button $base.frame.button -command \
        [list ::InstallAPI::PromptForDirectory -virtualtext InstallDir]
    grid $base.frame.button -row 0 -column 1 -padx 2
    $id widget set BrowseButton -widget $base.frame.button
}
Added Themes/Classic_Wizard/Install/SelectProgramFolder.pane.
























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane SelectProgramFolder "Select Program Folder"

Order 11

Include CustomBlankPane1

Condition PlatformCondition Operation "equals" Platform "Windows"

Property Active boolean "Active" No
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Image image "Image" "<%Image%>"
Property DefaultFolder shorttext "Default Folder" "<%AppName%>"

Text Title
Text Caption
Text ProgramFolderLabel   "Program Folder Label"   0
Text FolderListLabel      "Folder List Label"      0
Text NextButton           "Next Button"            1
Text BackButton           "Back Button"            1
Text CancelButton         "Cancel Button"          1
Text AllUsersCheckbutton  "All Users Checkbutton"  0
Added Themes/Classic_Wizard/Install/SelectProgramFolder.tcl.




























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.SelectProgramFolder { wizard id } {
    CreateWindow.CustomBlankPane1 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 4 -weight 1
    grid columnconfigure $base 0 -weight 1

    Label $base.caption -autowrap 1 -anchor nw -justify left
    grid  $base.caption -row 0 -column 0 -sticky new -pady [list 0 5]
    $id widget set Caption -widget $base.caption

    label $base.label
    grid  $base.label -row 1 -column 0 -sticky w -pady [list 0 2]
    $id widget set ProgramFolderLabel -widget $base.label

    entry $base.entry -textvariable ::info(ProgramFolderName)
    grid  $base.entry -row 2 -column 0 -sticky ew

    label $base.label2
    grid  $base.label2 -row 3 -column 0 -sticky w -pady [list 10 0]
    $id widget set FolderListLabel -widget $base.label2

    frame $base.frame
    grid  $base.frame -row 4 -column 0 -sticky news -pady {2 0}

    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 0 -weight 1

    listbox $base.frame.list \
        -bg #FFFFFF -highlightthickness 0 -selectmode single \
        -xscrollcommand "$base.frame.hs set" \
        -yscrollcommand "$base.frame.vs set"
    grid $base.frame.list -row 0 -column 0 -sticky news
    $id widget set ProgramFolderListBox -widget $base.frame.list \
        -type optiontree

    ttk::scrollbar $base.frame.vs -command "$base.frame.list yview"
    grid $base.frame.vs -row 0 -column 1 -sticky ns

    ttk::scrollbar $base.frame.hs -command "$base.frame.list xview" \
        -orient horizontal
    grid $base.frame.hs -row 1 -column 0 -stick ew

    bind $base.frame.list <1> [list focus %W]
    bind $base.frame.list <Double-1> ::InstallJammer::SetProgramFolder

    ttk::checkbutton $base.allUsers -variable ::info(ProgramFolderAllUsers)
    grid $base.allUsers -row 5 -column 0 -sticky nw -pady {2 10}
    $id widget set AllUsersCheckbutton -widget $base.allUsers

    if {![info exists ::InstallJammer]} {
        ::InstallJammer::PopulateProgramFolders $id
    }
}
Added Themes/Classic_Wizard/Install/Setup.pane.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Window Setup "Setup Window"

Order 2

Action CreateInstallPanes
Action MoveForward

Property Anchor anchor "Anchor" "s"
Property Icon image "Icon" "<%Icon%>"

Text Title
Text Caption
Added Themes/Classic_Wizard/Install/Setup.tcl.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.Setup { wizard id } {
    set base [Toplevel $id 325x90]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 1 -weight 1

    label $base.icon
    grid  $base.icon -row 0 -column 0 -sticky w -padx 5
    $id widget set Icon -widget $base.icon -type image

    Label $base.caption -autowrap 1 -anchor nw -justify left
    grid $base.caption -row 0 -column 1 -sticky w -pady [list 10 0]
    $id widget set Caption -widget $base.caption

    ::Progressbar::New $base.progress
    grid $base.progress -row 1 -column 1 -sticky ew -padx [list 0 10] -pady 5
    $id widget set ProgressBar -widget $base.progress -type progress
}
Added Themes/Classic_Wizard/Install/SetupComplete.pane.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane SetupComplete "Setup Complete"

Order 14

Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Image image "Image" "<%Image%>"

Text Title
Text Caption
Text Text
Text NextButton    "Next Button"    1
Text BackButton    "Back Button"    1
Text CancelButton  "Cancel Button"  1
Added Themes/Classic_Wizard/Install/SetupComplete.tcl.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.SetupComplete { wizard id } {
    set base [$wizard widget get $id]

    grid rowconfigure    $base 1 -weight 1
    grid columnconfigure $base 1 -weight 1

    Image $base.image $id Image
    grid  $base.image -row 0 -column 0 -rowspan 5 -sticky nw -padx 15 -pady 15

    Label $base.caption -autowrap 1 -anchor nw -justify left
    grid $base.caption -row 0 -column 1 -sticky nw -padx [list 0 15] -pady 15
    $id widget set Caption -widget $base.caption

    Label $base.text -autowrap 1 -anchor nw -justify left
    grid $base.text -row 1 -column 1 -sticky sew -padx [list 0 15] -pady 15
    $id widget set Text -widget $base.text
}
Added Themes/Classic_Wizard/Install/SetupType.pane.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane SetupType "Setup Type"

Order 9

Include CustomBlankPane1

Condition ScriptCondition Script {[llength [SetupTypes children]] > 1}

Property Active boolean "Active" No
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Image image "Image" "<%Image%>"

Text Title
Text Caption
Text NextButton   "Next Button"   1
Text BackButton   "Back Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Classic_Wizard/Install/SetupType.tcl.






















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.SetupType { wizard id } {
    CreateWindow.CustomBlankPane1 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 1 -weight 1
    grid columnconfigure $base 0 -weight 1

    Label $base.caption -autowrap 1 -anchor nw -justify left
    grid  $base.caption -row 0 -column 0 -sticky ew -padx [list 0 10] -pady 15
    $id widget set Caption -widget $base.caption

    set f [frame $base.types]
    grid $f -row 1 -column 0 -sticky new

    grid columnconfigure $f 1 -weight 1

    if {[info exists ::InstallJammer]} { return }

    foreach id [SetupTypes children] {
        if {![$id active] || ![$id get ShowSetupType]} { continue }

        set radio $f.radio[incr0 row]

        ttk::radiobutton $radio -text [$id name] \
            -value [$id name] -variable ::info(InstallType) \
            -command ::InstallJammer::SelectSetupType

        set label $f.label$row
        Label $label -autowrap 1 -anchor nw -justify left \
            -text [::InstallJammer::GetText $id Description]

        grid $radio -column 0 -row $row -sticky nw -padx 5 -pady 10
        grid $label -column 1 -row $row -sticky ew -padx 5 -pady 10
    }
}
Added Themes/Classic_Wizard/Install/Splash.pane.


































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Window Splash "Splash Screen"

Order 3

Action MoveForward

Property Active boolean "Active" No
Property Image image "Splash Image"
Property Anchor anchor "Anchor" "center"
Property SplashTimer shorttext "Splash Timer" 2
Added Themes/Classic_Wizard/Install/Splash.tcl.






















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.Splash { wizard id } {
    if {![$id get SplashTimer timer]} { return }
    if {![::InstallJammer::ImageExists $id,Image]} { return }

    set base   [$id window]
    set image  [::InstallJammer::Image $id Image]
    set width  [image width $image]
    set height [image height $image]

    toplevel    $base
    wm withdraw $base
    wm override $base 1
    ::InstallJammer::PlaceWindow $id -width $width -height $height

    label $base.l
    pack  $base.l
    $id widget set Image -type image -widget $base.l

    bind $base.l <Button-1> [list ::InstallJammer::Window hide $base]
}
Added Themes/Classic_Wizard/Install/StartCopyingFiles.pane.












































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane StartCopyingFiles "Start Copying Files"

Order 12

Include CustomTextPane2

Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Image image "Image" "<%Image%>"

Text Title
Text Caption
Text Text
Text NextButton   "Next Button"   1
Text BackButton   "Back Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Classic_Wizard/Install/StartCopyingFiles.tcl.




















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.StartCopyingFiles { wizard id } {
    CreateWindow.CustomTextPane2 $wizard $id
}
Added Themes/Classic_Wizard/Install/UserInformation.pane.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane UserInformation "User Information"

Order 7

Include CustomBlankPane1

Property Active boolean "Active" No
Property Image image "Image" "<%Image%>"
Property Buttons buttons "Buttons" "Back/Next/Cancel"

Text Title
Text Caption
Text NameLabel    "Name Label"    0
Text CompanyLabel "Company Label" 0
Text NextButton   "Next Button"   1
Text BackButton   "Back Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Classic_Wizard/Install/UserInformation.tcl.
















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.UserInformation { wizard id } {
    CreateWindow.CustomBlankPane1 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 1 -weight 1
    grid columnconfigure $base 0 -weight 1

    Label $base.caption -autowrap 1 -anchor nw -justify left
    grid  $base.caption -row 0 -column 0 -sticky new -pady 15
    $id widget set Caption -widget $base.caption

    frame $base.frame
    grid  $base.frame -row 1 -column 0 -sticky new -padx [list 0 15] -pady 20

    grid columnconfigure $base.frame 1 -weight 1

    label $base.frame.nameL
    grid  $base.frame.nameL -row 0 -column 0 -sticky w -padx 5 -pady 5
    $id widget set NameLabel -widget $base.frame.nameL

    entry $base.frame.nameE -textvariable info(UserInfoName)
    grid  $base.frame.nameE -row 0 -column 1 -sticky ew -pady 5

    label $base.frame.companyL
    grid  $base.frame.companyL -row 1 -column 0 -sticky w -padx 5 -pady 5
    $id widget set CompanyLabel -widget $base.frame.companyL

    entry $base.frame.companyE -textvariable info(UserInfoCompany)
    grid  $base.frame.companyE -row 1 -column 1 -sticky ew

    focus $base.frame.nameE
}
Added Themes/Classic_Wizard/Install/Welcome.pane.














































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane Welcome "Welcome Screen"

Order 4

Include CustomTextPane1

Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon image "Icon" "<%Icon%>"
Property Image image "Image" "<%Image%>"

Text Title
Text Caption
Text Message
Text BackButton   "Back Button"   1
Text NextButton   "Next Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Classic_Wizard/Install/Welcome.tcl.




















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.Welcome { wizard id } {
    CreateWindow.CustomTextPane1 $wizard $id
}
Added Themes/Classic_Wizard/Install/init.tcl.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ThemeInit {} {
    variable info

    ## Create the main wizard.
    Wizard $info(Wizard) \
        -raisecommand [list RaiseStep %W %S] \
        -width [::InstallJammer::SubstText "<%WizardWidth%>"] \
        -height [::InstallJammer::SubstText "<%WizardHeight%>"]

    if {$::tcl_platform(platform) eq "unix"} {
        $info(Wizard) configure -bg [style configure . -background]
    }
}
Added Themes/Classic_Wizard/Install/main.tcl.
























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc main {} {
    ::InstallJammer::InstallMain
}

if {![info exists ::InstallJammer]} { main }
Added Themes/Classic_Wizard/Install/utils.tcl.
























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc Toplevel { id geometry } {
    set base [$id window]

    toplevel     $base
    wm withdraw  $base
    update idletasks
    wm transient $base .
    wm protocol  $base WM_DELETE_WINDOW [list ::InstallJammer::exit 1]
    wm resizable $base 0 0
    wm geometry  $base $geometry
    ::InstallJammer::SetTitle $base $id
    lassign [split $geometry x] w h
    ::InstallJammer::PlaceWindow $id -width $w -height $h

    return $base
}

proc Image { path id field } {
    label $path -relief sunken -borderwidth 2 -width 0 -height 0
    ::InstallJammer::SetImage $path $id $field
}
Added Themes/Classic_Wizard/Uninstall/Uninstall.pane.






















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Window Uninstall "Uninstall Window" 1

Order 1

Action ExecuteAction Action "Uninstall Actions"

Action UninstallLeftoverFiles
Condition StringIsCondition Operator "true" String "<%ErrorsOccurred%>"
Condition AskYesOrNo \
    Title   "Uninstall <%AppName%>" Message "<%UninstallLeftoverText%>"

Action MoveForward

Property Anchor anchor "Anchor" "center"
Property Icon image "Icon" "<%Icon%>"

Text Title
Text Caption
Text Message
Text ProgressValue "Progress Value"
Added Themes/Classic_Wizard/Uninstall/Uninstall.tcl.










































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.Uninstall { wizard id } {
    set base [$id window]

    toplevel     $base
    wm withdraw  $base
    wm geometry  $base 347x110
    wm protocol  $base WM_DELETE_WINDOW [list $wizard finish 1]
    wm resizable $base 0 0
    ::InstallJammer::SetTitle    $base $id
    ::InstallJammer::PlaceWindow $id -width 347 -height 110

    grid rowconfigure    $base 2 -weight 1
    grid columnconfigure $base 1 -weight 1

    label $base.icon
    grid  $base.icon -row 0 -column 0 -rowspan 3 -sticky nw -pady 20 -padx 10
    $id widget set Icon -widget $base.icon -type image

    label $base.caption -anchor w
    grid  $base.caption -row 0 -column 1 -sticky sw -padx 7 -pady 10
    $id widget set Caption -widget $base.caption

    label $base.message -anchor w
    grid  $base.message -row 1 -column 1 -sticky sw -padx 7 -pady [list 5 0]
    $id widget set Message -widget $base.message

    ::Progressbar::New $base.progress
    grid $base.progress -row 2 -column 1 -sticky ew -padx 10
    $id widget set ProgressValue -widget $base.progress -type progress
}
Added Themes/Classic_Wizard/Uninstall/UninstallComplete.pane.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Window UninstallComplete "Uninstall Complete Window" 1

Order 3

Condition StringIsCondition Operator "false" String "<%ErrorsOccurred%>"

Property Anchor anchor "Anchor" "center"
Property Icon image "Icon" "<%Icon%>"

Text Title
Text Caption
Text FinishButton "Finish Button" 1
Added Themes/Classic_Wizard/Uninstall/UninstallComplete.tcl.














































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.UninstallComplete { wizard id } {
    set base [$id window]

    toplevel     $base
    wm withdraw  $base
    wm geometry  $base 347x110
    wm protocol  $base WM_DELETE_WINDOW [list $wizard finish 1]
    wm resizable $base 0 0
    ::InstallJammer::SetTitle    $base $id
    ::InstallJammer::PlaceWindow $id -width 347 -height 110

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 1 -weight 1

    label $base.icon
    grid  $base.icon -row 0 -column 0 -sticky nw -padx 20 -pady 5
    $id widget set Icon -widget $base.icon -type image

    Label $base.label -autowrap 1 -anchor nw -justify left
    grid  $base.label -row 0 -column 1 -sticky new -pady 5
    $id widget set Caption -widget $base.label

    set text [::InstallJammer::GetText $id FinishButton]
    set width [string length $text]
    if {$width < 12} { set width 12 }

    ttk::button $base.finish -width $width -command [list $wizard finish 1]
    grid   $base.finish -row 1 -column 1 -sticky se -padx 5 -pady 5
    $id widget set FinishButton -widget $base.finish

    focus  $base.finish
}
Added Themes/Classic_Wizard/Uninstall/UninstallDetails.pane.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Window UninstallDetails "Uninstall Error Details Window" 1

Order 2

Condition StringIsCondition Operator "true" String "<%ErrorsOccurred%>"

Property Anchor anchor "Anchor" "center"
Property Icon image "Icon" "<%Icon%>"

Text Title
Text Caption
Text Errors "Error Messages"
Text FinishButton "Finish Button" 1
Added Themes/Classic_Wizard/Uninstall/UninstallDetails.tcl.


















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.UninstallDetails { wizard id } {
    set base [$id window]

    toplevel     $base
    wm withdraw  $base
    wm geometry  $base 500x400
    wm protocol  $base WM_DELETE_WINDOW exit
    wm resizable $base 0 0
    ::InstallJammer::SetTitle    $base $id
    ::InstallJammer::PlaceWindow $id -width 500 -height 400

    grid rowconfigure    $base 1 -weight 1
    grid columnconfigure $base 1 -weight 1

    label $base.icon
    grid  $base.icon -row 0 -column 0 -sticky nw -padx 5 -pady 5
    $id widget set Icon -widget $base.icon -type image

    label $base.caption 
    grid  $base.caption -row 0 -column 1 -sticky sw -padx 5 -pady 5
    $id widget set Caption -widget $base.caption

    text $base.text -bg #FFFFFF -bd 2 -relief sunken -wrap word
    grid $base.text -row 1 -column 0 -columnspan 2 -sticky news
    $id widget set Errors -widget $base.text

    set text [::InstallJammer::GetText $id FinishButton]
    set width [string length $text]
    if {$width < 12} { set width 12 }

    ttk::button $base.finish -width $width -command [list $wizard finish 1]
    grid $base.finish -row 2 -column 1 -sticky se -padx 5 -pady 5
    $id widget set FinishButton -widget $base.finish
}
Added Themes/Classic_Wizard/Uninstall/init.tcl.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ThemeInit {} {
    global info

    Wizard $info(Wizard) \
        -width  [::InstallJammer::SubstText "<%WizardWidth%>"] \
        -height [::InstallJammer::SubstText "<%WizardHeight%>"]

    bind $info(Wizard) <<WizardFinish>> [list ::InstallJammer::exit 1]

    if {$::tcl_platform(platform) eq "unix"} {
        $info(Wizard) configure -bg [style configure . -background]
    }
}
Added Themes/Classic_Wizard/Uninstall/main.tcl.
























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc main {} {
    ::InstallJammer::UninstallMain
}

if {![info exists ::InstallJammer]} { main }
Added Themes/Classic_Wizard/cs.msg.




































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# options: -encoding utf-8

Background {
    Title
    "Instalace programu <%AppName%>"

    Text
    "<%AppName%>"
}

ChooseComponents {
    Title
    "Vlastní instalace"

    Caption
    "Zvolte souÄásti, které chcete nainstalovat, a zruÅ¡te vybrání souÄástí,\
     které nechcete nainstalovat."

    ComponentLabel
    "SouÄásti"

    DescriptionLabel
    "Popis"

    SpaceRequiredLabel
    "Vyžadované místo: <%SpaceRequiredText%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Kopírování souborů"

    Caption
    "<%GroupBeingInstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Title
    "Instalace programu <%AppName%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


CustomTextPane1 {
    Title
    "Nadpis"

    Caption
    "Titulek"

    Message
    "Zpráva"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane2 {
    Title
    "Instalace programu <%AppName%>"

    Caption
    "Titulek"

    Text
    "Zde bude text."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane3 {
    Title
    "Nadpis"

    Caption
    "Titulek"

    Message
    "Zpráva"

    Text
    "Zde bude text."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

License {
    Title
    "LicenÄní ujednání"

    Caption
    "Prosím pÅ™eÄtÄ›te si následující licenÄní ujednání. StisknÄ›te klávesu PAGE DOWN\
     pro zobrazení zbytku ujednání."

    Message
    "PÅ™ijímáte podmínky pÅ™edchozího licenÄního ujednání? Pokud zvolíte\
     Ne, instalátor se ukonÄí. K instalaci programu <%AppName%> musíte\
     přijmout toto ujednání."

    Text
    "Sem vložte své licenÄní ujednání."

    AcceptCheck
    "PÅ™ijímám podmínky licenÄního ujednání."

    NextButton
    "Ano"

    BackButton
    "< <%Back%>"

    CancelButton
    "Ne"
}

Readme {
    Title
    "Informace ÄŒtiMÄ›"

    Text
    "Sem vložte vaÅ¡e informace ÄtimÄ›."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Zvolte cílové umístění"

    Caption
    "Program <%AppName%> bude nainstalován do následující složky.\n\nK instalaci\
     do této složky stiskněte Vpřed. K instalaci do jiné složky stiskněte\
     Procházet a zvolte jinou složku.\n\nStisknutím ZruÅ¡it ukonÄíte instalaci\
     programu <%AppName%>."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Cílová složka"
}

SelectProgramFolder {
    Title
    "Zvolte složku programu"

    Caption
    "Instalátor přidá ikony programu do složky programu uvedené níže.\
     Můžete vepsat odlišný název složky nebo ji vybrat ze seznamu existujících složek.\
     K pokraÄování stisknÄ›te VpÅ™ed."

    ProgramFolderLabel
    "Složka programu:"

    FolderListLabel
    "Existující složky:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Vytvořit složku programu pro všechny uživatele"
}

Setup {
    Title
    "Instalace"

    Caption
    "Instalátor připravuje průvodce InstallJammer, který vás provede zbytkem\
     procesu instalace. Prosím Äekejte."
}

SetupComplete {
    Title
    "Instalace dokonÄena"

    Caption
    "Instalátor dokonÄil instalaci programu <%AppName%> na váš poÄítaÄ."

    Text
    "StisknÄ›te DokonÄit pro dokonÄení instalace."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Typ instalace"

    Caption
    "Zvolte typ instalace, který vám nejlépe vyhovuje, a stiskněte Vpřed."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Spustit kopírování souborů"

    Caption
     "Instalátor má dostatek informací pro spustění kopírování souborů programu. Pokud\
     chcete zkontrolovat nebo změnit jakékoliv nastavení, stiskněte Zpět. Pokud jste\
     spokojeni s nastavením, stiskněte Vpřed pro spuštění kopírování souborů.\
     \n\nAktuální nastavení:"

    Text
    "InstalaÄní složka:\n\
     \t<%InstallDir%>

    Typ instalace:\n\
    \t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Odinstalace programu <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Title
    "Odinstalace dokonÄena"

    Caption
    "Odinstalace úspěšnÄ› dokonÄena."

    FinishButton
    "<%Finish%>"
}

UninstallDetails {
    Title
    "Podrobnosti odinstalace"

    Caption
    "Následující chyby nastaly během odstraňování:"

    Errors
    "<%Errors%>"

    FinishButton
    "<%Finish%>"
}


UserInformation {
    Title
    "Uživatelské informace"

    Caption
    "VepiÅ¡te níže své jméno a spoleÄnost, pro kterou pracujete."

    NameLabel
    "Jméno:"

    CompanyLabel
    "SpoleÄnost:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Welcome {
    Title
    "Uvítací obrazovka"

    Caption
    "Vítejte v instalátoru programu <%AppName%>. Tento program nainstaluje\
     aplikaci <%AppName%> na váš poÄítaÄ."

    Message
    "Je důraznÄ› doporuÄeno ukonÄit vÅ¡echny programy Windows, které máte\
     spuÅ¡tÄ›né. StisknÄ›te VpÅ™ed k pokraÄování v instalaci.\n\nVAROVÃNÃ: \
     Tento program je chráněn autorským právem a mezinárodními\
     dohodami.\n\nNepovolená reprodukce nebo šíření tohoto programu, \
     nebo jeho libovolné Äásti, může vyústit ve vážné obÄanské a kriminální postihy\
     a bude stíháno v maximálním možném právním rozsahu."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Classic_Wizard/de.msg.










































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
Background {
    Title
    "<%AppName%> Setup"

    Text
    "<%AppName%>"
}

ChooseComponents {
    Title
    "Benutzerdefinierte Einstellungen"

    Caption
    "Wählen Sie die zu installierenden Komponenten aus und deselektieren Sie\
    die Komponenten, die Sie nicht installieren möchten."

    ComponentLabel
    "Komponenten"

    DescriptionLabel
    "Beschreibung"

    SpaceRequiredLabel
    "<%SpaceRequiredText%> an Plattenplatz benötigt"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Kopiere Dateien"

    Caption
    "<%GroupBeingInstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Title
    "<%AppName%> Setup"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


CustomTextPane1 {
    Title
    "Titel"

    Caption
    "Überschrift"

    Message
    "Meldung"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane2 {
    Title
    "<%AppName%> Setup"

    Caption
    "Überschrift"

    Text
    "Text kommt hier hin."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane3 {
    Title
    "Title"

    Caption
    "Überschrift"

    Message
    "Meldung"

    Text
    "Text kommt hier hin."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

License {
    Title
    "Lizenzbestimmungen"

    Caption
    "Bitte lesen Sie die folgenden Lizenzbestimmungen.  Press the PAGE DOWN key\
     to see the rest of the agreement."

    Message
    "Akzeptieren Sie die vorangegangenen Lizenzbestimmungen? Wenn Sie Nein\
    wählen, wird die Installation beendet. Um <%AppName%> zu installieren,\
    müssen Sie den Lizenzbestimmungen zustimmen."

    Text
    "Hier kommen Ihre Lizenzbestimmungen hin."

    AcceptCheck
    "Ich akzeptiere die Lizenzbestimmungen."

    NextButton
    "Ja"

    BackButton
    "< <%Back%>"

    CancelButton
    "Nein"
}

Readme {
    Title
    "Liesmich Informationen"

    Text
    "Hier kommen Ihre Liesmich Informationen hin."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Auswahl Installationsziel"

    Caption
    "Setup wird <%AppName%> in das folgende Verzeichnis installieren. \
    \n\nKlicken Sie auf Weiter, wenn dieses Verzeichnis verwendet werden soll. \
    \n\nUm ein anderes Verzeichnis auszuwählen, klicken Sie auf Durchsuchen\
    \n\nMöchten Sie <%AppName%> nicht installieren,\
    dann klicken Sie auf Abbrechen, um das Setup zu verlassen."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Zielordner"
}

SelectProgramFolder {
    Title
    "Auswahl Programmordner"

    Caption
    "Setup wird die Programmsymbole zum unten aufgeführten Programmordner\
    hinzufügen. Sie können einen neuen Ordnernamen eingeben oder einen von der\
    von der existierenden Ordnerliste auswählen. Klicken Sie auf Weiter um\
    Fortzufahren."

    ProgramFolderLabel
    "Programmordner:"

    FolderListLabel
    "Vorhandene Ordner:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Erstelle Programmordner für alle Benutzer"
}

Setup {
    Title
    "Setup"

    Caption
    "Setup bereitet den InstallJammer Assistenten vor, der Sie durch den\
    Rest des Installationsvorgang führen wird. Bitte warten Sie."
}

SetupComplete {
    Title
    "Setup Vollständig"

    Caption
    "Setup hat die Installation von <%AppName%> auf Ihrem Computer beendet."

    Text
    "Klicken Sie auf Beenden, um Setup zu verlassen."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Setup Art"

    Caption
    "Klicken Sie auf die bevorzugte Art des Setup, dann auf Weiter."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Start Copying Files"

    Caption
    "Setup hat genug Informationen, um die Programmdateien zu kopieren. \
    Wenn Sie die Einstellungen überprüfen oder ändern möchten,\
    klicken Sie auf Zurück. Wenn Sie mit den Einstellungen zufrieden sind,\
    klicken Sie auf Weiter, um mit dem Kopieren der Dateien zu beginnen. \
    \n\nDerzeitige Einstellungen:"
    

    Text
    "Install Directory:\n\
     \t<%InstallDir%>

    Setup Type:\n\
    \t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Deinstallation <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Title
    "Deinstallation Abgeschlossen"

    Caption
    "Deinstallation erfolgreich abgeschlossen."

    FinishButton
    "<%Finish%>"
}

UninstallDetails {
    Title
    "Deinstallation Details"

    Caption
    "Die folgenden Fehler sind beim Löschen aufgetreten:"

    Errors
    "<%Errors%>"

    FinishButton
    "<%Finish%>"
}


UserInformation {
    Title
    "Benutzer Information"

    Caption
    "Bitte geben Sie Ihren Namen und den Namen der Firma ein, für die Sie\
    arbeiten."

    NameLabel
    "Name:"

    CompanyLabel
    "Firma:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Welcome {
    Title
    "Willkommen"

    Caption
    "Willkommen zum Setup von <%AppName%>. Dieses Programm wird <%AppName%>\
    auf Ihrem Computer installieren."

    Message
    "Es wird empfohlen, das Sie alle anderen Anwendungen schließen, bevor\
    Sie fortfahren.\n\nKlicken Sie auf Weiter um Fortzufahren.\n\nWARNUNG:\
    Dies Programm ist urheberrechtlich geschützt. Nicht authorisierte\
    Vervielfältigung oder Verbreitung von diesem Programm oder Teilen dessen,\
    können zu erheblichen Strafen führen und diese werden nach maximalen\
    Möglichkeiten der geltenden Gesetze angewendet."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Classic_Wizard/en.msg.
































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
Background {
    Title
    "<%AppName%> Setup"

    Text
    "<%AppName%>"
}

ChooseComponents {
    Title
    "Custom Setup"

    Caption
    "Select the components you want to install and deselect the components\
     you do not want to install."

    ComponentLabel
    "Components"

    DescriptionLabel
    "Description"

    SpaceRequiredLabel
    "Space Required: <%SpaceRequiredText%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Copying Files"

    Caption
    "<%GroupBeingInstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Title
    "<%AppName%> Setup"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


CustomTextPane1 {
    Title
    "Title"

    Caption
    "Caption"

    Message
    "Message"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane2 {
    Title
    "<%AppName%> Setup"

    Caption
    "Caption"

    Text
    "Text goes here."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane3 {
    Title
    "Title"

    Caption
    "Caption"

    Message
    "Message"

    Text
    "Text goes here."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

License {
    Title
    "License Agreement"

    Caption
    "Please read the following License Agreement.  Press the PAGE DOWN key\
     to see the rest of the agreement."

    Message
    "Do you accept all the terms of the preceding License Agreement?  If\
     you choose No, Setup will close.  To install <%AppName%>, you must\
     accept this agreement."

    Text
    "Put your license agreement here."

    AcceptCheck
    "I accept the terms of this license agreement."

    NextButton
    "Yes"

    BackButton
    "< <%Back%>"

    CancelButton
    "No"
}

Readme {
    Title
    "Readme Information"

    Text
    "Put your readme information here."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Select Destination Location"

    Caption
    "Setup will install <%AppName%> in the following folder.\n\nTo install\
     to this folder, click Next.\n\nTo install to a different folder, click\
     Browse and select another folder.\n\nYou can choose not to install\
     <%AppName%> by clicking Cancel to exit Setup."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Destination Folder"
}

SelectProgramFolder {
    Title
    "Select Program Folder"

    Caption
    "Setup will add the program icons to the Program Folder listed below. \
     You may type a new folder name or select from the existing folders list. \
     Click Next to continue."

    ProgramFolderLabel
    "Program Folder:"

    FolderListLabel
    "Exising Folders:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Create program folder for all users"
}

Setup {
    Title
    "Setup"

    Caption
    "Setup is preparing the InstallJammer Wizard which will guide you through\
     the rest of the setup process.  Please wait."
}

SetupComplete {
    Title
    "Setup Complete"

    Caption
    "Setup has finished installing <%AppName%> on your computer."

    Text
    "Click Finish to complete Setup."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Setup Type"

    Caption
    "Click the type of Setup you prefer, then click Next."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Start Copying Files"

    Caption
    "Setup has enough information to start copying the program files.  If\
     you want to review or change any settings, click Back.  If you are\
     satisfied with the settings, click Next to begin copying files. \
     \n\nCurrent Settings:"

    Text
    "Install Directory:\n\
     \t<%InstallDir%>

    Setup Type:\n\
    \t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Uninstall <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Title
    "Uninstall Complete"

    Caption
    "Uninstall Completes Successfully."

    FinishButton
    "<%Finish%>"
}

UninstallDetails {
    Title
    "Uninstall Details"

    Caption
    "The following errors occurred during uninstall:"

    Errors
    "<%Errors%>"

    FinishButton
    "<%Finish%>"
}


UserInformation {
    Title
    "User Information"

    Caption
    "Type your name and the company you work for below."

    NameLabel
    "Name:"

    CompanyLabel
    "Company:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Welcome {
    Title
    "Welcome Screen"

    Caption
    "Welcome to the <%AppName%> Setup program.  This program will install\
     <%AppName%> on your computer."

    Message
    "It is strongly recommended that you exit all Windows programs you have\
     running.  Click Next to continue with the Setup program.\n\nWARNING:\
     This program is protected by copyright law and international\
     treaties.\n\nUnauthorized reproduction or distribution of this program,\
     or any portion of it, may result in severe civil and criminal penalties,\
     and will be prosecuted to the maximum extent possible under law."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Classic_Wizard/es.msg.


































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
Background {
    Title
    "Instalación de <%AppName%>"

    Text
    "<%AppName%>"
}

ChooseComponents {
    Title
    "Instalación Personalizada"

    Caption
    "Seleccione los componentes que desea instalar y elimine aquéllos\
    que no desea que sean instalados."

    ComponentLabel
    "Componentes"

    DescriptionLabel
    "Descripción"

    SpaceRequiredLabel
    "Espacio Requerido: <%SpaceRequiredText%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Copiando Archivos"

    Caption
    "<%GroupBeingInstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Title
    "Instalación de <%AppName%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


CustomTextPane1 {
    Title
    "Título"

    Caption
    "Leyenda"

    Message
    "Mensaje"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane2 {
    Title
    "Instalación de <%AppName%>"

    Caption
    "Leyenda"

    Text
    "Texto aquí."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane3 {
    Title
    "Título"

    Caption
    "Leyenda"

    Message
    "Mensaje"

    Text
    "Texto aquí."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

License {
    Title
    "Acuerdo de Licencia"

    Caption
    "Por favor lea el siguiente Acuerdo de Licencia. Presione Av.Pag\
    para ver el resto del acuerdo."

    Message
    "¿Acepta los terminos del Acuerdo de Licencia anterior?\
    Si escoge No, la instalación se cerrara. Para instalar <%AppName%>,\
    debe aceptar este acuerdo."

    Text
    "Ponga aquí su Acuerdo de Licencia."

    AcceptCheck
    "Acepto los términos de este Acuerdo de Licencia."

    NextButton
    "Sí"

    BackButton
    "< <%Back%>"

    CancelButton
    "No"
}

Readme {
    Title
    "Léame"

    Text
    "Ponga aqui su Léame."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Seleccione carpeta destino"

    Caption
    "Se instalará <%AppName%> en la siguiente carpeta.\n\nPara instalar en\
    esta carpeta, pulse Siguiente.\n\nPara instalar en una carpeta diferente,\
    pulse Examinar y seleccione otra carpeta.\n\nPuede escoger no instalar\
    <%AppName%> pulsando Cancelar para salir de la instalación."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Carpeta Destino"
}

SelectProgramFolder {
    Title
    "Seleccione Grupo de Programas"

    Caption
    "Se instalarán iconos en el Grupo de Programas siguiente. \
    Puede escribir un nuevo nombre de grupo o seleccionarlo\
    de la lista de grupos existentes. \
    Pulse Siguiente para continuar."

    ProgramFolderLabel
    "Grupo de Programas:"

    FolderListLabel
    "Grupos Existentes:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Crear grupo de programas para todos los usuarios"
}

Setup {
    Title
    "Instalación"

    Caption
    "El programa de instalación está preparando el Wizard InstallJammer, que\
    le guiara a través del proceso de instalación. Por favor espere."
}

SetupComplete {
    Title
    "Instalación Completa"

    Caption
    "Se ha finalizado la instalación de <%AppName%> en su equipo."

    Text
    "Pulse Finalizar para completar la instalación."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Tipo de Instalación"

    Caption
    "Seleccione el tipo de instalación que prefiere, y pulse Siguiente."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Comenzar a Copiar Archivos"

    Caption
    "Se ha recopilado la información necesaria para comenzar a copiar los\
    archivos del programa. Si desea revisar o cambiar la configuración,\
    pulse Atrás. Si esta conforme con la configuración, pulse Siguiente para\
    comenzar a copiar los archivos.
    \n\nConfiguración actual:"

    Text
    "Directorio de Instalación:\n\
     \t<%InstallDir%>

    Tipo de Instalación:\n\
    \t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Desinstalación de <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Title
    "Desinstalación Completa"

    Caption
    "La Desinstalación se completó con exito."

    FinishButton
    "<%Finish%>"
}

UninstallDetails {
    Title
    "Detalles de la Desinstalación"

    Caption
    "Ocurrieron los siguientes errores durante el proceso de desinstalación:"

    Errors
    "<%Errors%>"

    FinishButton
    "<%Finish%>"
}


UserInformation {
    Title
    "Información de Usuario"

    Caption
    "Escriba su nombre y empresa a continuación."

    NameLabel
    "Nombre:"

    CompanyLabel
    "Empresa:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Welcome {
    Title
    "Pantalla de Bievenida"

    Caption
    "Bienvenido al programa de instalación de <%AppName%>. Este programa instalará\
     <%AppName%> en su equipo."

    Message
    "Se recomienda salir de todos los programas Windows que este ejecutando. \
    Pulse Siguiente para continuar con el programa de instalación.\n\nADVERTENCIA:\
    Este programa esta protegido con copyright y los acuerdos internacionales.\n\n
    La reproducción o distribución no autorizada de este programa, o parte del mismo,\
    puede acarrear penas civiles y criminales, y será perseguida por la ley."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Classic_Wizard/fr.msg.






























































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
Background {
    Title
    "Installation <%AppName%>"

    Text
    "<%AppName%>"
}

ChooseComponents {
    Title
    "Installation personnalisée"

    Caption
    "Sélectionner les composants à installer et déselectionner les composants à ne pas installer."

    ComponentLabel
    "Composants"

    DescriptionLabel
    "Description"

    SpaceRequiredLabel
    "Espace requis: <%SpaceRequiredText%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Copie des fichiers"

    Caption
    "<%GroupBeingInstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Title
    "<%AppName%> Setup"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


CustomTextPane1 {
    Title
    "Titre"

    Caption
    "Légende"

    Message
    "Message"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane2 {
    Title
    "Installation <%AppName%>"

    Caption
    "Légende"

    Text
    "Saisir le texte ici."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane3 {
    Title
    "Titre"

    Caption
    "Légende"

    Message
    "Message"

    Text
    "Saisir le texte ici."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

License {
    Title
    "Accord de licence"

    Caption
    "Lisez SVP l'accord de licence suivant.  Appuyez sur la touche PAGE DOWN\
     pour lire la suite de l'accord de licence."

    Message
    "Acceptez-vous tous les termes du précédent accord de licence ?  Si\
     vous choisissez Non, l'installation s'arrêtera.  Pour installer <%AppName%>, vous devez\
     accepter cet accord de licence."

    Text
    "Mettez votre accord de licence ici."

    AcceptCheck
    "J'accepte les termes de cet accord de licence."

    NextButton
    "Oui"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

Readme {
    Title
    "Readme"

    Text
    "Mettez les informations de votre Readme ici."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Sélectionnez le répertoire d'installation"

    Caption
    "L'installation de <%AppName%> s'effectuera dans le répertoire suivant.\n\nPour installer\
     dans ce répertoire, cliquez sur le bouton SUIVANT.\n\nPour installer dans un autre répertoire, cliquez\
     sur le bouton PARCOURIR et sélectionnez un autre répertoire.\n\nVous pouvez choisir de ne pas installer\
     <%AppName%> en cliquant sur le bouton ANNULER pour sortir de l'installation."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Répertoire d'installation"
}

SelectProgramFolder {
    Title
    "Sélectionnez le dossier Programme"

    Caption
    "L'installation ajoutera les icônes de programme au dossier Programme affiché ci-dessous. \
     Vous pouvez saisir un nouveau nom de dossier ou en sélectionner un dans la liste des dossiers existants. \
     Cliquez sur SUIVANT pour continuer."

    ProgramFolderLabel
    "Dossier Programme :"

    FolderListLabel
    "Dossiers existants :"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Créer le dossier programme pour tous les utilisateurs"
}

Setup {
    Title
    "Installation"

    Caption
    "L'installation prépare l'assistant InstallJammer qui vous guidera tout\
     au long du processus d'installation.  Patientez SVP."
}

SetupComplete {
    Title
    "Installation terminée"

    Caption
    "L'installation de <%AppName%> sur votre ordinateur est terminée."

    Text
    "Cliquez sur TERMINER pour finir l'installation."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Type d'installation"

    Caption
    "Cliquez sur le type d'installation que vous souhaitez, puis cliquez sur SUIVANT."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Copie des fichiers"

    Caption
    "L'installeur a maintenant assez d'informations pour commencer à copier les fichiers.  Si\
     vous voulez revoir ou modifier le paramétrage, cliquez sur PRECEDENT.  Si vous êtes\
     satisfait du paramétrage, cliquez sur suivant pour commencer à copier les fichiers. \
     \n\nParamétrage courant:"

    Text
    "Répertoire d'installation:\n\
     \t<%InstallDir%>

    Type d'installation:\n\
    \t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Désinstaller <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Title
    "Désinstallation terminée"

    Caption
    "La désinstallation s'est bien terminée."

    FinishButton
    "<%Finish%>"
}

UninstallDetails {
    Title
    "Details de la désinstallation"

    Caption
    "Les erreurs suivantes sont apparues pendant la désinstallation:"

    Errors
    "<%Errors%>"

    FinishButton
    "<%Finish%>"
}


UserInformation {
    Title
    "Informations sur l'utilisateur"

    Caption
    "Saisissez votre nom et votre société ci-dessous."

    NameLabel
    "Nom:"

    CompanyLabel
    "Société:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Welcome {
    Title
    "Ecran d'accueil"

    Caption
    "Bienvenue dans le programme d'installation de <%AppName%>.  Ce programme installera\
     <%AppName%> sur votre ordinateur."

    Message
    "Il est fortement recommandé de fermer tous les programmes en cours d'exécution. \
     Cliquez sur SUIVANT pour continuer l'installation.\n\nATTENTION:\
     Ce programme est protégé par les lois du copyright et les traités\
     internationaux.\n\nToute reproduction interdite ou distribution de ce programme,\
     dans son intégralité ou en partie, entrainera des poursuites civils et criminelles,\
     avec l'ampleur maximale autorisée par la loi."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Classic_Wizard/hu.msg.
































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
Background {
    Title
    "<%AppName%> Telepítés"

    Text
    "<%AppName%>"
}

ChooseComponents {
    Title
    "Egyedi telepítés"

    Caption
    "Válassza ki azokat a komponenseket, amelyeket fel akar telepíteni,\
     és ne válassza ki azokat, amelyeket nem akar telepíteni."

    ComponentLabel
    "Komponensek"

    DescriptionLabel
    "Leírás"

    SpaceRequiredLabel
    "Szükséges tárterület: <%SpaceRequiredText%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Állományok másolása"

    Caption
    "<%GroupBeingInstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Title
    "A fejléc jön ide."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Cím"

    Caption
    "Leírás"

    Message
    "Üzenet"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane2 {
    Title
    "<%AppName%> Telepítés"

    Caption
    "Fejléc"

    Text
    "Szöveg kerül ide."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane3 {
    Title
    "Cím"

    Caption
    "Fejléc"

    Message
    "Üzenet"

    Text
    "Szöveg kerül ide."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

License {
    Title
    "Licensz elfogadása"

    Caption
    "Kérem olvassa el a következ\u0151 Licensz megállapodást. Nyomja le a PAGE DOWN billenty\u0171t,\
     hogy lássa a megállapodás további részét."

    Message
    "Elfogadja a fenti Licensz megállapodás minden feltételét? Ha\
     Nem-et választ, akkor a telepítés befejez\u0151dik. A <%AppName%> telepítéséhez el kell fogadnia\
     ezt a megállapodást."

    Text
    "Rakja ide a licensz megállapodását."

    AcceptCheck
    "Elfogadom ezt a licensz megállapodás feltételeit."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

Readme {
    Title
    "Olvassa el információk"

    Text
    "Rakja ide az olvassa el információit."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Válassza ki a célkönyvtárat"

    Caption
    "A telepít\u0151 a <%AppName%> programot a következ\u0151 könyvtárba telepíti.\n\n
     Ahhoz, hogy ebbe könyvtárba kerüljön kattintson a <%Next%> gombra\
     Ahhoz, hogy más könyvtárba kerüljön kattintson a <%Browse%> gombra.\n\n
	 A <%Cancel%> választásával kiléphet a <%AppName%> program telepítéséb\u0151l."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Célkönyvtár"
}

SelectProgramFolder {
    Title
    "Program mappa kiválasztás"

    Caption
    "A telepít\u0151 a program ikonokat a lentebb listázott Program mappához fogja hozzáadni. \
	 Megváltoztathatja az új mappa nevét, vagy kiválaszthat egy már létez\u0151t a listáról. \
     Kattintson a <%Next%> gombra a folytatáshoz."

    ProgramFolderLabel
    "Program mappa:"

    FolderListLabel
    "Létez\u0151 mappák:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Létrehozza a program mappát az összes felhasználónak?"
}

Setup {
    Title
    "Telepítés"

    Caption
    "A telepít\u0151 el\u0151készíti az InstallJammer Varázslót, amely keresztülvezeti Önt a\
	 telepítés folyamatán. Kérem várjon!"
}

SetupComplete {
    Title
    "Telepítés befejez\u0151dött"

    Caption
    "A telepít\u0151 befejezte az <%AppName%> program telepítését a számítógépére."

	Text
	"Kattintson a <%Finish%> gombra a telepítés befejezéséhez."
	
    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Telepítés típusa"

    Caption
    "Válassza ki a kívánt telepítési típust, majd kattintson a <%Next%> gombra!"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Állományok másolásának elkezdése"

    Caption
    "A telepít\u0151nek elég információja van ahhoz, hogy a program állományait\
	elkezdje másolni. Ha meg akarja nézni vagy változtatni a beállításokat,\
	akkor kattintson a <%Back%> gombra. Ha elégedett a beállításokkal, akkor\
	kattintson a <%Next%> gombra, hogy elkezd\u0151djön a fájlok másolása. \
	\n\nJelenlegi beállítások:"

    Text
    "Telepítési könyvtár:\n\
     \t<%InstallDir%>

    Telepítés típusa:\n
     \t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "<%AppName%> eltávolítása"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Title
    "Eltávolítás befejez\u0151dött"

    Caption
    "Az eltávolítás sikeresen befejez\u0151dött."

    FinishButton
    "<%Finish%>"
}

UninstallDetails {
    Title
    "Eltávolítás részletei"

    Caption
    "A következ\u0151 hibák léptek fel az eltávolítás alatt:"

	Errors
    "<%Errors%>"

    FinishButton
    "<%Finish%>"
}


UserInformation {
    Title
    "Felhasználói információk"

    Caption
    "Kérem írja be a nevét és a munkahelyének nevét."

    NameLabel
    "Felhasználó neve:"

    CompanyLabel
    "Cég:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Title
    "Üdvözl\u0151 képerny\u0151"

    Caption
    "Üdvözli a <%AppName%> telepít\u0151je.  Ez program a <%AppName%> programot\
     fogja telepíteni a számítógépére."

    Message
    "Er\u0151sen javasolt, hogy lépjen ki minden futó Windows programból. \
	 Kattintson a <%Next%> gombra, hogy folytassa a telepítést.\n\n\
	 FIGYELMEZTETÉS: Ezt a programot szerz\u0151i jogok és nemzetközi szerz\u0151dések\
	 védik.\n\nEzen program nem engedélyezett gyártása és forgalmazása\
	 polgári büntetést eredményezhet és a törvény teljes erejével sújt le."
	 
    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Classic_Wizard/it.msg.












































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
Background {
    Title
    "Installazione di <%AppName%>"

    Text
    "<%AppName%>"
}

ChooseComponents {
    Title
    "Installazione personalizzata"

    Caption
    "Selezionare le parti che si desidera installare e deselezionare le\
    parti che non si desidera installare."

    ComponentLabel
    "Parti"

    DescriptionLabel
    "Descrizione"

    SpaceRequiredLabel
    "Spazio richiesto: <%SpaceRequiredText%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Copia dei file"

    Caption
    "<%GroupBeingInstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Title
    "Installazione di <%AppName%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


CustomTextPane1 {
    Title
    "Titolo"

    Caption
    "Didascalia"

    Message
    "Messaggio"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane2 {
    Title
    "Installazione di <%AppName%>"

    Caption
    "Didascalia"

    Text
    "Il testo va qui."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane3 {
    Title
    "Titolo"

    Caption
    "Didascalia"

    Message
    "Messaggio"

    Text
    "Il testo va qui."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

License {
    Title
    "Contratto di Licenza d'uso"

    Caption
    "Si prega di leggere il Contratto di Licenza d'uso che segue.  Premere\
    il tasto PAGINA GIU' per vedere il resto del contratto."

    Message
    "Si accettano tutte le condizioni del Contratto di Licenza riportato?\
    Se si sceglie No, il programma di installazione sarà terminato. Per\
    installare <%AppName%>, è necessario accettare il presente contratto."

    Text
    "Inserire qui il contratto di licenza."

    AcceptCheck
    "Accetto le condizioni del contratto di licenza."

    NextButton
    "Sì"

    BackButton
    "< <%Back%>"

    CancelButton
    "No"
}

Readme {
    Title
    "Informazioni da leggere"

    Text
    "Inserire qui le informazioni da leggere."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Selezionare la directory di destinazione"

    Caption
    "Il programma di installazione sta per installare <%AppName%>\
     nella seguente cartella.\n\nPer installare in questa cartella, premere su Avanti.\n\nPer installare in una cartella diversa, premere su Sfoglia\
     e selezionare un'altra cartella.\n\nSi può scegliere di non installare\
     <%AppName%> premendo su Annulla per uscire dal programma di installazione."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Cartella di destinazione"
}

SelectProgramFolder {
    Title
    "Selezionare la cartella del programma"

    Caption
    "Il programma di installazione aggiungerà le icone del programma nella\
     cartella elencata sotto. Si può inserire il nome di una nuova\
     cartella o selezionarla dalla lista delle cartelle esistenti. Premere\
     su Avanti per proseguire."

    ProgramFolderLabel
    "Cartella del programma:"

    FolderListLabel
    "Cartelle esistenti:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Crea la cartella del programma per tutti gli utenti"
}

Setup {
    Title
    "Installazione"

    Caption
    "Il programma di installazione sta preparando l'autocomposizione di\
     InstallJammer che seguirà l'utente nel restante processo di\
     installazione. Si prega di attendere."
}

SetupComplete {
    Title
    "Installazione completata"

    Caption
    "Il programma ha concluso l'installazione di <%AppName%> sul computer."

    Text
    "Premere su Fine per completare l'installazione."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Tipologia di installazione"

    Caption
    "Selezionare la tipologia di installazione che si preferisce, poi\
     premere su Avanti."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Inizio della copia dei file"

    Caption
    "Il programma di installazione dispone di sufficienti informazioni per\
     iniziare la copia dei file del programma. Se si desidera controllare\
     o modificare le impostazioni, premere su Indietro. Se si è soddisfatti\
     delle impostazioni, premere su Avanti per iniziare a copiare i file\
     \n\nImpostazioni correnti:"

    Text
    "Directory di installazione:\n\
     \t<%InstallDir%>

    Tipologia di installazione:\n\
    \t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Disinstallazione <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Title
    "Disinstallazione completata"

    Caption
    "Disinstallazione completata con successo."

    FinishButton
    "<%Finish%>"
}

UninstallDetails {
    Title
    "Dettagli della disinstallazione"

    Caption
    "Durante la disinstallazione sono occorsi i seguenti errori:"

    Errors
    "<%Errors%>"

    FinishButton
    "<%Finish%>"
}


UserInformation {
    Title
    "Informazioni sull'utente"

    Caption
    "Inserire di seguito il proprio nome e la società per cui si lavora."

    NameLabel
    "Nome:"

    CompanyLabel
    "Società:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Welcome {
    Title
    "Schermata di benvenuto"

    Caption
    "Benvenuti nel programma di installazione di <%AppName%>. Il programma\
     installerà <%AppName%> sul computer."

    Message
    "E' vivamente consigliata l'uscita da tutti i programmi Windows che\
     sono in esecuzione. Premere su Avanti per proseguire con il programma\
     di installazione.\n\nATTENZIONE:\
     Questo programma è protetto dalla legge sul diritto d'autore e dai\
     trattati internazionali. \
     \n\nLa riproduzione o distribuzione non autorizzata del programma,\
     o di parte di esso, può comportare gravi sanzioni civili e penali,\
     e sarà perseguita fino al massimo livello consentito dalla legge."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Classic_Wizard/lt.msg.






























































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
Background {
    Title
    "<%AppName%> ádiegimo programa"

    Text
    "<%AppName%>"
}

ChooseComponents {
    Title
    "Pasirenkamasis ádiegimas"

    Caption
    "Paþymëkite komponentus kuriuos norite ádiegti ir atþymëkite\
     tuos kuriuos nenorite ádiegti."

    ComponentLabel
    "Komponentai"

    DescriptionLabel
    "Apraðymas"

    SpaceRequiredLabel
    "Reikalinga talpa: <%SpaceRequiredText%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Kopijuojami failai"

    Caption
    "<%GroupBeingInstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Title
    "<%AppName%> diegimo programa"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


CustomTextPane1 {
    Title
    "Antraðtë"

    Caption
    "Pavadinimas"

    Message
    "Praneðimas"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane2 {
    Title
    "<%AppName%> diegimo programa"

    Caption
    "Antraðtë"

    Text
    "Èia ávedamas tekstas."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane3 {
    Title
    "Antraðtë"

    Caption
    "Pavadinimas"

    Message
    "Praneðimas"

    Text
    "Èia ávedamas tekstas."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

License {
    Title
    "Sutikimas su licencija"

    Caption
    "Praðom perskaityti ðá sutikimà su licencija. Spauskite PAGE DOWN klaviðà\
     tam kad perþiûrëtumëte visà susitarimà."

    Message
    "Ar jûs sutinkate su licensija? Jei pasirinksite Ne, diegimo programa\
	uþsidarys. Tam kad ádiegti <%AppName%>, jûs privalote sutikti su\
	licencija"

    Text
    "Patalpinkite èia savo licencijà."

    AcceptCheck
    "Að sutinku su licencija."

    NextButton
    "Taip"

    BackButton
    "< <%Back%>"

    CancelButton
    "Ne"
}

Readme {
    Title
    "Skaityti daugiau informacijos"

    Text
    "Patalpinkite informacija."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Pasirinkite paskirties vietà"

    Caption
    "Diegimo programa ádiegs <%AppName%> á ðá katalogà.\n\nTam kad instaliuoti\
     á ðá katalogà, paspauskite <%Next%>.\n\nÁdiegimui á kita katalogà,\
     paspauskite <%Browse%> ir pasirinkite kità katalogà.\n\nTam kad nutraukti\
     <%AppName%> programos diegimà spauskite <%Cancel%>."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Paskirties katalogas"
}

SelectProgramFolder {
    Title
    "Pasirinkite programos katalogà"

    Caption
    "Diegimo programa ákels programos ikonas á programø katalogà pavaizduotà\
     apaèioje.  Galite ávesti naujà katalogo pavadinimà arba pasirinkti ið\
     esanèiø.  Norëdami tæsti <%Next%>."

    ProgramFolderLabel
    "Programos katalogas:"

    FolderListLabel
    "Esantys katalogai:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Sukurti programos katalogus visiems vartotojams"
}

Setup {
    Title
    "Diegimo programa"

    Caption
    "Diegimo programa ruoðia InstallJammer vedlá, kuris jus ves\
     per diegimo prosesà. Praðom palaukti."
}

SetupComplete {
    Title
    "Diegimas baigtas"

    Caption
    "Diegimo programa baigë diegti <%AppName%> á jûsø kompiuterá."

    Text
    "Paspauskite <%Finish%>, kad uþbaigti diegimà."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Diegimo tipas"

    Caption
    "Pasirinkite diegimo tipà, tada spauskite <%Next%>."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Pradedamas failø kopijavimas"

    Caption
    "Diegimo programa turi pakankamai informacijos, kad pradëti kopijuoti
     programos failus.  Jei norite perþiûrëti arba pakeisti nustatymus,\
     spauskite <%Back%>. Jei nustatymai tenkina, spauskite <%Next%>, kad\
     pradëti kopijuoti failus.\n\nDabartiniai nustatymai:"

    Text
    "Diegimo katalogas:\n\
     \t<%InstallDir%>

    Diegimo tipas:\n\
    \t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Paðalinti <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Title
    "Programos paðalinimas baigtas"

    Caption
    "Programos paðalinimas sëkmingai atliktas."

    FinishButton
    "<%Finish%>"
}

UninstallDetails {
    Title
    "Programos paðalinimas iðsamiau"

    Caption
    "Klaidos atsitikusios per programos paðalinimà:"

    Errors
    "<%Errors%>"

    FinishButton
    "<%Finish%>"
}


UserInformation {
    Title
    "Vartotojo informacija"

    Caption
    "Áveskite savo vardà ir organizacijà kurioje dirbate."

    NameLabel
    "Vardas:"

    CompanyLabel
    "Organizacija:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Welcome {
    Title
    "Pasveikinimo ekranas"

    Caption
    "Sveiki atvyke á <%AppName%> diegimo programà. Ði programa ádiegs\
     <%AppName%> á jûsø kompiuterá."

    Message
    "Pabrëþtinai patartina iðeiti ið visø Windows programø kurias esate\
     pasileidæ. Spauskite <%Next%> tam, kad tæsti diegimà.\n\nDËMESIO:\
     Ði programa yra saugoma autoriniø teisiø ir tarptautiniais ástatymais.\
     \n\nNelegalus ðios programos kopijavimas arba platinimas, baudþiamas\
     pagal civilinës ir nusikalstamos veiklos ástatymus."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Classic_Wizard/nl.msg.






















































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
Background {
    Title
    "<%AppName%> Setup"

    Text
    "<%AppName%>"
}

ChooseComponents {
    Title
    "Custom Setup"

    Caption
    "Selecteer de componenten die u wilt installeren en deselecteer de componenten\
     die u niet wilt installeren."

    ComponentLabel
    "Componenten"

    DescriptionLabel
    "Omschrijving"

    SpaceRequiredLabel
    "Benodigde ruimte: <%SpaceRequiredText%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Bestanden kopiëren "

    Caption
    "<%GroupBeingInstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Title
    "<%AppName%> Setup"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


CustomTextPane1 {
    Title
    "Titel"

    Caption
    "Bijschrift"

    Message
    "Bericht"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane2 {
    Title
    "<%AppName%> Setup"

    Caption
    "Bijschrift"

    Text
    "Tekst gaat hier."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane3 {
    Title
    "Titel"

    Caption
    "Bijschrift"

    Message
    "Bericht"

    Text
    "Tekst gaat hier."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

License {
    Title
    "Licentie Overeenkomst"

    Caption
    "Lees de licentie overeenkomst aandachtig.  Gebruik de PAGE DOWN toets\
     om de rest van de overeenkomst te zien."

    Message
    "Gaat u akkoord met de licentie overeenkomst?  Als u Nee kiest zal\
     de installatie worden afgebroken.  Om <%AppName%> te installeren, moet\
     u akkoord gaan."

    Text
    "De licentie overeenkomst kunt u hier plaatsen."

    AcceptCheck
    "Ik ga akkoord met de licentie overeenkomst."

    NextButton
    "Ja"

    BackButton
    "< <%Back%>"

    CancelButton
    "Stop Installatie"
}

Readme {
    Title
    "Readme Informatie"

    Text
    "Plaats uw readme informatie hier."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Kies de installatie map"

    Caption
    "Dit installatie programma zal <%AppName%> in de onderstaande map installeren.\n\n
     Als u de installatie locatie wilt wijzigen klikt u op 'Selecteer map' en selecteert u een nieuwe locatie.
     Om verder te gaan met het installatieproces klikt u op Volgende."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Installatie map"
}

SelectProgramFolder {
    Title
    "Selecteer Programma Map"

    Caption
    "Het installatie programma zal de programma iconen toevoegen aan de onderstaande Programma map. \
     U kunt een nieuwe map aanmaken of een bestaande map selecteren uit de lijst. \
     Klik op Volgende om door te gaan."

    ProgramFolderLabel
    "Programma map:"

    FolderListLabel
    "Huidige mappen:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Maak programma map voor alle gebruikers"
}

Setup {
    Title
    "Setup"

    Caption
    "Setup is de wizard aan het voorbereiden die u door de rest van het proces begeleid. Een ogenblik geduld."
}

SetupComplete {
    Title
    "Setup Afgerond"

    Caption
    "Setup is klaar met het installeren van <%AppName%> op uw computer."

    Text
    "Klik op <%Finish%> om de installatie af te ronden."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Setup Type"

    Caption
    "Kies het type setup dat u prefereerd, klik daarna op Volgende."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Start Kopiëren Bestanden"

    Caption
    "Het installatie programma heeft genoeg informatie om het kopiëren te starten. \
     Als u de instellingen wilt bekijken of wijzigen kunt op <%Back%> klikken.  Als u\
     tevreden bent met de instellingen klikt u op <%Next%> om het kopiëren te starten. \
     \n\nHuidige instellingen:"

    Text
    "Installatie map:\n\
     \t<%InstallDir%>

    Setup type:\n\
    \t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "<%AppName%> deïnstalleren"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Title
    "Deïnstallatie Afgerond"

    Caption
    "Deïnstallatie succesvol afgerond."

    FinishButton
    "<%Finish%>"
}

UninstallDetails {
    Title
    "Deïnstallatie Details"

    Caption
    "De volgende fouten hebben zicht voorgedaan tijdens de deïnstallatie:"

    Errors
    "<%Errors%>"

    FinishButton
    "<%Finish%>"
}


UserInformation {
    Title
    "Gebruikers Informatie"

    Caption
    "Vul uw naam en uw bedrijfsnaam in."

    NameLabel
    "Naam:"

    CompanyLabel
    "Bedrijfsnaam:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Welcome {
    Title
    "Welkomst Scherm"

    Caption
    "Welkom bij het <%AppName%> installatie programma.  Dit programma zal\
     <%AppName%> op uw computer installeren."

    Message
    "Het is aan te raden alle overige applicaties te sluiten alvorens\
     verder te gaan met deze installatie.\n\nKlik op <%Next%> om verder\
     te gaan of op <%Cancel%> om deze installatie af te breken"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Classic_Wizard/pt_br.msg.






























































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
Background {
    Title
    "Instalação do <%AppName%>"

    Text
    "<%AppName%>"
}

ChooseComponents {
    Title
    "Instalação Customizada"

    Caption
    "Selecione os componentes que você quer instalar e deselecione os componentes\
     que você não quer instalar."

    ComponentLabel
    "Componentes"

    DescriptionLabel
    "Descrição"

    SpaceRequiredLabel
    "Espaço necessário: <%SpaceRequiredText%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Copiando arquivos"

    Caption
    "<%GroupBeingInstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Title
    "Instalação do <%AppName%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


CustomTextPane1 {
    Title
    "Título"

    Caption
    "Caption"

    Message
    "Mensagem"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane2 {
    Title
    "Instalação do <%AppName%>"

    Caption
    "Caption"

    Text
    "Texto aparecerá aqui."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane3 {
    Title
    "Título"

    Caption
    "Caption"

    Message
    "Mensagem"

    Text
    "Texto aparecerá aqui."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

License {
    Title
    "Concordância com a Licença"

    Caption
    "Por favor, leia a Concordância com a Licença.  Pressione PAGEDOWN\
     para visualizar o resto da licença."

    Message
    "Você aceita todos os termos da Licença?  Se\
     você escolher Não, A instalação será Cancelada.  Para instalar <%AppName%>, você precisa\
     aceitar todos os termos da Licença."

    Text
    "Coloque a sua Concordância com a Licença aqui."

    AcceptCheck
    "Eu aceito todos os termos desta Licença."

    NextButton
    "Sim"

    BackButton
    "< <%Back%>"

    CancelButton
    "Não"
}

Readme {
    Title
    "Informação do Readme"

    Text
    "Coloque as informações do seu Readme aqui."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Selecione a localização de destino"

    Caption
    "O Instalador irá instalar <%AppName%> Na seguinte pasta.\n\nPara instalar\
     nesta pasta, clique em Próximo.\n\nPara instalar em uma pasta diferente, clique\
     Navegar e selecione outra pasta.\n\nVocê pode cancelar a Instalação do\
     <%AppName%> clicando em Cancelar e o Instalador será finalizado."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Pasta de destino"
}

SelectProgramFolder {
    Title
    "Selecionar a pasta de Programas"

    Caption
    "Setup will add the program icons to the Program Folder listed below. \
     You may type a new folder name or select from the existing folders list. \
     Click Next to continue."

    ProgramFolderLabel
    "Pasta de Programas:"

    FolderListLabel
    "Pastas Existentes:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Criar uma pasta de programa para todos os usuários"
}

Setup {
    Title
    "Instalação"

    Caption
    "A Instalação está preparando o Assistente do InstallJammer que irá te guiar através do\
     processo de instalação.  Por favor aguarde."
}

SetupComplete {
    Title
    "Instalação Concluída"

    Caption
    "O Instalador concluiu a instalação do <%AppName%> em seu computador."

    Text
    "Clique em Concluir para finalizar a Instalação."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Setup Type"

    Caption
    "Click the type of Setup you prefer, then click Next."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Start Copying Files"

    Caption
    "Setup has enough information to start copying the program files.  If\
     you want to review or change any settings, click Back.  If you are\
     satisfied with the settings, click Next to begin copying files. \
     \n\nCurrent Settings:"

    Text
    "Install Directory:\n\
     \t<%InstallDir%>

    Setup Type:\n\
    \t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Desinstalar <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Title
    "Desinstalação Concluída"

    Caption
    "Desinstalação Concluída com Sucesso."

    FinishButton
    "<%Finish%>"
}

UninstallDetails {
    Title
    "Detalhes de Desintalação"

    Caption
    "Os seguintes erros ocorreram durante a deinstalação:"

    Errors
    "<%Errors%>"

    FinishButton
    "<%Finish%>"
}


UserInformation {
    Title
    "Informação do Usuário"

    Caption
    "Digite seu nome e a empresa onde você trabalha."

    NameLabel
    "Nome:"

    CompanyLabel
    "Empresa:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Welcome {
    Title
    "Tela de Boas Vindas"

    Caption
    "Bem vido ao programa de Instalação do <%AppName%>.  Este programa irá instalar\
     <%AppName%> em seu computador."

    Message
    "É fortemente recomendado que você feche todos os programas do Windows que você\
     esteja executando.  Clique em Próximo para continuar o programa de Instalação.\n\nAdvertência:\
     Este programa é protegido por leis de Copyright e tratados Internacionais. \n\n
     A cópia não autorizada ou a distribuição deste programa, or qualquer parte deste,\
     poderá resultar em severas penalidades cívis e criminais e será processado dentro da leis aplicáveis."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Classic_Wizard/theme.cfg.


























>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
Name    "Classic Wizard"
Version 1
Width   475
Height  350
Buttons {
    Back/Next/Cancel
    Back/Next
    Back/Cancel
    Next/Cancel
    Back
    Next
    Cancel
}
Added Themes/Classic_Wizard/theme.tcl.


























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::InstallJammer::theme::NewProject { arrayName } {
    upvar 1 $arrayName vars

    set map {"<%FileBeingInstalled%>" "<%Tail <%FileBeingInstalled%>%>"}
    foreach lang [::InstallJammer::GetLanguageCodes] {
        ::msgcat::mcset $lang FileBeingInstalledText \
            [string map $map [::msgcat::mcget $lang FileBeingInstalledText]]
    }

    if {$vars(includeCustomSetup)} {
        ::InstallJammer::AddPane Install ChooseComponents \
            -parent StandardInstall -index 3
        ::InstallJammer::AddPane Install SetupType \
            -parent StandardInstall -index 3
    }

    foreach pane [GetPaneComponentList] {
        if {[$pane component] ne "SetupComplete"} { continue }

        set y 100
        if {$vars(ViewReadmeCheckbutton)} {
            set act [::InstallJammer::AddAction Install AddWidget \
                -parent $pane -title "View Readme Checkbutton"]
            $act set Type checkbutton X 150 Y $y Background system \
                VirtualText ViewReadme
            $act title "View Readme Checkbutton"
            ::InstallJammer::SetVirtualText en $act Text "<%ViewReadmeText%>"

            set con [::InstallJammer::AddCondition FileExistsCondition \
                -parent $act]
            $con set Filename "<%ProgramReadme%>"

            set con [::InstallJammer::AddCondition StringIsCondition \
                -parent $act]
            $con set Operator false
            $con set String "<%InstallStopped%>"
        }

        if {$vars(LaunchAppCheckbutton)} {
            incr y 20
            set act [::InstallJammer::AddAction Install AddWidget \
                -parent $pane -title "Launch Application Checkbutton"]
            $act set Type checkbutton X 150 Y $y Background system \
                VirtualText LaunchApplication
            $act title "Launch Application Checkbutton"
            ::InstallJammer::SetVirtualText en $act \
                Text "<%LaunchApplicationText%>"

            set con [::InstallJammer::AddCondition FileExistsCondition \
                -parent $act]
            $con set Filename "<%ProgramExecutable%>"

            set con [::InstallJammer::AddCondition StringIsCondition \
                -parent $act]
            $con set Operator false
            $con set String "<%InstallStopped%>"
        }

        if {$vars(DesktopShortcutCheckbutton)} {
            incr y 20
            set act [::InstallJammer::AddAction Install AddWidget \
                -parent $pane -title "Desktop Shortcut Checkbutton"]
            $act set Type checkbutton X 150 Y $y Background system \
                VirtualText CreateDesktopShortcut
            ::InstallJammer::SetVirtualText en $act \
                Text "<%CreateDesktopShortcutText%>"

            set con [::InstallJammer::AddCondition FileExistsCondition \
                -parent $act]
            $con set Filename "<%ProgramExecutable%>"

            set con [::InstallJammer::AddCondition StringIsCondition \
                -parent $act]
            $con set Operator false
            $con set String "<%InstallStopped%>"
        }

        if {$vars(QuickLaunchShortcutCheckbutton)} {
            incr y 20
            set act [::InstallJammer::AddAction Install AddWidget \
                -parent $pane -title "Quick Launch Shortcut Checkbutton"]
            $act set Type checkbutton X 150 Y $y Background system \
                VirtualText CreateQuickLaunchShortcut
            ::InstallJammer::SetVirtualText en $act Text \
                "<%CreateQuickLaunchShortcutText%>"
                
            set con [::InstallJammer::AddCondition PlatformCondition \
                -parent $act]
            $con set Operator "is"
            $con set Platform "Windows"

            set con [::InstallJammer::AddCondition FileExistsCondition \
                -parent $act]
            $con set Filename "<%ProgramExecutable%>"

            set con [::InstallJammer::AddCondition StringIsCondition \
                -parent $act]
            $con set Operator false
            $con set String "<%InstallStopped%>"
        }
    }
}
Added Themes/Modern_Wizard/Common/CustomBlankPane1.pane.












































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane CustomBlankPane1 "Custom Blank Pane 1"

Order 100

Property Active  boolean "Active"  "No"
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Image   image   "Image"   "<%Image%>"

Property WizardOptions hidden "Wizard Options" [list -bg #FFFFFF -separator 0]

Text Caption
Text Message
Text BackButton   "Back Button"   1
Text NextButton   "Next Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Modern_Wizard/Common/CustomBlankPane1.tcl.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.CustomBlankPane1 { wizard id } {
    global _FG
    global _BG
    set base [$wizard widget get $id]

    grid rowconfigure    $base 1 -weight 1
    grid columnconfigure $base 1 -weight 1

    label $base.image -borderwidth 0 -background $_BG -foreground $_FG
    grid  $base.image -row 0 -column 0 -rowspan 2 -sticky nw
    $id widget set Image -type image -widget $base.image

    Label $base.title -height 3 -bg $_BG -foreground $_FG -font TkCaptionFont \
        -autowrap 1 -anchor nw -justify left
    grid $base.title -row 0 -column 1 -sticky ew -padx 20 -pady [list 20 10]
    $id widget set Caption -type text -widget $base.title

    Label $base.message -bg $_BG -foreground $_FG -autowrap 1 -anchor nw -justify left
    grid  $base.message -row 1 -column 1 -sticky news -padx 20
    $id widget set Message -type text -widget $base.message

    Separator $base.sep -orient horizontal
    grid $base.sep -row 2 -column 0 -columnspan 2 -sticky ew
}
Added Themes/Modern_Wizard/Common/CustomBlankPane2.pane.












































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane CustomBlankPane2 "Custom Blank Pane 2"

Order 101

Property Active  boolean "Active"  "No"
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon    image   "Icon"    "<%Icon%>"

Text Title
Text Subtitle
Text Caption
Text Message
Text NextButton   "Next Button"        1
Text BackButton   "Back Button"        1
Text CancelButton "Cancel Button"      1
Added Themes/Modern_Wizard/Common/CustomBlankPane2.tcl.












































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.CustomBlankPane2 { wizard id } {
    global _FG
    global _BG
    set base  [$wizard widget get $id]
    set frame $base.titleframe

    grid rowconfigure    $base 3 -weight 1
    grid columnconfigure $base 0 -weight 1

    frame $frame -bd 0 -relief flat -background $_BG
    grid  $frame -row 0 -column 0 -sticky nsew

    grid rowconfigure    $frame 1 -weight 1
    grid columnconfigure $frame 0 -weight 1

    Label $frame.title -background $_BG -foreground $_FG -anchor nw -justify left \
        -autowrap 1 -font TkCaptionFont \
        -textvariable [$wizard variable $id -text1]
    grid $frame.title -row 0 -column 0 -sticky new -padx 5 -pady 5
    $id widget set Title -widget $frame.title

    Label $frame.subtitle -background $_BG -foreground $_FG -anchor nw -autowrap 1 \
        -justify left -textvariable [$wizard variable $id -text2]
    grid $frame.subtitle -row 1 -column 0 -sticky new -padx [list 20 5]
    $id widget set Subtitle -widget $frame.subtitle

    label $frame.icon -borderwidth 0 -background $_BG -foreground $_FG -anchor c
    grid  $frame.icon -row 0 -column 1 -rowspan 2
    $id widget set Icon -widget $frame.icon -type image

    Separator $base.separator -relief groove -orient horizontal
    grid $base.separator -row 1 -column 0 -sticky ew 

    Label $base.caption -anchor nw -justify left -autowrap 1 \
        -textvariable [$wizard variable $id -text3] -background $_BG -foreground $_FG
    grid $base.caption -row 2 -sticky nsew -padx 8 -pady [list 8 4]
    $id widget set Caption -widget $base.caption

    frame $base.clientarea -background $_BG
    grid  $base.clientarea -row 3 -sticky nsew -padx 8 -pady 4
    $id widget set ClientArea -widget $base.clientarea -type frame

    Label $base.message -anchor nw -justify left -autowrap 1 \
        -textvariable [$wizard variable $id -text4] -background $_BG -foreground $_FG
    grid $base.message -row 4 -sticky nsew -padx 8 -pady [list 4 8]
    $id widget set Message -widget $base.message
}
Added Themes/Modern_Wizard/Common/CustomTextPane1.pane.




















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane CustomTextPane1 "Custom Text Pane 1"

Order 102

Include CustomBlankPane2

Property Active boolean "Active" No
Property Icon image "Icon" "<%Icon%>"
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property TextFont font "Text Font" "TkTextFont"

Text Title
Text Subtitle
Text Caption
Text Message
Text Text
Text NextButton   "Next Button"        1
Text BackButton   "Back Button"        1
Text CancelButton "Cancel Button"      1
Added Themes/Modern_Wizard/Common/CustomTextPane1.tcl.
















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.CustomTextPane1 { wizard id } {
    global _FG
    global _BG
    CreateWindow.CustomBlankPane2 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 0 -weight 1

    frame $base.frame
    grid  $base.frame -row 0 -column 0 -sticky news
    
    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 0 -weight 1

    if {![$id get TextFont font]} { set font TkTextFont }

    Text $base.frame.text \
        -state readonly -bg $_BG -foreground $_FG -font $font\
        -wrap word -highlightthickness 0 \
	-yscrollcommand "$base.frame.vs set" \
	-xscrollcommand "$base.frame.hs set"
    grid $base.frame.text -row 0 -column 0 -sticky news
    $id widget set Text -widget $base.frame.text

    ttk::scrollbar $base.frame.vs -command "$base.frame.text yview"
    grid $base.frame.vs -row 0 -column 1 -sticky ns

    ttk::scrollbar $base.frame.hs -command "$base.frame.text xview" \
        -orient horizontal
    grid $base.frame.hs -row 1 -column 0 -sticky ew
}
Added Themes/Modern_Wizard/Common/defaults.tcl.


















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

SafeSet info(Icon)  "Modern/Small/SetupModernSmall01.gif"
SafeSet info(Image) "Modern/SetupModern01.gif"
Added Themes/Modern_Wizard/Common/setup.tcl.


































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::ThemeSetup {} {

    global _FG
    global _BG
    set _FG [style default . -foreground]
    set _BG [style default . -background]

    option add *font  TkTextFont

    if {$::tcl_platform(platform) ne "windows"} {
       	option add *background          $_BG
       	option add *foreground          $_FG
       	option add *selectForeground    [style default . -selectforeground]
       	option add *selectBackground    [style default . -selectbackground]

       	option add *Listbox.background  $_BG
       	option add *Listbox.foreground  $_FG

       	option add *Entry.background    $_BG
       	option add *Entry.foreground    $_FG
       	option add *Entry.borderWidth   1

       	option add *Text.background     $_BG
       	option add *Text.foreground     $_FG
    }
}
Added Themes/Modern_Wizard/Common/utils.tcl.


































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc RaiseStep { wizard id } {
    set widget [$id widget get Caption]
    if {$widget ne ""} {
        if {![string length [::InstallJammer::GetText $id Caption]]} {
            grid remove $widget
        } else {
            grid $widget
        }
    }

    set widget [$id widget get Message]
    if {$widget ne ""} {
        if {![string length [::InstallJammer::GetText $id Message]]} {
            grid remove $widget
        } else {
            grid $widget
        }
    }

    set widget [$id widget get ClientArea]
    if {$widget ne ""} {
        grid configure $wizard.buttons -pady {18 5}
    } else {
        grid configure $wizard.buttons -pady 5
    }
}
Added Themes/Modern_Wizard/Install/ChooseComponents.pane.




























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane ChooseComponents "Choose Components"

Order 10

Include CustomBlankPane2

Condition StringEqualCondition \
    String1 "<%InstallType%>" Operation "equals" String2 "Custom"

Property Active boolean "Active" No
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon image "Icon" "<%Icon%>"

Action PopulateComponents ExecuteAction "Before Pane is Displayed"

Text Title
Text Subtitle
Text Caption
Text Message
Text DescriptionLabel "Description Label" 0
Text NextButton       "Next Button"       1
Text BackButton       "Back Button"       1
Text CancelButton     "Cancel Button"     1
Added Themes/Modern_Wizard/Install/ChooseComponents.tcl.






































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.ChooseComponents { wizard id } {
    CreateWindow.CustomBlankPane2 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 0 -weight 1

    ScrolledWindow $base.sw
    grid $base.sw -row 0 -column 0 -sticky news -pady [list 4 0]

    set tree [OptionTree $base.tree -bd 2 -relief sunken \
        -background #FFFFFF -highlightthickness 0 -toggleselect 0]
    $base.sw setwidget $tree
    $id widget set ComponentTree -widget $tree -type tree

    labelframe $base.frame -relief groove -bd 2
    grid $base.frame -row 0 -column 1 -sticky news \
        -padx [list 10 0]
    $id widget set DescriptionLabel -widget $base.frame

    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 0 -weight 1

    Label $base.frame.desc -width 25 -autowrap 1 -anchor nw -justify left
    grid $base.frame.desc -row 0 -column 0 -sticky news -padx 10 -pady 5
    $id widget set DescriptionText -widget $base.frame.desc
}
Added Themes/Modern_Wizard/Install/CopyFiles.pane.


































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane CopyFiles "Copying Files"

Order 13

Include CustomBlankPane2

InstallTypes Standard Default

Action ModifyWidget <Title> "Disable Buttons" \
    State "disabled" Widget "Back Button;Next Button" \
    ExecuteAction "Before Pane is Displayed"
Action ExecuteAction Action "Install Actions" <Title> "Install Everything"
Action MoveForward

Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon image "Icon" "<%Icon%>"

Text Title
Text Subtitle
Text Caption
Text Message
Text FileLabel     "File Label"     1
Text ProgressValue "Progress Value" 1
Text NextButton    "Next Button"    1
Text BackButton    "Back Button"    1
Text CancelButton  "Cancel Button"  1
Added Themes/Modern_Wizard/Install/CopyFiles.tcl.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.CopyFiles { wizard id } {
    CreateWindow.CustomBlankPane2 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 0 -weight 1

    set frame [frame $base.frame]
    grid $frame -row 0 -column 0 -sticky new

    grid rowconfigure    $frame 1 -weight 1
    grid columnconfigure $frame 0 -weight 1

    Label $frame.file -anchor w -elide 1 -ellipsis {[...]} -elideside center
    grid  $frame.file -row 0 -column 0 -sticky new -padx [list 0 10]
    $id widget set FileLabel -widget $frame.file

    ttk::progressbar $frame.progress
    grid $frame.progress -row 1 -column 0 -sticky ew
    $id widget set ProgressValue -widget $frame.progress -type progress
}
Added Themes/Modern_Wizard/Install/InstallPassword.pane.














































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane InstallPassword "Install Password"

Order 20

Include CustomBlankPane2

Property Active boolean "Active" "No"
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon image "Icon" "<%Icon%>"
Property HidePassword boolean "Hide Password" "No"

Property VirtualText short "Virtual Text" "InstallPassword"
Help VirtualText "The virtual text to attach to the password entry"

Condition PasswordTestCondition \
    CheckCondition      "Before Next Pane is Displayed" \
    FailureFocus        "Password Entry" \
    FailureMessage      "<%PasswordIncorrectText%>" \
    EncryptedPassword   "<%InstallPasswordEncrypted%>" \
    UnencryptedPassword "<%InstallPassword%>"

Action SetInstallPassword \
    ExecuteAction "Before Next Pane is Displayed" \
    Password      "<%InstallPassword%>"

Text Title
Text Subtitle
Text Caption
Text Message
Text NextButton    "Next Button"     1
Text BackButton    "Back Button"     1
Text CancelButton  "Cancel Button"   1
Added Themes/Modern_Wizard/Install/InstallPassword.tcl.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.InstallPassword { wizard id } {
    CreateWindow.CustomBlankPane2 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 0 -weight 1

    set frame [frame $base.frame]
    grid $frame -row 0 -column 0 -sticky new -padx 10

    grid rowconfigure    $frame 0 -weight 1
    grid columnconfigure $frame 0 -weight 1

    ttk::entry $frame.passwordE -textvariable ::info([$id get VirtualText])
    grid $frame.passwordE -row 0 -column 0 -sticky new
    $id widget set PasswordEntry -widget $frame.passwordE -type entry

    if {[$id get HidePassword]} {
        $frame.passwordE configure -show *
    }
}
Added Themes/Modern_Wizard/Install/License.pane.




































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane License "License Agreement"

Order 5

Include CustomTextPane1

Property Active boolean "Active" No
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon image "Icon" "<%Icon%>"
Property UserMustAcceptLicense boolean "User Must Accept License" Yes

Action ModifyWidget Widget "NextButton" State "disabled" \
    ExecuteAction "Before Pane is Displayed"
Condition StringIsCondition String \
  {<%Property <%CurrentPane%> UserMustAcceptLicense%>}
Condition StringIsCondition Operator "false" String "<%LicenseAccepted%>"

Text Title
Text Subtitle
Text Caption
Text Message
Text Text                "License Contents"
Text AcceptRadiobutton   "Accept Radiobutton"  0
Text DeclineRadiobutton  "Decline Radiobutton" 0
Text NextButton          "Next Button"         1
Text BackButton          "Back Button"         1
Text CancelButton        "Cancel Button"       1
Added Themes/Modern_Wizard/Install/License.tcl.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.License { wizard id } {
    CreateWindow.CustomTextPane1 $wizard $id

    if {![$id get UserMustAcceptLicense]} { return }

    set base [$id widget get ClientArea]

    ttk::radiobutton $base.accept -variable ::info(LicenseAccepted) -value 1 \
        -command [list $wizard itemconfigure next -state normal]
    grid $base.accept -row 1 -column 0 -sticky w
    $id widget set AcceptRadiobutton -widget $base.accept

    ttk::radiobutton $base.decline -variable ::info(LicenseAccepted) -value 0 \
        -command [list $wizard itemconfigure next -state disabled]
    grid $base.decline -row 2 -column 0 -sticky w
    $id widget set DeclineRadiobutton -widget $base.decline
}
Added Themes/Modern_Wizard/Install/Readme.pane.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane Readme "Readme Information"

Order 6

Include CustomTextPane1

Property Active boolean "Active" No
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon image "Icon" "<%Icon%>"

Text Title
Text Subtitle
Text Caption
Text Message
Text Text         "Readme Contents"
Text NextButton   "Next Button"        1
Text BackButton   "Back Button"        1
Text CancelButton "Cancel Button"      1
Added Themes/Modern_Wizard/Install/Readme.tcl.




















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.Readme { wizard id } {
    CreateWindow.CustomTextPane1 $wizard $id
}
Added Themes/Modern_Wizard/Install/SelectDestination.pane.














































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane SelectDestination "Select Destination"

Order 8

Include CustomBlankPane2

Condition ScriptCondition CheckCondition "Before Pane is Displayed" \
    Comment "Do not display this pane if this is an upgrade install\
                unless there is more than one installation present" \
    Script "!<%UpgradeInstall%> || <%PreviousInstallCount%> != 1"

Condition FilePermissionCondition Filename {<%InstallDir%>} \
    CheckCondition "Before Next Pane is Displayed" Permission "can create" \
    FailureMessage "<%DirectoryPermissionText%>"

Property Buttons buttons "Buttons" "Back/Next/Cancel"

Property Icon image "Icon" "<%Icon%>"

Property VirtualText short "Virtual Text" "InstallDir"

Text Title
Text Subtitle
Text Caption
Text Message
Text Destination
Text BrowseText   "Browse Text"
Text NextButton   "Next Button"   1
Text BackButton   "Back Button"   1
Text CancelButton "Cancel Button" 1
Text BrowseButton "Browse Button" 1
Text DestinationLabel "Destination Label" 0
Added Themes/Modern_Wizard/Install/SelectDestination.tcl.














































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.SelectDestination { wizard id } {
    variable info

    CreateWindow.CustomBlankPane2 $wizard $id

    set base [$id widget get ClientArea]

    set varName [$id get VirtualText]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 0 -weight 1

    labelframe $base.frame -relief groove -bd 2
    grid $base.frame -row 0 -column 0 -sticky sew
    $id widget set DestinationLabel -widget $base.frame

    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 0 -weight 1

    Label $base.frame.destination -anchor nw -elide 1 -elideside center \
        -ellipsis {[...]}
    grid  $base.frame.destination -row 0 -column 0 -sticky ew -padx 5 -pady 3
    $id widget set Destination -widget $base.frame.destination
    if {$varName ne ""} {
        $id setText all Destination "<%Dir <%$varName%>%>"
    }

    Button $base.frame.browse -command \
        [list ::InstallAPI::PromptForDirectory -virtualtext $varName]
    grid $base.frame.browse -row 0 -column 1 -sticky nw -padx 5 -pady [list 0 5]
    $id widget set BrowseButton -widget $base.frame.browse
}
Added Themes/Modern_Wizard/Install/SelectProgramFolder.pane.


































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane SelectProgramFolder "Select Program Folder"

Order 11

Include CustomBlankPane2

Condition PlatformCondition Operator "is" Platform "Windows"
Condition FileNameTestCondition CheckCondition "Before Next Pane is Displayed" \
    Filename "<%ProgramFolderName%>" Operator "name is valid" \
    FailureMessage "||<%DirectoryNameErrorText%>"

Property Active boolean "Active" No
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon image "Icon" "<%Icon%>"
Property DefaultFolder shorttext "Default Folder" "<%AppName%>"

Text Title
Text Subtitle
Text Caption
Text Message
Text ProgramFolderLabel  "Program Folder Label"  0
Text FolderListLabel     "Folder List Label"     0
Text NextButton          "Next Button"           1
Text BackButton          "Back Button"           1
Text CancelButton        "Cancel Button"         1
Text AllUsersCheckbutton "All Users Checkbutton" 0
Added Themes/Modern_Wizard/Install/SelectProgramFolder.tcl.






















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.SelectProgramFolder { wizard id } {
    CreateWindow.CustomBlankPane2 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 3 -weight 1
    grid columnconfigure $base 0 -weight 1

    label $base.programFolderL -anchor w -padx 0 -bd 0
    grid  $base.programFolderL -row 0 -column 0 -sticky w -padx 1
    $id widget set ProgramFolderLabel -widget $base.programFolderL

    entry $base.programFolderE -textvariable ::info(ProgramFolderName)
    grid  $base.programFolderE -row 1 -column 0 -sticky ew -padx 1

    label $base.existingFoldersL -anchor w -padx 0 -bd 0
    grid  $base.existingFoldersL -row 2 -column 0 -sticky w \
        -padx 1 -pady [list 5 0]
    $id widget set FolderListLabel -widget $base.existingFoldersL

    frame $base.frame
    grid  $base.frame -row 3 -column 0 -sticky news

    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 0 -weight 1

    listbox $base.frame.list -bd 2 -relief sunken -highlightthickness 0 \
        -xscrollcommand [list $base.frame.hs set] \
        -yscrollcommand [list $base.frame.vs set]
    grid $base.frame.list -row 0 -column 0 -sticky news
    $id widget set ProgramFolderListBox -widget $base.frame.list \
        -type optiontree

    ttk::scrollbar $base.frame.vs -orient vertical \
        -command [list $base.frame.list yview]
    grid $base.frame.vs -row 0 -column 1 -sticky ns

    ttk::scrollbar $base.frame.hs -orient horizontal \
        -command [list $base.frame.list xview]
    grid $base.frame.hs -row 1 -column 0 -sticky ew

    bind $base.frame.list <1> [list focus %W]
    bind $base.frame.list <Double-1> ::InstallJammer::SetProgramFolder

    ttk::checkbutton $base.allUsers -variable ::info(ProgramFolderAllUsers)
    $id widget set AllUsersCheckbutton -widget $base.allUsers
    grid  $base.allUsers -row 4 -column 0 -sticky nw -pady {2 0}

    if {![info exists ::InstallJammer]} {
        ::InstallJammer::PopulateProgramFolders $id
    }
}
Added Themes/Modern_Wizard/Install/SetupComplete.pane.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane SetupComplete "Setup Complete"

Order 14

Include CustomBlankPane1

InstallTypes Standard Default

Property Buttons buttons "Buttons" "Next/Cancel"
Property Image image "Image" "<%Image%>"

Property WizardOptions hidden "Wizard Options" [list -bg #FFFFFF -separator 0]

Text Caption
Text Message
Text BackButton   "Back Button"   1
Text NextButton   "Next Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Modern_Wizard/Install/SetupComplete.tcl.




















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.SetupComplete { wizard id } {
    CreateWindow.CustomBlankPane1 $wizard $id
}
Added Themes/Modern_Wizard/Install/SetupType.pane.






































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane SetupType "Setup Type"

Order 9

Include CustomBlankPane2

Condition ScriptCondition \
    Comment "Only display this pane if we have more than one Setup Type" \
    Script {[llength [SetupTypes children]] > 1}

Condition StringIsCondition \
    Comment "Don't display this pane in an upgrade install" \
    Operator "false" String "<%UpgradeInstall%>"

Property Active boolean "Active" No
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon image "Icon" "<%Icon%>"

Action PopulateSetupTypes ExecuteAction "Before Pane is Displayed"

Text Title
Text Subtitle
Text Caption
Text Message
Text DescriptionLabel "Description Label" 0
Text NextButton       "Next Button"       1
Text BackButton       "Back Button"       1
Text CancelButton     "Cancel Button"     1
Added Themes/Modern_Wizard/Install/SetupType.tcl.






















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.SetupType { wizard id } {
    CreateWindow.CustomBlankPane2 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 0 -weight 1

    ScrolledWindow $base.sw
    grid $base.sw -row 0 -column 0 -sticky news -pady [list 4 0]

    ListBox $base.list -bd 2 -relief sunken -background #FFFFFF \
        -highlightthickness 0 -selectmode single -selectfill 1 -padx 0
    $base.sw setwidget $base.list
    $id widget set SetupTypeListBox -widget $base.list -type listbox

    labelframe $base.frame -relief groove -bd 2
    grid $base.frame -row 0 -column 1 -sticky news -padx [list 10 0]
    $id widget set DescriptionLabel -widget $base.frame

    grid rowconfigure    $base.frame 0 -weight 1
    grid columnconfigure $base.frame 0 -weight 1

    Label $base.frame.desc -width 25 -autowrap 1 -anchor nw -justify left
    grid $base.frame.desc -row 0 -column 0 -sticky news -padx 10 -pady 5
    $id widget set DescriptionText -widget $base.frame.desc

    if {[info exists ::InstallJammer]} {
        $base.list insert end #auto -text "Typical"
        $base.list selection set 0

        ::InstallJammer::SetVirtualText $id DescriptionText \
            "Program will be installed with the most common options."
        return
    }
}
Added Themes/Modern_Wizard/Install/StartCopyingFiles.pane.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane StartCopyingFiles "Start Copying Files"

Order 12

Include CustomTextPane1

Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon image "Icon" "<%Icon%>"

Text Title
Text Subtitle
Text Caption
Text Message
Text Text
Text NextButton   "Next Button"   1
Text BackButton   "Back Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Modern_Wizard/Install/StartCopyingFiles.tcl.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.StartCopyingFiles { wizard id } {
    CreateWindow.CustomTextPane1 $wizard $id

    set text [$id widget get Text]
    $text configure -bg [style configure . -background]
}
Added Themes/Modern_Wizard/Install/UserInformation.pane.




















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane UserInformation "User Information"

Order 7

Include CustomBlankPane2

Property Active boolean "Active" No
Property Buttons buttons "Buttons" "Back/Next/Cancel"
Property Icon image "Icon" "<%Icon%>"

Text Title
Text Subtitle
Text Caption
Text Message
Text UserNameLabel "User Name Label" 0
Text CompanyLabel  "Company Label"   0
Text NextButton    "Next Button"     1
Text BackButton    "Back Button"     1
Text CancelButton  "Cancel Button"   1
Added Themes/Modern_Wizard/Install/UserInformation.tcl.










































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.UserInformation { wizard id } {
    CreateWindow.CustomBlankPane2 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 0 -weight 1

    set frame [frame $base.frame]
    grid $frame -row 0 -column 0 -sticky new

    grid rowconfigure    $frame 0 -weight 1
    grid columnconfigure $frame 0 -weight 1

    label $frame.userLabel -anchor w -padx 0
    grid  $frame.userLabel -row 0 -column 0 -sticky w -pady 5
    $id widget set UserNameLabel -widget $frame.userLabel

    entry $frame.userEntry -textvariable info(UserInfoName)
    grid  $frame.userEntry -row 1 -column 0 -sticky ew
    $id widget set UserNameEntry -widget $frame.userEntry -type entry

    label $frame.companyLabel -anchor w -padx 0
    grid  $frame.companyLabel -row 2 -column 0 -sticky w -pady 5
    $id widget set CompanyLabel -widget $frame.companyLabel

    entry $frame.companyEntry -textvariable info(UserInfoCompany)
    grid  $frame.companyEntry -row 3 -column 0 -sticky ew
    $id widget set CompanyEntry -widget $frame.userEntry -type entry
}
Added Themes/Modern_Wizard/Install/Welcome.pane.














































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane Welcome "Welcome Screen"

Order 1

Include CustomBlankPane1

Property Buttons buttons "Buttons" "Next/Cancel"
Property Image image "Image" "<%Image%>"

Property WizardOptions hidden "Wizard Options" [list -bg #FFFFFF -separator 0]

Text Caption
Text Message
Text BackButton   "Back Button"   1
Text NextButton   "Next Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Modern_Wizard/Install/Welcome.tcl.




















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.Welcome { wizard id } {
    CreateWindow.CustomBlankPane1 $wizard $id
}
Added Themes/Modern_Wizard/Install/init.tcl.












































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::ThemeInit {} {
    variable info

    ## Create the main wizard.
    Wizard $info(Wizard) \
        -raisecommand [list RaiseStep %W %S] \
        -width [::InstallJammer::SubstText "<%WizardWidth%>"] \
        -height [::InstallJammer::SubstText "<%WizardHeight%>"] \
        -title [::InstallJammer::SubstText "<%InstallTitleText%>"] \
        -separatortext [::InstallJammer::SubstText "<%SeparatorText%>"]

    if {$::tcl_platform(platform) eq "unix"} {
        $info(Wizard) configure -bg [style configure . -background]
    }
}
Added Themes/Modern_Wizard/Install/main.tcl.
























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::ThemeMain {} {
    ::InstallJammer::InstallMain
}

if {![info exists ::InstallJammer]} { ThemeMain }
Added Themes/Modern_Wizard/Uninstall/Uninstall.pane.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane Uninstall "Uninstall"

Order 1

Include CustomBlankPane2

Action ModifyWidget Widget "NextButton; CancelButton" State "disabled" \
    ExecuteAction "Before Pane is Displayed"
Action ExecuteAction Action "Uninstall Actions"

Action MoveForward

Property Buttons buttons "Buttons" "Next/Cancel"
Property Icon image "Icon" "<%Icon%>"

Text Title
Text Subtitle
Text Caption
Text Message
Text FileValue     "File Label"     1
Text ProgressValue "Progress Value" 1
Text NextButton    "Next Button"    1
Text BackButton    "Back Button"    1
Text CancelButton  "Cancel Button"  1
Added Themes/Modern_Wizard/Uninstall/Uninstall.tcl.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.Uninstall { wizard id } {
    CreateWindow.CustomBlankPane2 $wizard $id

    set base [$id widget get ClientArea]

    grid rowconfigure    $base 0 -weight 1
    grid columnconfigure $base 0 -weight 1

    set frame [frame $base.frame]
    grid $frame -row 0 -column 0 -sticky new

    grid rowconfigure    $frame 1 -weight 1
    grid columnconfigure $frame 0 -weight 1

    label $frame.file -anchor w
    grid  $frame.file -row 0 -column 0 -sticky new
    $id widget set FileValue -widget $frame.file

    ttk::progressbar $frame.progress
    grid $frame.progress -row 1 -column 0 -sticky ew
    $id widget set ProgressValue -widget $frame.progress -type progress
}
Added Themes/Modern_Wizard/Uninstall/UninstallComplete.pane.














































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane UninstallComplete "Uninstall Complete"

Order 3

Include CustomBlankPane1

Property Buttons buttons "Buttons" "Next/Cancel"
Property Image image "Image" "<%Image%>"

Property WizardOptions hidden "Wizard Options" [list -bg #FFFFFF -separator 0]

Text Caption
Text Message
Text BackButton   "Back Button"   1
Text NextButton   "Next Button"   1
Text CancelButton "Cancel Button" 1
Added Themes/Modern_Wizard/Uninstall/UninstallComplete.tcl.




















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.UninstallComplete { wizard id } {
    CreateWindow.CustomBlankPane1 $wizard $id
}
Added Themes/Modern_Wizard/Uninstall/UninstallDetails.pane.




















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Pane UninstallDetails "Uninstall Details"

Order 2

Include CustomTextPane1

Condition StringIsCondition Operator "true" String "<%ErrorsOccurred%>"

Property Buttons buttons "Buttons" "Next/Cancel"
Property Icon image "Icon" "<%Icon%>"

Text Title
Text Subtitle
Text Caption
Text Message
Text Text         "Detail Text"
Text NextButton   "Next Button"        1
Text BackButton   "Back Button"        1
Text CancelButton "Cancel Button"      1
Added Themes/Modern_Wizard/Uninstall/UninstallDetails.tcl.




















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CreateWindow.UninstallDetails { wizard id } {
    CreateWindow.CustomTextPane1 $wizard $id
}
Added Themes/Modern_Wizard/Uninstall/init.tcl.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ThemeInit {} {
    global info

    ## Create the main wizard.
    Wizard $info(Wizard) \
        -raisecommand  [list RaiseStep %W %S] \
        -width [::InstallJammer::SubstText "<%WizardWidth%>"] \
        -height [::InstallJammer::SubstText "<%WizardHeight%>"] \
        -title [::InstallJammer::SubstText "<%UninstallTitleText%>"] \
        -separatortext [::InstallJammer::SubstText "<%SeparatorText%>"]

    bind $info(Wizard) <<WizardFinish>> [list ::InstallJammer::exit 1]

    if {$::tcl_platform(platform) eq "unix"} {
        $info(Wizard) configure -bg [style configure . -background]
    }
}
Added Themes/Modern_Wizard/Uninstall/main.tcl.
























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::ThemeMain {} {
    ::InstallJammer::UninstallMain
}

if {![info exists ::InstallJammer]} { ThemeMain }
Added Themes/Modern_Wizard/ar.msg.












































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
ChooseComponents {
    Title
    "\u202B\u0625\u062E\u062A\u064A\u0627\u0631 \u0627\u0644\u0645\u0643\u0648\u0646\u0627\u062A"

    Subtitle
    "\u202B\u0627\u0644\u0631\u062C\u0627\u0621 \u0625\u062E\u062A\u064A\u0627\u0631 \u0627\u0644\u0645\u0643\u0648\u0646\u0627\u062A \u0627\u0644\u062A\u064A \u0633\u064A\u0642\u0648\u0645 \u0628\u062A\u0631\u0643\u064A\u0628\u0647\u0627 \u0627\u0644\u0625\u0639\u062F\u0627\u062F."

    Caption
    "\u202B\u0625\u062E\u062A\u0627\u0631 \u0627\u0644\u0645\u0643\u0648\u0646\u0627\u062A \u0627\u0644\u062A\u064A \u062A\u0631\u064A\u062F \u062A\u0631\u0643\u064A\u0628\u0647\u0627 \u062B\u0645 \u0642\u0645 \u0628\u0639\u062F\u0645 \u0625\u062E\u062A\u064A\u0627\u0631 \u0627\u0644\u0645\u0643\u0648\u0646\u0627\u062A \u0627\u0644\u062A\u064A \u0644\u0627 \u062A\u0631\u064A\u062F \u062A\u0631\u0643\u064A\u0628\u0647\u0627."

    Message
    "\u202B<%SpaceRequiredText%> \u0645\u0637\u0644\u0648\u0628\u0629 \u0645\u0646 \u0645\u0633\u0627\u062D\u0629 \u0627\u0644\u062C\u0647\u0627\u0632"

    DescriptionLabel
    "\u202B\u0648\u0635\u0641"

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

CopyFiles {
    Title
    "\u202B\u062A\u0631\u0643\u064A\u0628"

    Subtitle
    "\u202B\u062A\u0631\u0643\u064A\u0628 <%AppName%>"

    Caption
    "\u202B\u0627\u0644\u0631\u062C\u0627\u0621 \u0627\u0644\u0625\u0646\u062A\u0638\u0627\u0631 \u0628\u064A\u0646\u0645\u0627 \u064A\u0642\u0648\u0645 \u0627\u0644\u0625\u0639\u062F\u0627\u062F \u0628\u062A\u0631\u0643\u064A\u0628 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%> \u0639\u0644\u0649 \u062C\u0647\u0627\u0632\u0643."

    Message
    ""

    FileLabel
    "\u202B<%Status%>"

    ProgressValue
    "\u202B<%InstallPercentComplete%>"

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "\u202B\u064A\u062A\u0645\u0651 \u0648\u0636\u0639 \u0627\u0644\u0639\u0646\u0627\u0648\u064A\u0646 \u0647\u0646\u0627."

    Message
    "\u202B\u0636\u0639 \u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u0647\u0646\u0627."

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "\u202B\u0639\u0646\u0648\u0627\u0646"

    Subtitle
    "\u202B\u0639\u0646\u0648\u0627\u0646 \u0641\u0631\u0639\u064A"

    Caption
    "\u202B\u0639\u0646\u0648\u0627\u0646"

    Message
    "\u202B\u0631\u0633\u0627\u0644\u0629"

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

CustomTextPane1 {
    Title
    "\u202B\u0639\u0646\u0648\u0627\u0646"

    Subtitle
    "\u202B\u0639\u0646\u0648\u0627\u0646 \u0641\u0631\u0639\u064A"

    Caption
    "\u202B\u0639\u0646\u0648\u0627\u0646"

    Message
    "\u202B\u0631\u0633\u0627\u0644\u0629"

    Text
    "\u202B\u0636\u0639 \u0646\u0635\u0651\u0643 \u0647\u0646\u0627."

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

License {
    Title
    "\u202B\u0639\u0642\u062F \u0627\u0644\u0631\u062E\u0635\u0629"

    Subtitle
    "\u202B\u0627\u0644\u0631\u062C\u0627\u0621 \u0642\u0631\u0627\u0621\u0629 \u0639\u0642\u062F \u0627\u0644\u0631\u062E\u0635\u0629 \u0627\u0644\u062A\u0627\u0644\u064A \u0628\u062F\u0642\u0629."

    AcceptRadiobutton
    "\u202B\u0623\u0648\u0627\u0641\u0642 \u0639\u0644\u0649 \u0634\u0631\u0648\u0637 \u0639\u0642\u062F \u0627\u0644\u0631\u062E\u0635\u0629."

    DeclineRadiobutton
    "\u202B\u0644\u0627 \u0623\u0648\u0627\u0641\u0642 \u0639\u0644\u0649 \u0634\u0631\u0648\u0637 \u0639\u0642\u062F \u0627\u0644\u0631\u062E\u0635\u0629."

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

Readme {
    Title
    "\u202B\u0645\u0639\u0644\u0648\u0645\u0627\u062A \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0645\u0633\u0627\u0639\u062F"

    Subtitle
    "\u202B\u0645\u0639\u0644\u0648\u0645\u0627\u062A \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0645\u0633\u0627\u0639\u062F \u0644\u0644\u0628\u0631\u0646\u0627\u0645\u062C <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

SelectDestination {
    Title
    "\u202B\u0625\u062E\u062A\u0627\u0631 \u0627\u0644\u0645\u0648\u0642\u0639 \u0627\u0644\u0646\u0647\u0627\u0626\u064A"

    Subtitle
    "\u202B\u0623\u064A\u0646 \u062A\u0631\u064A\u062F \u062A\u0631\u0643\u064A\u0628 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%>\u061F"

    Caption
    "\u202B\u0647\u0630\u0647 \u0627\u0644\u0639\u0645\u0644\u064A\u0629 \u0633\u062A\u0642\u0648\u0645 \u0628\u062A\u0631\u0643\u064A\u0628 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%> \u0641\u064A \u0627\u0644\u0645\u062C\u0644\u062F \u0627\u0644\u062A\u0627\u0644\u064A.\n\u202B\n\u202B\u0644\u0644\u062A\u0631\u0643\u064A\u0628 \u0641\u064A \u0647\u0630\u0627 \u0627\u0644\u0645\u062C\u0644\u062F\u060C \u0623\u0646\u0642\u0631 \u0627\u0644\u062A\u0627\u0644\u064A.  \u0644\u0644\u062A\u0631\u0643\u064A\u0628 \u0641\u064A \u0645\u0644\u0641 \u0645\u062E\u062A\u0644\u0641\u060C \u0623\u0646\u0642\u0631 \u0625\u0633\u062A\u0637\u0644\u0627\u0639 \u062B\u0645 \u0627\u062E\u062A\u0627\u0631 \u0645\u062C\u0644\u062F \u0622\u062E\u0631."

    Message
    ""

    BrowseText
    "\u202B\u0644\u0644\u0625\u0643\u0645\u0627\u0644\u060C \u0623\u0646\u0642\u0631 \u0627\u0644\u062A\u0627\u0644\u064A.  \u0625\u0630\u0627 \u0623\u0631\u062F\u062A \u0623\u0646 \u062A\u062E\u062A\u0627\u0631 \u0645\u062C\u0644\u0651\u062F \u0645\u062E\u062A\u0644\u0641\u060C \u0623\u0646\u0642\u0631 \u0625\u0633\u062A\u0637\u0644\u0627\u0639."

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"

    BrowseButton
    "\u202B<%Browse%>"

    DestinationLabel
    "\u202B\u0645\u062C\u0644\u0651\u062F \u0627\u0644\u0645\u0648\u0642\u0639 \u0627\u0644\u0646\u0647\u0627\u0626\u064A"
}

SelectProgramFolder {
    Title
    "\u202B\u0625\u062E\u062A\u064A\u0627\u0631 \u0645\u062C\u0644\u062F \u0627\u0644\u0628\u0631\u0627\u0645\u062C"

    Subtitle
    "\u202B\u0627\u0644\u0631\u062C\u0627\u0621 \u0625\u062E\u062A\u064A\u0627\u0631 \u0645\u062C\u0644\u062F \u0644\u0644\u0628\u0631\u0646\u0627\u0645\u062C."

    Caption
    "\u202B\u0633\u0648\u0641 \u064A\u0636\u064A\u0641 \u0627\u0644\u0625\u0639\u062F\u0627\u062F \u0623\u064A\u0642\u0648\u0646\u0627\u062A \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C \u0625\u0644\u0649 \u0645\u062C\u0644\u062F \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C \u0627\u0644\u062A\u0627\u0644\u064A.  \u0628\u0625\u0645\u0643\u0627\u0646\u0643 \u0643\u062A\u0627\u0628\u0629 \u0625\u0633\u0645 \u0645\u062C\u0644\u062F \u062C\u062F\u064A\u062F \u0623\u0648 \u0623\u0646 \u062A\u062E\u062A\u0627\u0631 \u0645\u062C\u0644\u062F \u0645\u0646 \u0644\u0627\u0626\u062D\u0629 \u0627\u0644\u0645\u062C\u0644\u062F\u0627\u062A \u0627\u0644\u0645\u0648\u062C\u0648\u062F\u0629.  \u0623\u0646\u0642\u0631 \u0627\u0644\u062A\u0627\u0644\u064A \u0644\u0644\u0625\u0643\u0645\u0627\u0644."

    Message
    ""

    ProgramFolderLabel
    "\u202B\u0645\u062C\u0644\u062F \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C:"

    FolderListLabel
    "\u202B\u0627\u0644\u0645\u062C\u0644\u062F\u0627\u062A \u0627\u0644\u0645\u0648\u062C\u0648\u062F\u0629:"

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"

    AllUsersCheckbutton
    "\u202B\u0625\u0646\u0634\u0627\u0621 \u0645\u062C\u0644\u062F \u0628\u0631\u0627\u0645\u062C \u0644\u062C\u0645\u064A\u0639 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645\u064A\u0646"
}

SetupComplete {
    Caption
    "\u202B\u0625\u0646\u062A\u0647\u0627\u0621 \u0645\u0639\u0627\u0644\u062C InstallJammer"

    Message
    "\u202B\u0646\u062C\u062D \u0645\u0639\u0627\u0644\u062C InstallJammer \u0628\u062A\u0631\u0643\u064A\u0628 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%>.  \u0623\u0646\u0642\u0631 \u0625\u0646\u062A\u0647\u0627\u0621 \u0644\u0644\u062E\u0631\u0648\u062C \u0645\u0646 \u0627\u0644\u0645\u0639\u0627\u0644\u062C."

    NextButton
    "\u202B<%Finish%>"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

SetupType {
    Title
    "\u202B\u0646\u0648\u0639 \u0627\u0644\u0625\u0639\u062F\u0627\u062F"

    Subtitle
    "\u202B\u0627\u0644\u0631\u062C\u0627\u0621 \u0625\u062E\u062A\u064A\u0627\u0631 \u0646\u0648\u0639 \u0627\u0644\u0625\u0639\u062F\u0627\u062F \u0627\u0644\u0630\u064A \u064A\u0646\u0627\u0633\u0628 \u0625\u062D\u062A\u064A\u0627\u062C\u0627\u062A\u0643."

    Caption
    "\u202B\u0623\u0646\u0642\u0631 \u0646\u0648\u0639 \u0627\u0644\u062A\u0631\u0643\u064A\u0628 \u0627\u0644\u0630\u064A \u062A\u0641\u0636\u0644\u0647."

    Message
    ""

    DescriptionLabel
    "\u202B\u0648\u0635\u0641"

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

StartCopyingFiles {
    Title
    "\u202B\u0628\u062F\u0621 \u0646\u0633\u062E \u0627\u0644\u0645\u0644\u0641\u0627\u062A"

    Subtitle
    "\u202B\u0645\u0631\u0627\u062C\u0639\u0629 \u0627\u0644\u0625\u0639\u062F\u0627\u062F\u0627\u062A \u0642\u0628\u0644 \u0646\u0633\u062E \u0627\u0644\u0645\u0644\u0641\u0627\u062A"

    Caption
    "\u202B\u0627\u0644\u0625\u0639\u062F\u0627\u062F \u0644\u062F\u064A\u0647 \u0645\u0639\u0644\u0648\u0645\u0627\u062A \u0643\u0627\u0641\u064A\u0629 \u0644\u0628\u062F\u0621 \u0646\u0633\u062E \u0645\u0644\u0641\u0627\u062A \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C.  \u0625\u0630\u0627  \u0623\u0631\u062F\u062A \u0645\u0631\u0627\u062C\u0639\u0629 \u0623\u0648 \u062A\u063A\u064A\u064A\u0631 \u0623\u064A\u0629 \u0625\u0639\u062F\u0627\u062F\u0627\u062A\u060C \u0623\u0646\u0642\u0631 \u0631\u062C\u0648\u0639.  \u0625\u0630\u0627 \u0643\u0646\u062A \u0631\u0627\u0636\u064A\u0627\u064B \u0639\u0646 \u0627\u0644\u0625\u0639\u062F\u0627\u062F\u0627\u062A\u060C \u0623\u0646\u0642\u0631 \u0627\u0644\u062A\u0627\u0644\u064A \u0644\u0628\u062F\u0621 \u0639\u0645\u0644\u064A\u0629 \u0646\u0633\u062E \u0627\u0644\u0645\u0644\u0641\u0627\u062A."

    Message
    ""

    Text
    "\u202B\u0645\u062C\u0644\u0651\u062F \u0627\u0644\u062A\u0631\u0643\u064A\u0628:\n\u202B          <%InstallDir%>\n\u202B\n\u202B\u0646\u0648\u0639 \u0627\u0644\u0625\u0639\u062F\u0627\u062F:\n\u202B          <%InstallType%>"

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

Uninstall {
    Title
    "\u202B\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C"

    Subtitle
    "\u202B\u0625\u0632\u0627\u0644\u0629 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%>"

    Caption
    "\u202B<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "\u202B<%Status%>"

    ProgressValue
    "\u202B<%UninstallPercentComplete%>"

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

UninstallComplete {
    Caption
    "\u202B\u0625\u0646\u062A\u0647\u0627\u0621 \u0639\u0645\u0644\u064A\u0629 \u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C"

    Message
    " \u0645\u0646 \u062C\u0647\u0627\u0632\u0643. <%AppName%> \u062A\u0645\u0651 \u062D\u0630\u0641 \u0628\u0631\u0646\u0627\u0645\u062C "

    NextButton
    "\u202B<%Finish%>"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}

UninstallDetails {
    Title
    "\u202B\u062A\u0641\u0627\u0635\u064A\u0644 \u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C"

    Subtitle
    "\u202B\u062D\u062F\u062B\u062A \u0623\u062E\u0637\u0627\u0621 \u0623\u062B\u0646\u0627\u0621 \u0639\u0645\u0644\u064A\u0629 \u0627\u0644\u062D\u0630\u0641"

    Caption
    "\u202B\u0627\u0644\u0623\u062E\u0637\u0627\u0621 \u0627\u0644\u062A\u0627\u0644\u064A\u0629 \u062D\u062F\u062B\u062A \u0623\u062B\u0646\u0627\u0621 \u0639\u0645\u0644\u064A\u0629 \u0627\u0644\u062D\u0630\u0641:"

    Message
    ""

    Text
    "\u202B<%Errors%>"

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}


UserInformation {
    Title
    "\u202B\u0645\u0639\u0644\u0648\u0645\u0627\u062A \u0627\u0644\u0632\u0628\u0648\u0646"

    Subtitle
    "\u202B\u0627\u0644\u0631\u062C\u0627\u0621 \u0625\u062F\u062E\u0627\u0644 \u0645\u0639\u0644\u0648\u0645\u0627\u062A\u0643."

    Caption
    "\u202B\u0627\u0644\u0631\u062C\u0627\u0621 \u0625\u062F\u062E\u0627\u0644 \u0625\u0633\u0645\u0643 \u0648 \u0625\u0633\u0645 \u0627\u0644\u0634\u0631\u0643\u0629 \u0627\u0644\u062A\u064A \u062A\u0639\u0645\u0644 \u0644\u062F\u064A\u0647\u0627."

    Message
    ""

    UserNameLabel
    "\u202B\u0625\u0633\u0645 \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645:"

    CompanyLabel
    "\u202B\u0625\u0633\u0645 \u0627\u0644\u0634\u0631\u0643\u0629:"

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}


Welcome {
    Caption
    "\u202B\u0645\u0631\u062D\u0628\u0627\u064B \u0628\u0642\u062F\u0648\u0645\u0643 \u0625\u0644\u0649 \u0645\u0639\u0627\u0644\u062C InstallJammer \u0644\u0628\u0631\u0646\u0627\u0645\u062C <%AppName%>"

    Message
    "\u202B\u0647\u0630\u0647 \u0627\u0644\u0639\u0645\u0644\u064A\u0629 \u0633\u062A\u0642\u0648\u0645 \u0628\u062A\u0631\u0643\u064A\u0628 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%> \u0625\u0635\u062F\u0627\u0631 \u0631\u0642\u0645 <%Version%> \u0639\u0644\u0649 \u062C\u0647\u0627\u0632\u0643 \u0627\u0644\u062E\u0627\u0635 \u0628\u0643. \n\u202B\n\u202B\u0645\u0646 \u0627\u0644\u0645\u0641\u0636\u0644 \u0623\u0646 \u062A\u063A\u0644\u0642 \u062C\u0645\u064A\u0639 \u0627\u0644\u0628\u0631\u0627\u0645\u062C \u0627\u0644\u0623\u062E\u0631\u0649 \u0642\u0628\u0644 \u0627\u0644\u0625\u0643\u0645\u0627\u0644.\n\u202B\n\u202B\u0623\u0646\u0642\u0631 \u0627\u0644\u062A\u0627\u0644\u064A \u0644\u0644\u0625\u0643\u0645\u0627\u0644 \u0623\u0648 \u0623\u0646\u0642\u0631 \u0625\u0644\u063A\u0627\u0621 \u0644\u0644\u062E\u0631\u0648\u062C \u0645\u0646 \u0627\u0644\u0625\u0639\u062F\u0627\u062F."

    NextButton
    "\u202B<%Next%> >"

    BackButton
    "\u202B< <%Back%>"

    CancelButton
    "\u202B<%Cancel%>"
}
Added Themes/Modern_Wizard/ca.msg.














































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
ChooseComponents {
    Title
    "Selecció de Components"

    Subtitle
    "Selecció dels components de la instal·lació."

    Caption
    "Seleccioni els components que desitja instal·lar i elimini els que\
     que no desitja que siguin instal·lats."

    Message
    "<%SpaceRequiredText%> d'espai necessari"

    DescriptionLabel
    "Descripció"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Instal·lant"

    Subtitle
    "Instal·lant <%AppName%>"

    Caption
    "Si us plau, espereu mentre s'instal·la <%AppName%> en el seu equip."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Llegenda aquí."

    Message
    "Missatge aquí."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Ròtul"

    Subtitle
    "Subtítol"

    Caption
    "Llegenda"

    Message
    "Missatge"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Ròtul"

    Subtitle
    "Subtítol"

    Caption
    "Llegenda"

    Message
    "Missatge"

    Text
    "Escriviu aquí el vostre missatge personalitzat."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Acord de Llicència"

    Subtitle
    "Si us plau, llegiu atentament l'acord de llicència."

    AcceptRadiobutton
    "Accepto els termes de l'acord de llicència."

    DeclineRadiobutton
    "NO accepto els termes de l'acord de llicència."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Llegiu-me"

    Subtitle
    "Informació sobre <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Elegiu el directori de destí"

    Subtitle
    "On desitgeu instal·lar <%AppName%>?"

    Caption
    "S'instal·larà <%AppName%> en el següent directori.\n\n Per instal·lar\
     en aquest directori, cliqueu Següent. Per instal·lar en un altre\
     directori, cliqueu Examinar i seleccioneu un altre directori."

    Message
    ""

    BrowseText
    "Cliqueu Següent per continuar. Si desitgeu seleccionar un\
    directori diferent, cliqueu Examinar."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Directori Destí"
}

SelectProgramFolder {
    Title
    "Seleccioni el Grup de Programes"

    Subtitle
    "Si us plau, seleccioni un grup de programes."

    Caption
    "S'instal·laran icones en el Grup de Programes següent. \
    Podeu escriure un nou nom de grup o seleccionar-ho\
    de la llista de grups existents. \
    Cliqueu Següent per continuar."

    Message
    ""

    ProgramFolderLabel
    "Grup de Programes:"

    FolderListLabel
    "Grups Existents:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Crear un grup de programes per a tots els usuaris"
}

SetupComplete {
    Caption
    "InstallJammer Wizard Completat"

    Message
    "El Wizard InstallJammer ha instal·lat <%AppName%> correctament. \
     Cliqueu Finalitzar per a sortir d'aquest assistent."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Tipus d'Instal·lació"

    Subtitle
    "Seleccioni el tipus d'instal·lació més adient a les seves necessitats."

    Caption
    "Cliqueu el tipus d'instal·lació desitjada."

    Message
    ""

    DescriptionLabel
    "Descripció"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Iniciar la Còpia d'Arxius"

    Subtitle
    "Reviseu la configuració abans de copiar els arxius"

    Caption
    "S'ha reunit la informació necessària per a iniciar la còpia dels\
    arxius del programa. Si desitgeu revisar o canviar la configuració,\
    cliqueu Enrera. Si esteu conforme amb la configuració, cliqueu Següent\
    per a iniciar la còpia dels arxius."

    Message
    ""

    Text
    "Directori d'Instal·lació:
            <%InstallDir%>

    Tipus d'Instalació:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Desinstal·lar"

    Subtitle
    "Desinstal·lar <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Desinstal·lació Completa"

    Message
    "<%AppName%> s'ha eliminat del seu sistema."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Detalls de la Desinstal·lació"

    Subtitle
    "Errors en l'eliminació"

    Caption
    "S'han produït els següents errors en el procés de desinstal·lació:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Informació d'Usuari"

    Subtitle
    "Si us plau, introduïu les vostres dades d'usuari."

    Caption
    "Si us plau, introduïu el nom de la vostra empresa."

    Message
    ""

    UserNameLabel
    "Nom d'Usuari:"

    CompanyLabel
    "Empresa:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Benvingut a l'Assistent InstallJammer per a <%AppName%>"

    Message
    "Aquest programa instal·larà <%AppName%> versió <%Version%> en el seu equip.\
    \n\nEs recomana tancar les aplicacions abans de continuar. \
    \n\nCliqueu Següent per continuar o Cancel·lar per sortir de la instal·lació."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/cs.msg.


































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# options: -encoding utf-8

ChooseComponents {
    Title
    "Zvolte souÄásti"

    Subtitle
    "Zvolte souÄásti, které budou nainstalovány."

    Caption
    "Zvolte souÄásti, které chcete nainstalovat, a zruÅ¡te vybrání souÄástí,\
     které nechcete nainstalovat."

    Message
    "Vyžadováno <%SpaceRequiredText%> místa"

    DescriptionLabel
    "Popis"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Instalace"

    Subtitle
    "Instalace programu <%AppName%>"

    Caption
    "Prosím Äekejte, dokud nebude program <%AppName%> nainstalován na váš poÄítaÄ."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Titulek bude zde."

    Message
    "Zpráva bude zde."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Nadpis"

    Subtitle
    "Podnadpis"

    Caption
    "Titulek"

    Message
    "Zpráva"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Nadpis"

    Subtitle
    "Podnadpis"

    Caption
    "Titulek"

    Message
    "Zpráva"

    Text
    "Zde vložte svůj vlastní text."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "LicenÄní ujednání"

    Subtitle
    "Následující licenÄní ujednání prosím ÄtÄ›te peÄlivÄ›."

    Text
    "Zde vložte své licenÄní ujednání."

    AcceptRadiobutton
    "PÅ™ijímám podmínky licenÄního ujednání."

    DeclineRadiobutton
    "NepÅ™ijímám podmínky licenÄního ujednání."

    NextButton
    "<%Yes%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%No%>"
}

Readme {
    Title
    "Informace ÄŒtiMÄ›"

    Subtitle
    "Informace ÄŒtiMÄ› pro <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    "Sem vložte vaÅ¡e informace ÄtimÄ›."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Zvolte cílové umístění"

    Subtitle
    "Kam má být program <%AppName%> nainstalován?"

    Caption
    "Program <%AppName%> bude nainstalován do následující složky.\n\nK instalaci\
     do této složky stiskněte Vpřed. K instalaci do jiné složky stiskněte\
     Procházet a zvolte jinou složku."

    Message
    ""

    BrowseText
    "K pokraÄování stisknÄ›te VpÅ™ed. Pokud chcete vybrat odliÅ¡nou složku,\
     stiskněte Procházet."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Cílová složka"
}

SelectProgramFolder {
    Title
    "Zvolte složku programu"

    Subtitle
    "Prosím zvolte složku programu."

    Caption
    "Instalátor přidá ikony programu do složky programu uvedené níže.\
     Můžete vepsat odlišný název složky nebo ji vybrat ze seznamu existujících složek.\
     K pokraÄování stisknÄ›te VpÅ™ed."

    Message
    ""

    ProgramFolderLabel
    "Složka programu:"

    FolderListLabel
    "Existující složky:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Vytvořit složku programu pro všechny uživatele"
}

SetupComplete {
    Caption
    "Průvodce InstallJammer dokonÄen"

    Message
    "Průvodce InstallJammer úspěšně nainstaloval program <%AppName%>.\
     StisknÄ›te DokonÄit pro ukonÄení průvodce."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Typ instalace"

    Subtitle
    "Zvolte typ instalace, který vám nejlépe vyhovuje."

    Caption
    "Klikněte na upřednostňovaný typ instalace."

    Message
    ""

    DescriptionLabel
    "Popis"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Spustit kopírování souborů"

    Subtitle
    "Zkontrolujte nastavení před kopírováním souborů"

    Caption
    "Instalátor má dostatek informací pro spustění kopírování souborů programu. Pokud\
     chcete zkontrolovat nebo změnit jakékoliv nastavení, stiskněte Zpět. Pokud jste\
     spokojeni s nastavením, stiskněte Vpřed pro spuštění kopírování souborů."

    Message
    ""

    Text
    "InstalaÄní složka:
            <%InstallDir%>

    Typ instalace:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Odinstalace"

    Subtitle
    "Odinstalace programu <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Odinstalace dokonÄena"

    Message
    "Program <%AppName%> byl odstraněn z vašeho systému."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Podrobnosti odinstalace"

    Subtitle
    "Během odstraňování došlo k chybám"

    Caption
    "Následující chyby nastaly během odstraňování:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Zákaznické informace"

    Subtitle
    "Prosím zadejte své informace."

    Caption
    "Prosím zadejte své jméno a název spoleÄnosti, pro kterou pracujete."

    Message
    ""

    UserNameLabel
    "Jméno zákazníka:"

    CompanyLabel
    "SpoleÄnost:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Vítejte v průvodci InstallJammer pro program <%AppName%>"

    Message
    "Na váš poÄítaÄ bude nainstalován program <%AppName%> verze <%Version%>.\
    \n\nPÅ™ed pokraÄováním je doporuÄeno uzavřít vÅ¡echny ostatní aplikace.\
    \n\nStisknÄ›te VpÅ™ed k pokraÄování nebo ZruÅ¡it k ukonÄení instalátoru."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

InstallPassword {
    Title
    "Heslo instalace"

    Subtitle
    "Tato instalace vyžaduje k pokraÄování heslo."

    Caption
    "Prosím zadejte heslo."

    Message
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/de.msg.






















































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
ChooseComponents {
    Title
    "Auswahl Komponenten"

    Subtitle
    "Wählen Sie die zu installierenden Komponenten aus."

    Caption
    "Wählen Sie die zu installierenden Komponenten aus und deselektieren Sie\
     die Komponenten, die Sie nicht installieren möchten."

    Message
    "<%SpaceRequiredText%> an Plattenplatz benötigt"

    DescriptionLabel
    "Beschreibung"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Installation"

    Subtitle
    "Installiere <%AppName%>"

    Caption
    "Bitte warten Sie, während Setup <%AppName%> auf Ihrem Computer installiert."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Überschrift kommt hier hin."

    Message
    "Meldung kommt hier hin."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Titel"

    Subtitle
    "Untertitel"

    Caption
    "Überschrift"

    Message
    "Meldung"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Titel"

    Subtitle
    "Untertitel"

    Caption
    "Untertitel"

    Message
    "Meldung"

    Text
    "Ihr benutzerdefinierter Text kommt hier hin."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Lizenzbestimmungen"

    Subtitle
    "Bitte lesen Sie die folgenden Lizenzbestimmungen aufmerksam."

    AcceptRadiobutton
    "Ich akzeptiere die Lizenzbestimmungen."

    DeclineRadiobutton
    "Ich akzeptiere nicht die Lizenzbestimmungen."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Liesmich Informationen"

    Subtitle
    "Liesmich Informationen für <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Auswahl Installationsziel"

    Subtitle
    "Wohin soll <%AppName%> installiert werden?"

    Caption
    "Setup wird <%AppName%> in das folgende Verzeichnis installieren. \
    \n\nKlicken Sie auf Weiter, wenn dieses Verzeichnis verwendet werden soll. \
    Um ein anderes Verzeichnis auszuwählen, klicken Sie auf Durchsuchen und\
    wählen ein anderes aus."

    Message
    ""

    BrowseText
    "Um Fortzufahren, klicken Sie auf Weiter.  Wenn Sie ein anderes Verzeichnis\
    verwenden möchten, klicken Sie auf Durchsuchen."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Zielordner"
}

SelectProgramFolder {
    Title
    "Auswahl Programmordner"

    Subtitle
    "Bitte wählen Sie einen Programmordner."

    Caption
    "Setup wird die Programmsymbole zum unten aufgeführten Programmordner\
    hinzufügen. Sie können einen neuen Ordnernamen eingeben oder einen von der\
    von der existierenden Ordnerliste auswählen. Klicken Sie auf Weiter um\
    Fortzufahren."

    Message
    ""

    ProgramFolderLabel
    "Programmordner:"

    FolderListLabel
    "Vorhandene Ordner:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Erstelle Programmordner für alle Benutzer"
}

SetupComplete {
    Caption
    "Installation Abgeschlossen"

    Message
    "InstallJammer hat <%AppName%> erfolgreich installiert. \
     Klicken Sie auf Beenden, um den Assistenten zu verlassen."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Setup Art"

    Subtitle
    "Wählen Sie die Art des Setup, welche am Besten Ihren Anforderungen\
    entspricht."

    Caption
    "Klicken Sie auf die bevorzugte Art des Setup."

    Message
    ""

    DescriptionLabel
    "Beschreibung"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Kopieren der Dateien"

    Subtitle
    "Überprüfen Sie die Einstellungen, bevor die Dateien kopiert werden."

    Caption
    "Setup hat genug Informationen, um die Programmdateien\
    zu kopieren. Wenn Sie die Einstellungen überprüfen oder ändern möchten,\
    klicken Sie auf Zurück. Wenn Sie mit den Einstellungen zufrieden sind,\
    klicken Sie auf Weiter, um mit dem Kopieren der Dateien zu beginnen."

    Message
    ""

    Text
    "Installationsverzeichnis:
                <%InstallDir%>

    Setup Art:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Deinstallation"

    Subtitle
    "Deinstalliere <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Deinstallation Abgeschlossen"

    Message
    "<%AppName%> wurde von Ihrem System entfernt."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Deinstallation Details"

    Subtitle
    "Es sind Fehler beim Löschen aufgetreten"

    Caption
    "Die folgenden Fehler sind beim Löschen aufgetreten:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Benutzer Information"

    Subtitle
    "Bitte geben Sie Ihre Informationen ein."

    Caption
    "Bitte geben Sie Ihren Namen und den Namen der Firma ein, für die Sie\
    arbeiten."

    Message
    ""

    UserNameLabel
    "Benutzername:"

    CompanyLabel
    "Firma:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Willkommen beim InstallJammer Assistenten für <%AppName%>"

    Message
    "Dies wird <%AppName%> Version <%Version%> auf Ihrem Computer installieren. \
    \n\nEs wird empfohlen, das Sie alle anderen Anwendungen schließen, bevor\
    Sie fortfahren.\n\nKlicken Sie auf Weiter um Fortzufahren oder auf\
    Abbrechen, um das Setup zu beenden."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/en.msg.






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
ChooseComponents {
    Title
    "Select Components"

    Subtitle
    "Select the components setup will install."

    Caption
    "Select the components you want to install and deselect the components\
     you do not want to install."

    Message
    "<%SpaceRequiredText%> of space required"

    DescriptionLabel
    "Description"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Installing"

    Subtitle
    "Installing <%AppName%>"

    Caption
    "Please wait while Setup installs <%AppName%> on your computer."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Caption goes here."

    Message
    "Message goes here."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Title"

    Subtitle
    "Subtitle"

    Caption
    "Caption"

    Message
    "Message"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Title"

    Subtitle
    "Subtitle"

    Caption
    "Caption"

    Message
    "Message"

    Text
    "Put your custom text here."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "License Agreement"

    Subtitle
    "Please read the following license agreement carefully."

    Text
    "Put your license agreement here."

    AcceptRadiobutton
    "I accept the terms of the license agreement."

    DeclineRadiobutton
    "I do not accept the terms of the license agreement."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Readme Information"

    Subtitle
    "Readme Information for <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    "Put your readme information here."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Choose Destination Location"

    Subtitle
    "Where should <%AppName%> be installed?"

    Caption
    "Setup will install <%AppName%> in the following folder.\n\nTo install\
     to this folder, click Next.  To install to a different folder, click\
     Browse and select another folder."

    Message
    ""

    BrowseText
    "To continue, click Next.  If you would like to select a different\
     folder, click Browse."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Destination Folder"
}

SelectProgramFolder {
    Title
    "Select Program Folder"

    Subtitle
    "Please select a program folder."

    Caption
    "Setup will add the program icons to the Program Folder listed below. \
     You may type a new folder name or select from the existing folders list. \
     Click Next to continue."

    Message
    ""

    ProgramFolderLabel
    "Program Folder:"

    FolderListLabel
    "Exising Folders:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Create program folder for all users"
}

SetupComplete {
    Caption
    "InstallJammer Wizard Complete"

    Message
    "The InstallJammer Wizard has successfully installed <%AppName%>. \
     Click Finish to exit the wizard."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Setup Type"

    Subtitle
    "Select the setup type that best suits your needs."

    Caption
    "Click the type of Setup you prefer."

    Message
    ""

    DescriptionLabel
    "Description"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Start Copying Files"

    Subtitle
    "Review settings before copying files"

    Caption
    "Setup has enough information to start copying the program files.  If\
     you want to review or change any settings, click Back.  If you are\
     satisfied with the settings, click Next to begin copying files."

    Message
    ""

    Text
    "Install Directory:
            <%InstallDir%>

    Setup Type:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Uninstalling"

    Subtitle
    "Uninstalling <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Uninstall Complete"

    Message
    "<%AppName%> has been removed from your system."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Uninstall Details"

    Subtitle
    "Errors occurred during removal"

    Caption
    "The following errors occurred during removal:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Customer Information"

    Subtitle
    "Please enter your information."

    Caption
    "Please enter your name and the name of the company for which you work."

    Message
    ""

    UserNameLabel
    "User Name:"

    CompanyLabel
    "Company:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Welcome to the InstallJammer Wizard for <%AppName%>"

    Message
    "This will install <%AppName%> version <%Version%> on your computer. \
    \n\nIt is recommended that you close all other applications before\
    continuing.\n\nClick Next to continue or Cancel to exit Setup."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

InstallPassword {
    Title
    "Install Password"

    Subtitle
    "This installation requires a password to continue."

    Caption
    "Please enter a password."

    Message
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/es.msg.














































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
ChooseComponents {
    Title
    "Seleccionar Componentes"

    Subtitle
    "Seleccionar los componentes de la instalación."

    Caption
    "Seleccione los componentes que desea instalar y elimine aquéllos\
     que no desea que sean instalados."

    Message
    "<%SpaceRequiredText%> de espacio requerido"

    DescriptionLabel
    "Descripción"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Instalando"

    Subtitle
    "Instalando <%AppName%>"

    Caption
    "Por favor espere mientras se instala <%AppName%> en su equipo."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Leyenda aquí."

    Message
    "Mensaje aquí."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Título"

    Subtitle
    "Subtítulo"

    Caption
    "Leyenda"

    Message
    "Mensaje"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Título"

    Subtitle
    "Subtítulo"

    Caption
    "Leyenda"

    Message
    "Mensaje"

    Text
    "Escriba su texto personalizado aquí."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Acuerdo de Licencia"

    Subtitle
    "Por favor lea atentamente el siguiente acuerdo de licencia."

    AcceptRadiobutton
    "Acepto los términos de este acuerdo de licencia."

    DeclineRadiobutton
    "NO acepto los términos de este acuerdo de licencia."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Léeme"

    Subtitle
    "Información sobre <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Escoja Carpeta Destino"

    Subtitle
    "¿Dónde desea instalar <%AppName%>?"

    Caption
    "Se instalará <%AppName%> en la siguiente carpeta. Para instalar\
     en esta carpeta, pulse Siguiente. Para instalar en una carpeta diferente,\
     pulse Examinar y seleccione otra."

    Message
    ""

    BrowseText
    "Pulse Siguiente para continuar. Si desea seleccionar una\
    carpeta diferente, pulse Examinar."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Carpeta Destino"
}

SelectProgramFolder {
    Title
    "Seleccione Grupo de Programas"

    Subtitle
    "Por favor, seleccione un grupo de programas."

    Caption
    "Se instalarán iconos en el Grupo de Programas siguiente.\
    Puede escribir un nuevo nombre de grupo o seleccionarlo\
    de la lista de grupos existentes.\
    Pulse Siguiente para continuar."

    Message
    ""

    ProgramFolderLabel
    "Grupo de Programas:"

    FolderListLabel
    "Grupos Existentes:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Crear grupo de programas para todos los usuarios"
}

SetupComplete {
    Caption
    "Instalación Completa"

    Message
    "Se ha instalado <%AppName%> con éxito. \
     Pulse Finalizar para salir de este wizard."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Tipo de Instalación"

    Subtitle
    "Seleccione el tipo de instalación que más se ajuste a sus necesidades."

    Caption
    "Pulse el tipo de instalación que prefiere."

    Message
    ""

    DescriptionLabel
    "Descripción"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Comenzar a Copiar Archivos"

    Subtitle
    "Revise la configuración antes de copiar los archivos"

    Caption
    "Se ha recopilado la información necesaria para comenzar a copiar los\
    archivos del programa. Si desea revisar o cambiar la configuración,\
    pulse Atrás. Si está conforme con la configuración, pulse Siguiente para\
    comenzar a copiar los archivos."

    Message
    ""

    Text
    "Directorio de Instalación:
            <%InstallDir%>

    Tipo de Instalación:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Desinstalar"

    Subtitle
    "Desinstalar <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Desinstalación Completa"

    Message
    "<%AppName%> ha sido eliminado de su sistema."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Detalles de Desinstalación"

    Subtitle
    "Errores durante la eliminación"

    Caption
    "Ocurrieron los siguientes errores durante el proceso de desinstalación:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Información de Usuario"

    Subtitle
    "Por favor introduzca sus datos de usuario."

    Caption
    "Por favor introduzca el nombre de la empresa para la que trabaja."

    Message
    ""

    UserNameLabel
    "Nombre de Usuario:"

    CompanyLabel
    "Empresa:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Bienvenido al InstallJammer Wizard para <%AppName%>"

    Message
    "Este programa instalará <%AppName%> versión <%Version%> en su equipo.\
    \n\nSe recomienda cerrar las demás aplicaciones antes de continuar. \
    \n\nPulse Siguiente para continuar o Cancelar para salir de la instalación."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/fr.msg.








































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
ChooseComponents {
    Title
    "Sélectionnez les composants"

    Subtitle
    "Sélectionnez les composants devant être installés."

    Caption
    "Sélectionner les composants à installer et déselectionner les composants à ne pas installer."

    Message
    "<%SpaceRequiredText%> d'espace requis"

    DescriptionLabel
    "Description"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Installation"

    Subtitle
    "Installation de <%AppName%>"

    Caption
    "Patientez pendant l'installation de <%AppName%> sur votre ordinateur."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Saisir la légende ici."

    Message
    "Saisir le message ici."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Titre"

    Subtitle
    "Sous-titre"

    Caption
    "Légende"

    Message
    "Message"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Titre"

    Subtitle
    "Sous-titre"

    Caption
    "Légende"

    Message
    "Message"

    Text
    "Saisissez votre texte personnalisé ici."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Accord de licence"

    Subtitle
    "Veuillez lire attentivement l'accord de licence suivant SVP."

    AcceptRadiobutton
    "J'accepte les termes de cet accord de licence."

    DeclineRadiobutton
    "Je n'accepte pas les termes de cet accord de licence."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Readme"

    Subtitle
    "Readme pour <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Sélectionnez le répertoire d'installation"

    Subtitle
    "Où installer <%AppName%> ?"

    Caption
    "L'installation de <%AppName%> s'effectuera dans le répertoire suivant.\n\nPour installer\
     dans ce répertoire, cliquez sur le bouton SUIVANT.\n\nPour installer dans un autre répertoire, cliquez\
     sur le bouton PARCOURIR et sélectionnez un autre répertoire."

    Message
    ""

    BrowseText
    "Pour continuer, cliquez sur SUIVANT.  Pour sélectionner un répertoire\
     différent, cliquez sur PARCOURIR."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Répertoire d'installation"
}

SelectProgramFolder {
    Title
    "Sélectionnez le dossier Programme"

    Subtitle
    "Sélectionnez un dossier Programme SVP."

    Caption
    "L'installation ajoutera les icônes de programme au dossier Programme affiché ci-dessous. \
     Vous pouvez saisir un nouveau nom de dossier ou en sélectionner un dans la liste des dossiers existants. \
     Cliquez sur SUIVANT pour continuer."

    Message
    ""

    ProgramFolderLabel
    "Dossier Programme:"

    FolderListLabel
    "Dossiers existants :"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Créer le dossier programme pour tous les utilisateurs"
}

SetupComplete {
    Caption
    "L'assistant InstallJammer est terminé"

    Message
    "L'assistant InstallJammer a installé <%AppName%> avec succès. \
     Cliquez sur TERMINER pour quitter l'assistant."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Type d'installation"

    Subtitle
    "Sélectionnez le type d'installation convenant le mieux à vos besoins."

    Caption
    "Cliquez sur le type d'installation que vous souhaitez."

    Message
    ""

    DescriptionLabel
    "Description"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Copie des fichiers"

    Subtitle
    "Contrôle du paramétrage avant la copie de fichiers"

    Caption
    "L'installeur a maintenant assez d'informations pour commencer à copier les fichiers.  Si\
     vous voulez revoir ou modifier le paramétrage, cliquez sur PRECEDENT.  Si vous êtes\
     satisfait du paramétrage, cliquez sur suivant pour commencer à copier les fichiers."

    Message
    ""

    Text
    "Répertoire d'installation:
            <%InstallDir%>

    Type d'installation:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Désinstallation"

    Subtitle
    "Désinstallation de <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Désinstallation terminée"

    Message
    "<%AppName%> a été désinstallé de votre système."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Details de la désinstallation"

    Subtitle
    "Des erreurs sont apparues pendant la désinstallation"

    Caption
    "Les erreurs suivantes sont apparues pendant la désinstallation:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Information client"

    Subtitle
    "Saisissez vos informations SVP."

    Caption
    "Saisissez votre nom et votre société."

    Message
    ""

    UserNameLabel
    "Nom:"

    CompanyLabel
    "Société:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Bienvenue dans l'assistant d'installation InstallJammer pour <%AppName%>"

    Message
    "Ceci installera <%AppName%> version <%Version%> sur votre ordinateur. \
    \n\nIl est recommandé de fermer toutes les autres applications avant\
    de continuer.\n\nCliquez sur SUIVANT pour continuer ou ANNULER pour quitter l'installation."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/hu.msg.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
ChooseComponents {
    Title
    "Komponensek kiválasztása"

    Subtitle
    "Válassza ki a telepítend\u0151 komponenseket."

    Caption
    "Válassza ki azokat a komponenseket, amelyeket fel akar telepíteni,\
     és ne válassza ki azokat, amelyeket nem akar telepíteni."

    Message
    "<%SpaceRequiredText%> szabad hely szükséges"

    DescriptionLabel
    "Leírás"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Telepítés"

    Subtitle
    "<%AppName%> telepítése"

    Caption
    "Kérem várjon, amíg a Telepít\u0151 a <%AppName%> programot feltelepíti a gépére."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "A fejléc jön ide."

    Message
    "Az üzenet jön ide."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Cím"

    Subtitle
    "Alcím"

    Caption
    "Leírás"

    Message
    "Üzenet"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Cím"

    Subtitle
    "Alcím"

    Caption
    "Leírás"

    Message
    "Üzenet"

    Text
    "A saját szövegedet rakd ide."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Licensz elfogadása"

    Subtitle
    "Kérem olvassa el figyelmesen a következ\u0151 licensz megállapodást."

    AcceptRadiobutton
    "Elfogadom a licensz megállapodás feltételeit."

    DeclineRadiobutton
    "Nem fogadom el a licensz megállapodás feltételeit."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Olvassa el információk"

    Subtitle
    "Olvassa el információk a <%AppName%> alkalmazáshoz"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Válassza ki a cél könyvtárat"

    Subtitle
    "Hova kellene a <%AppName%> alkalmazást telepíteni?"

    Caption
    "A telepít\u0151 a <%AppName%> programot a következ\u0151 könyvtárba telepíti.\n\n
     Ahhoz, hogy ebbe könyvtárba kerüljön kattintson a <%Next%> gombra\
     Ahhoz, hogy más könyvtárba kerüljön kattintson a <%Browse%> gombra."

    Message
    ""

    BrowseText
    "A folytatáshoz nyomja meg a <%Next%> gombot. \
     Ha másik könyvtárat szeretne kiválasztani nyomja meg a <%Browse%> gombot."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Cél könyvtár"
}

SelectProgramFolder {
    Title
    "Program mappa kiválasztás"

    Subtitle
    "Kérem válassza ki a program mappát!"

    Caption
    "A telepít\u0151 a program ikonokat a lentebb listázott Program mappához fogja hozzáadni. \
	 Megváltoztathatja az új mappa nevét, vagy kiválaszthat egy már létez\u0151t a listáról. \
     Kattintson a <%Next%> gombra a folytatáshoz."

    Message
    ""

    ProgramFolderLabel
    "Program mappa:"

    FolderListLabel
    "Létez\u0151 mappák:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Létrehozza a program mappát az összes felhasználónak?"
}

SetupComplete {
    Caption
    "InstallJammer Varázsló befejez\u0151dött"

    Message
    "Az InstallJammer Varázsló sikeresen telepítette a <%AppName%> alkalmazást. \
	 Kattintson a <%Finish%> gombra ahhoz, hogy kilépjen a varázslóból."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Telepítés típusa"

    Subtitle
    "Válassza ki az Önnek legjobban megfelel\u0151 telepítési módot."

    Caption
    "Válassza ki a kívánt telepítési típust!"

    Message
    ""

    DescriptionLabel
    "Leírás"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Állományok másolásának elkezdése"

    Subtitle
    "Tekintse át a beállításokat, miel\u0151tt átmásolnánk az állományokat!"

    Caption
    "A telepít\u0151nek elég információja van ahhoz, hogy a program állományait\
	elkezdje másolni. Ha meg akarja nézni vagy változtatni a beállításokat,\
	akkor kattintson a <%Back%> gombra. Ha elégedett a beállításokkal, akkor\
	kattintson a <%Next%> gombra, hogy elkezd\u0151djön a fájlok másolása."

    Message
    ""

    Text
    "Telepítési könyvtár:
            <%InstallDir%>

    Telepítés típusa:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Eltávolítás"

    Subtitle
    "A <%AppName%> alkalmazás eltávolítása"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Eltávolítás befejez\u0151dött"

    Message
    "A <%AppName%> alkalmazás el lett távolítva a rendszerér\u0151l."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Eltávolítás részletei"

    Subtitle
    "Az eltávolítás alatt hiba lépett fel!"

    Caption
    "A következ\u0151 hibák léptek fel az eltávolítás alatt:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Vásárlói információk"

    Subtitle
    "Kérem írja ide az információkat."

    Caption
    "Kérem írja be a nevét és a munkahelyének nevét."

    Message
    ""

    UserNameLabel
    "Felhasználó neve:"

    CompanyLabel
    "Cég:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Isten hozta a <%AppName%> InstallJammer Varázslójában"

    Message
    "Ez a <%AppName%> alkalmazás <%Version%> verzióját fogja telepíteni\
	a számítógépére.\n\n Javasoljuk, hogy zárjon be minden alkalmazást,\
	miel\u0151tt folytatná.\n\n Kattintson a <%Next%> gombra a folytatáshoz\
	vagy a <%Cancel%> gombra kilépéshez."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

InstallPassword {
    Title
    "Jelszavas telepítés"

    Subtitle
    "Ez a telepítés egy jelszót igényel a folytatáshoz."

    Caption
    "Kérem gépelje be a jelszót."

    Message
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/it.msg.






































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
ChooseComponents {
    Title
    "Selezionare le parti"

    Subtitle
    "Selezionare le parti che saranno installate dal programma."

    Caption
    "Selezionare le parti che si desidera installare e deselezionare le\
     parti che non si desidera installare."

    Message
    "<%SpaceRequiredText%> di spazio richiesto"

    DescriptionLabel
    "Descrizione"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Installazione in corso"

    Subtitle
    "Installazione di <%AppName%>"

    Caption
    "Si prega di attendere mentre il programma installa <%AppName%> sul\
     computer."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "La didascalia va qui."

    Message
    "Il messaggio va qui."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Titolo"

    Subtitle
    "Sottotitolo"

    Caption
    "Didascalia"

    Message
    "Messaggio"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Titolo"

    Subtitle
    "Sottotitolo"

    Caption
    "Didascalia"

    Message
    "Messaggio"

    Text
    "Inserire qui il testo personalizzato."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Contratto di Licenza"

    Subtitle
    "Si prega di leggere attentamente il contratto di licenza che segue."

    AcceptRadiobutton
    "Accetto le condizioni del Contratto di licenza."

    DeclineRadiobutton
    "Non accetto le condizioni del Contratto di licenza."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Informazioni da leggere"

    Subtitle
    "Informazioni da leggere riguardo a <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Scegliere la directory  di destinazione"

    Subtitle
    "Dove si desidera installare <%AppName%>?"

    Caption
    "Il programma di installazione installerà <%AppName%> nella seguente\
     cartella.\n\nPer installare in questa cartella, premere su Avanti. \
     Per installare in una cartella diversa, premere su Sfoglia e\
     selezionare un'altra cartella."

    Message
    ""

    BrowseText
    "Per proseguire, premere su Avanti. Se si desidera selezionare una\
     cartella diversa, premere su Sfoglia."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Cartella di destinazione"
}

SelectProgramFolder {
    Title
    "Selezionare la cartella del programma"

    Subtitle
    "Si prega di selezionare la cartella del programma."

    Caption
    "Il programma di installazione aggiungerà le icone del programma nella\
     cartella elencata sotto. \
     Si può inserire il nome di una nuova cartella o selezionarla dalla\
     lista delle cartelle esistenti. \
     Premere su Avanti per proseguire."

    Message
    ""

    ProgramFolderLabel
    "Cartella del programma:"

    FolderListLabel
    "Cartelle esistenti:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Crea la cartella del programma per tutti gli utenti"
}

SetupComplete {
    Caption
    "Autocomposizione di InstallJammer completata"

    Message
    "L'autocomposizione di InstallJammer ha installato <%AppName%> con\
     successo. Premere su Fine per uscire dall'autocomposizione."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Tipologia di installazione"

    Subtitle
    "Selezionare la tipologia di installazione più adatta alle proprie esigenze."

    Caption
    "Scegliere la tipologia di installazione che si preferisce."

    Message
    ""

    DescriptionLabel
    "Descrizione"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Inizio della copia dei file"

    Subtitle
    "Controllo delle impostazioni prima della copia dei file"

    Caption
    "Il programma di installazione ha sufficienti informazioni per iniziare\
     la copia dei file del programma. Se si desidera controllare o\
     modificare le impostazioni, premere Indietro. Se si è soddisfatti\
     delle impostazioni, premere Avanti per iniziare a copiare i file."

    Message
    ""

    Text
    "Directory di installazione:
            <%InstallDir%>

    Tipologia di installazione:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Disinstallazione in corso"

    Subtitle
    "Disinstallazione di <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Disinstallazione completata"

    Message
    "<%AppName%> è stato rimosso dal sistema."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Dettagli della disinstallazione"

    Subtitle
    "Durante la rimozione sono occorsi degli errori"

    Caption
    "I seguenti errori sono occorsi durante la rimozione:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Informazioni sul cliente"

    Subtitle
    "Si prega di inserire le informazioni."

    Caption
    "Si prega di inserire il proprio nome e il nome della società per cui\
     si lavora."

    Message
    ""

    UserNameLabel
    "Nome dell'utente:"

    CompanyLabel
    "Società:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Benvenuti nell'autocomposizione di InstallJammer per <%AppName%>"

    Message
    "Si sta per installare <%AppName%> nella versione <%Version%>\
     sul computer. \
     \n\nE' consigliata la chiusura di tutte le altre applicazioni prima di\
     proseguire.\n\nPremere su Avanti per continuare o su Annulla per uscire dall'installazione."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

InstallPassword {
    Title
    "Parola chiave di installazione"

    Subtitle
    "L'installazione richiede una parola chiave per proseguire."

    Caption
    "Si prega di inserire la parola chiave."

    Message
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/lt.msg.






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
ChooseComponents {
    Title
    "Pasirenkamasis ádiegimas"

    Subtitle
    "Pasirinkite komponentus kuriuos diegimo programa ádiegs."

    Caption
    "Paþymëkite komponentus kuriuos norite ádiegti ir atþymëkite\
     tuos kuriuos nenorite ádiegti."


    Message
    "Reikës <%SpaceRequiredText%> talpos"

    DescriptionLabel
    "Apraðymas"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Diegiama"

    Subtitle
    "Diegiama <%AppName%>"

    Caption
    "Praðom palaukti kol diegimo programa ádiegs <%AppName%> á jûsø kompiuterá."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Áveskite pavadinimà."

    Message
    "Áveskite praneðimà."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Antraðtë"

    Subtitle
    "Paantraðtë"

    Caption
    "Pavadinimas"

    Message
    "Praneðimas"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Antraðtë"

    Subtitle
    "Paantraðtë"

    Caption
    "Pavadinimas"

    Message
    "Praneðimas"

    Text
    "Áveskite pasirinktà teskta."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Sutikimas su licencija"

    Subtitle
    "raðom perskaityti ðá sutikimà su licencija."

    Text
    "Patalpinkite èia savo licencijà."

    AcceptRadiobutton
    "Að sutinku su licencija."

    DeclineRadiobutton
    "Að nesutinku su licencija."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Skaityti daugiau informacijos"

    Subtitle
    "Skaityti daugiau informacijos apie <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    "Patalpinkite informacija."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Pasirinkite paskirties vietà"

    Subtitle
    "Kur turëtø bûti <%AppName%> ádiegta?"

    Caption
     "Diegimo programa ádiegs <%AppName%> á ðá katalogà.\n\nTam kad instaliuoti\
     á ðá katalogà, paspauskite <%Next%>.\n\nÁdiegimui á kita katalogà,\
     paspauskite <%Browse%> ir pasirinkite kità katalogà."

    Message
    ""

    BrowseText
    "Tam kad instaliuoti á ðá katalogà, paspauskite <%Next%>. Ádiegimui á
     kita katalogà, paspauskite <%Browse%> ir pasirinkite kità katalogà."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Paskirties katalogas"
}

SelectProgramFolder {
    Title
    "Pasirinkite programos katalogà"

    Subtitle
    "Praðom pasirinkite programos katalogà"

    Caption
    "Diegimo programa ákels programos ikonas á programø katalogà pavaizduotà\
     apaèioje.  Galite ávesti naujà katalogo pavadinimà arba pasirinkti ið\
     esanèiø.  Norëdami tæsti <%Next%>."

    Message
    ""

    ProgramFolderLabel
    "Programos katalogas:"

    FolderListLabel
    "Esantys katalogai:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Sukurti programos katalogus visiems vartotojams"
}

SetupComplete {
    Caption
    "InstallJammer vedlys pabaigë darbà"

    Message
    "Diegimo programa baigë diegti <%AppName%> á jûsø kompiuterá.  Paspauskite\
    <%Finish%>, kad uþbaigti diegimà."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Diegimo tipas"

    Subtitle
    "Pasirinkite diegimo tipà kurio pageidaujate."

    Caption
    "Pasirinkite diegimo tipà kurio pageidaujate."

    Message
    ""

    DescriptionLabel
    "Apraðymas"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Pradedamas failø kopijavimas"

    Subtitle
    "Perþiûrëkite nustatymus prieð pradedant kopijuoti failus"

    Caption
    "Diegimo programa turi pakankamai informacijos, kad pradëti kopijuoti programos failus.\
     Jei norite perþiûrëti arba pakeisti nustatymus, spauskite <%Back%>. Jei nustatymai\
     tenkina, spauskite <%Next%>, kad pradëti kopijuoti failus."

    Message
    ""

    Text
    "Diegimo katalogas:
            <%InstallDir%>

    Diegimo tipas:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Uninstalling"

    Subtitle
    "Paðalinama <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Programos paðalinimas baigtas"

    Message
    "<%AppName%> buvo paðalinta ið jûsø sistemos."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Programos paðalinimas iðsamiau"

    Subtitle
    "Klaidos atsitikusios per programos paðalinimà"

    Caption
    "Klaidos atsitikusios per programos paðalinimà:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Vartotojo informacija"

    Subtitle
    "Praðome ávesti savo informacijà."

    Caption
    "Áveskite savo vardà ir organizacijà kurioje dirbate."

    Message
    ""

    UserNameLabel
    "Vartotojo vardas:"

    CompanyLabel
    "Organizacija:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Sveiki atvyke á <%AppName%> diegimo programà."

    Message
    "Pabrëþtinai patartina iðeiti ið visø Windows programø kurias esate\
     pasileidæ. Spauskite <%Next%> tam, kad tæsti diegimà."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

InstallPassword {
    Title
    "Diegimo slaptaþodis"

    Subtitle
    "Ðiam diegimui reikia slaptaþodþio."

    Caption
    "Praðom ávesti slaptaþodá."

    Message
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/nl.msg.
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
ChooseComponents {
    Title
    "Selecteer Componenten"

    Subtitle
    "Selecteer de componenten die het installatie programma zal installeren."

    Caption
    "Selecteer de componenten die u wilt installeren en deselecteer de componenten\
     die u niet wilt installeren."

    Message
    "<%SpaceRequiredText%> aan ruimte benodigd"

    DescriptionLabel
    "Omschrijving"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Installeren"

    Subtitle
    "<%AppName%> installeren"

    Caption
    "Een ogenblik geduld terwijl <%AppName%> wordt geïnstalleerd op uw computer."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Bijschrift hier."

    Message
    "Bericht hier."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Titel"

    Subtitle
    "Ondertitel"

    Caption
    "Bijschrift"

    Message
    "Bericht"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Titel"

    Subtitle
    "Ondertitel"

    Caption
    "Bijschrift"

    Message
    "Bericht"

    Text
    "Zet uw eigen tekst hier."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Licentie Overeenkomst"

    Subtitle
    "Lees de licentie overeenkomst aandachtig."

    AcceptRadiobutton
    "Ik ga akkoord met de licentie overeenkomst."

    DeclineRadiobutton
    "Ik ga NIET akkoord met de licentie overeenkomst."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "Stop Installatie"
}

Readme {
    Title
    "Readme Informatie"

    Subtitle
    "Readme Informatie voor <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Kies de installatie map"

    Subtitle
    "Waar moet <%AppName%> worden geïnstalleerd?"

    Caption
    "Dit installatie programma zal <%AppName%> in de onderstaande map installeren."


    Message
    ""

    BrowseText
    "Als u de installatie locatie wilt wijzigen klikt u op 'Selecteer map' en selecteert u een nieuwe locatie.
     Om verder te gaan met het installatieproces klikt u op Volgende."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Installatie map"
}

SelectProgramFolder {
    Title
    "Selecteer Programma Map"

    Subtitle
    "U kunt de Programma map selecteren."

    Caption
    "Het installatie programma zal de programma iconen toevoegen aan de onderstaande Programma map. \
     U kunt een nieuwe map aanmaken of een bestaande map selecteren uit de lijst. \
     Klik op Volgende om door te gaan."

    Message
    ""

    ProgramFolderLabel
    "Programma map:"

    FolderListLabel
    "Huidige mappen:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Maak programma map voor alle gebruikers"
}

SetupComplete {
    Caption
    "Installatie Programma Afgerond"

    Message
    "Het installatie programma heeft <%AppName%> succesvol geïnstalleerd. \
     Klik op <%Finish%> om het installatie programma te sluiten."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Setup Type"

    Subtitle
    "Kies het type setup dat u prefereerd."

    Caption
    "Kies het type setup dat u prefereerd."

    Message
    ""

    DescriptionLabel
    "Omschrijving"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Start Kopiëren Bestanden"

    Subtitle
    "Bekijk uw instellingen voordat het installeren begint"

    Caption
    "Het installatie programma heeft genoeg informatie om het kopiëren te starten. \
     Als u de instellingen wilt bekijken of wijzigen kunt op <%Back%> klikken.  Als u\
     tevreden bent met de instellingen klikt u op <%Next%> om het kopiëren te starten."

    Message
    ""

    Text
    "Installatie directory:
            <%InstallDir%>

    Setup type:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Deïnstalleren"

    Subtitle
    "<%AppName%> deïnstalleren"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Deïnstallatie afgerond"

    Message
    "<%AppName%> is van uw systeem verwijderd."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Deïnstallatie Details"

    Subtitle
    "Er hebben zich fouten voorgedaan tijdens de deïnstallatie"

    Caption
    "De volgende fouten hebben zicht voorgedaan tijdens de deïnstallatie:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Gebruikers Informatie"

    Subtitle
    "Vul uw informatie in."

    Caption
    "Vul uw naam en uw bedrijfsnaam in."

    Message
    ""

    UserNameLabel
    "Naam:"

    CompanyLabel
    "Bedrijfsnaam:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Welkom bij het <%AppName%> installatie programma.  Dit programma zal\
     <%AppName%> op uw computer installeren."

    Message
    "Het is aan te raden alle overige applicaties te sluiten alvorens\
     verder te gaan met deze installatie.\n\nKlik op <%Next%> om verder\
     te gaan of op <%Cancel%> om deze installatie af te breken"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

InstallPassword {
    Title
    "Installatie Wachtwoord"

    Subtitle
    "Deze installatie vereist een wachtwoord om door te kunnen gaan."

    Caption
    "Vul uw wachtwoord in."

    Message
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/pl.msg.
















































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# options: -encoding utf-8

ChooseComponents {
    Title
    "Wybierz komponenty"

    Subtitle
    "Wybierz komponenty do zainstalowania."

    Caption
    "Zaznacz komponenty, które chcesz zainstalować, a odznacz te,\
     których nie chcesz instalować."

    Message
    "Wymagane miejsce na dysku: <%SpaceRequiredText%>"

    DescriptionLabel
    "Opis"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Instalowanie"

    Subtitle
    "Instalowanie <%AppName%>"

    Caption
    "Proszę czekać podczas, gdy Instalator instaluje <%AppName%> na twoim komputerze."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Caption goes here."

    Message
    "Message goes here."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Tytuł"

    Subtitle
    "Podtytuł"

    Caption
    "Nagłówek"

    Message
    "Wiadomość"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Tytuł"

    Subtitle
    "podtytuł"

    Caption
    "Nagłówek"

    Message
    "Wiadomość"

    Text
    "Tutaj wpisuj swój tekst."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Warunki licencji"

    Subtitle
    "Proszę uważnie przeczytać poniższą licencję."

    AcceptRadiobutton
    "AkceptujÄ™ warunki licencji."

    DeclineRadiobutton
    "Nie akceptuję warunków licencji."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Informacje Readme"

    Subtitle
    "Informacje Readme dla <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Wybierz folder docelowy"

    Subtitle
    "Gdzie zainstalować <%AppName%>?"

    Caption
    "Instalator zainstaluje <%AppName%> w wybranym folderze.\n\nAby instalować\
     w tym folderze, kliknij Dalej.  Aby zainstalować w innym folderze, kliknij\
     PrzeglÄ…daj i wybierz inny folder."

    Message
    ""

    BrowseText
    "Aby kontynuować, kliknij Dalej.  Jeśli chcesz wybrać inny folder,\
     kliknij PrzeglÄ…daj."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Folder docelowy"
}

SelectProgramFolder {
    Title
    "Wybierz folder programu"

    Subtitle
    "Przoszę wybrać folder dla programu."

    Caption
    "Instalator doda ikonki programu w folderze aplikacji wybranym poniżej. \
     Możesz wprowadzić nową nazwę folderu lub wybrać z listy już istniejących. \
     Kliknij Dalej, aby kontynuować."

    Message
    ""

    ProgramFolderLabel
    "Folder programu:"

    FolderListLabel
    "IstniejÄ…ce foldery:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Utwórz folder programu dla wszystkich użytkowników"
}

SetupComplete {
    Caption
    "InstallJammer - Instalacja zakończona"

    Message
    "Instalator InstallJammer zainstalował pomyślnie <%AppName%>. \
     Kliknij Zakończ, aby opuścić instalator."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Typ instalacji"

    Subtitle
    "Wybierz typ instalacji, który Ci odpowiada."

    Caption
    "Kliknij preferowany typ instalacji."

    Message
    ""

    DescriptionLabel
    "Opis"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Rozpocznij kopiowanie plików"

    Subtitle
    "Pokaż ustawienia przed rozpoczęciem kopiowania plików"

    Caption
    "Instalator posiada już wszystkie informacje potrzebnedo rozpoczęcia\
     kopiowania plików. Jeśli chcesz zobaczyć ustawienia lub zmienić je,\
     kliknij Wstecz. Jeśli jesteś pewien ustawień, kliknij Dalej, aby\
     rozpocząć kopiowanie plików."

    Message
    ""

    Text
    "Folder docelowy:
            <%InstallDir%>

    Typ instalacji:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Usuwanie"

    Subtitle
    "Deinstalacja <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Usuwanie zakończone"

    Message
    "Usunięto pomyślnie <%AppName%> z twojego systemu."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Detale deinstalacji"

    Subtitle
    "Błędy podczas usuwania"

    Caption
    "Napotkano następujące błędy podczas usuwania:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Informacje o kliencie"

    Subtitle
    "Proszę wpisać swoje dane."

    Caption
    "Proszę podać nazwisko i nazwę firmy, dla której pracujesz."

    Message
    ""

    UserNameLabel
    "Nazwa użytkownika:"

    CompanyLabel
    "Firma:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Witamy w InstallJammer - instalatorze dla <%AppName%>"

    Message
    "Zainstaluje on <%AppName%> w wersji <%Version%> na twoim komputerze. \
    \n\nZalecane jest zamknięcie wszystkich programów przed instalacją. \
    \n\nKliknij Dalej, aby kontynuować lub Anuluj, aby opuścić instalator."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/pt_br.msg.


































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
ChooseComponents {
    Title
    "Selecionar Componentes"

    Subtitle
    "Selecione os componentes que seão instalados."

    Caption
    "Selecione os componentes que você quer instalar e deselecione os componentes\
     que você não quer instalar."

    Message
    "<%SpaceRequiredText%> de espaço é necessário"

    DescriptionLabel
    "Descrição"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Instalando"

    Subtitle
    "Instalando <%AppName%>"

    Caption
    "Por favor, aguarde enquanto o programa <%AppName%> é instalado em seu computador."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Caption irá aqui."

    Message
    "Mensagem irá aqui."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Título"

    Subtitle
    "Subtítulo"

    Caption
    "Caption"

    Message
    "Mensagem"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Título"

    Subtitle
    "Subtítulo"

    Caption
    "Caption"

    Message
    "Mensagem"

    Text
    "Coloque seu texto personalizado aqui."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Concordância com a Licença"

    Subtitle
    "Por favor, leia os termos da licença cuidadosamente."

    AcceptRadiobutton
    "Eu concordo os termos da licença."

    DeclineRadiobutton
    "Eu não concordo com os termos da licença."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Informações do Readme"

    Subtitle
    "Informações do Readme para <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Escolha a localização de destino"

    Subtitle
    "Onde o <%AppName%> deverá ser instalado?"

    Caption
    "A Instalação irá instalar <%AppName%> na seguinte pasta.\n\nPara instalar\
     nesta pasta, clique em Próximo.  Para instalar em uma pasta diferente, clique\
     em Procurar e selecione outra pasta."

    Message
    ""

    BrowseText
    "Para continuar, clique em Próximo.  Se você deseja selecionar uma pasta diferente,\
     clique em Procurar."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Pasta de Destino"
}

SelectProgramFolder {
    Title
    "Selecione a Pasta de Programas"

    Subtitle
    "Por favor, selecione uma pasta de programa."

    Caption
    "A Instalação adicionará os ícones do programa Pasta de Programas listada abaixo. \
     Você poderá digitar um novo nome de pasta or selecionar uma das pastas da lista. \
     Clique em Próximo para continuar."

    Message
    ""

    ProgramFolderLabel
    "Pasta de Programas:"

    FolderListLabel
    "Pastas Existentes:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Criar uma pasta de programa para todos os usuários"
}

SetupComplete {
    Caption
    "Assistente InstallJammer Concluído"

    Message
    "O Assistente InstallJammer instalou com sucesso o <%AppName%>. \
     Clique em Concluir para sair do assistente."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Tipo de Instalação"

    Subtitle
    "Seleciona o tipo de instalação que melhor de adapta às suas necessidades."

    Caption
    "Clique no tipo de Instalação de sua preferência."

    Message
    ""

    DescriptionLabel
    "Descrição"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Iniciar Cópia de Arquivos"

    Subtitle
    "Reveja as configurações antes de copiar os arquivos"

    Caption
    "A Instalação tem bastante informação para iniciar a cópia dos arquivos do programa.  Se\
     você deseja revisar or mudar qualquer configuração, clique em Voltar.  Se você está\
     satisfeito com as configurações, clique em Próximo para iniciar a cópia dos arquivos."

    Message
    ""

    Text
    "Diretório de Instalação:\n\t<%InstallDir%>\n\nTipo de Instalação:\n\t<%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Desinstalando"

    Subtitle
    "Desinstalando <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Desinstalação Concluída"

    Message
    "<%AppName%> foi removido do seu sistema."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Detalhes de Desinstalação"

    Subtitle
    "Erros ocurreram durante a desinstalação"

    Caption
    "Os seguintes error ocorreram durante a desinstalação:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Informações do Proprietário"

    Subtitle
    "Por favor, digite as tuas informações."

    Caption
    "Por favor, digite seu nome e o nome da empresa onde você trabalha."

    Message
    ""

    UserNameLabel
    "Nome do Usuário:"

    CompanyLabel
    "Empresa:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Bem vindo ao Assistente InstallJammer para o <%AppName%>"

    Message
    "Será instalado <%AppName%> version <%Version%> em seu computador. \
    \n\nÉ recomendado que você feche todos os outros programas antes de continuar. \n\n
    Clique em Próximo para continuar ou em Cancelar para sair da Instalação."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/ru.msg.
































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
# options: -encoding utf-8

ChooseComponents {
    Title
    "Âûáîð êîìïîíåíò äëÿ óñòàíîâêè"

    Subtitle
    "Âûáåðèòå êîìïîíåíòû, êîòîðûå âû õîòèòå óñòàíîâèòü."

    Caption
    "Îòìåòüòå êîìïîíåíòû, êîòîðûå âû õîòèòå óñòàíîâèòü, è ñíèìèòå îòìåòêó\
     ñ òåõ êîìïîíåíò, êîòîðûå âû íå æåëàåòå óñòàíàâëèâàòü."

    Message
    "Äëÿ óñòàíîâêè òðåáóåòñÿ <%SpaceRequiredText%> íà æåñòêîì äèñêå"

    DescriptionLabel
    "Îïèñàíèå"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CopyFiles {
    Title
    "Óñòàíîâêà"

    Subtitle
    "Óñòàíîâêà <%AppName%>"

    Caption
    "Èä¸ò óñòàíîâêà <%AppName%> íà Âàø êîìïüþòåð. Ïîæàëóéñòà, ïîäîæäèòå."

    Message
    ""

    FileLabel
    "<%Status%>"

    ProgressValue
    "<%InstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane1 {
    Caption
    "Çäåñü äîëæíà áûòü ïîäïèñü."

    Message
    "Çäåñü äîëæíî áûòü ñîîáùåíèå."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomBlankPane2 {
    Title
    "Çàãîëîâîê"

    Subtitle
    "Ïîäçàãîëîâîê"

    Caption
    "Ïîäïèñü"

    Message
    "Ñîîáùåíèå"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

CustomTextPane1 {
    Title
    "Çàãîëîâîê"

    Subtitle
    "Ïîäçàãîëîâîê"

    Caption
    "Ïîäïèñü"

    Message
    "Ñîîáùåíèå"

    Text
    "Çäåñü âïèøèòå òåêñò."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

License {
    Title
    "Ëèöåíçèîííîå Ñîãëàøåíèå"

    Subtitle
    "Ïîæàëóéñòà, âíèìàòåëüíî ïðî÷òèòå ïðèâåä¸ííîå íèæå ëèöåíçèîííîå ñîãëàøåíèå."

    Text
    "Çäåñü äîëæíî áûòü ëèöåíçèîííîå ñîãëàøåíèå."

    AcceptRadiobutton
    "ß ïðèíèìàþ ïîëîæåíèÿ ëèöåíçèîííîãî ñîãëàøåíèÿ."

    DeclineRadiobutton
    "ß íå ïðèíèìàþ ïîëîæåíèÿ ëèöåíçèîííîãî ñîãëàøåíèÿ."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Readme {
    Title
    "Èíôîðìàöèÿ"

    Subtitle
    "Èíôîðìàöèÿ î <%AppName%>"

    Caption
    ""

    Message
    ""

    Text
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SelectDestination {
    Title
    "Óêàæèòå êàòàëîã íàçíà÷åíèÿ"

    Subtitle
    "Ãäå íóæíî óñòàíîâèòü <%AppName%> ?"

    Caption
    "<%AppName%> áóäåò óñòàíîâëåíà â óêàçàííûé íèæå êàòàëîã.\n\n×òîáû ïðîèçâåñòè óñòàíîâêó\
     â ýòîò êàòàëîã, ù¸ëêíèòå ïî <%Next%>.  ×òîáû ïðîèçâåñòè óñòàíîâêó â äðóãîé êàòàëîã, ù¸ëêíèòå\
     ïî <%Browse%>."

    Message
    ""

    BrowseText
    "Äëÿ ïðîäîëæåíèÿ ù¸ëêíèòå ïî <%Next%>. Äëÿ óêàçàíèÿ äðóãîãî êàòàëîãà ù¸ëêíèòå ïî <%Browse%>."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    BrowseButton
    "<%Browse%>"

    DestinationLabel
    "Êàòàëîã íàçíà÷åíèÿ"
}

SelectProgramFolder {
    Title
    "Óêàæèòå ïðîãðàììíóþ ãðóïïó"

    Subtitle
    "Ïîæàëóéñòà, âûáåðèòå ïðîãðàììíóþ ãðóïïó."

    Caption
    "ßðëûêè ïðîãðàììû áóäóò äîáàâëåíû â óêàçàííóþ íèæå ïðîãðàììíóþ ãðóïïó. \
     Âû ìîæåòå óêàçàòü äðóãóþ ãðóïïó, ëèáî âûáðàòü ãðóïïó èç ñïèñêà ñóùåñòâóþùèõ. \
     Äëÿ ïðîäîëæåíèÿ ù¸ëêíèòå ïî <%Next%>."

    Message
    ""

    ProgramFolderLabel
    "Ïðîãðàììíàÿ ãðóïïà:"

    FolderListLabel
    "Ñóùåñòâóþùèå ïðîãðàììíûå ãðóïïû:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"

    AllUsersCheckbutton
    "Ñîçäàòü ïðîãðàììíóþ ãðóïïó äëÿ âñåõ ïîëüçîâàòåëåé"
}

SetupComplete {
    Caption
    "Óñòàíîâêà çàâåðøåíà"

    Message
    "Ìàñòåð InstallJammer óñïåøíî óñòàíîâèë <%AppName%>. \
     Âûáåðèòå <%Finish%>, ÷òîáû çàêðûòü ìàñòåð."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

SetupType {
    Title
    "Òèï óñòàíîâêè"

    Subtitle
    "Âûáåðèòå òèï óñòàíîâêè, êîòîðûé âàì áîëüøå âñåãî ïîäõîäèò."

    Caption
    "Ù¸ëêíèòå ïî íóæíîìó âàì òèïó óñòàíîâêè."

    Message
    ""

    DescriptionLabel
    "Îïèñàíèå"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

StartCopyingFiles {
    Title
    "Íà÷àëî êîïèðîâàíèÿ ôàéëîâ"

    Subtitle
    "Ïðîñìîòð èíôîðìàöèè ïåðåä íà÷àëîì êîïèðîâàíèÿ ôàéëîâ"

    Caption
    "Ïðîãðàììà óñòàíîâêè ñîáðàëà íåîáõîäèìóþ èíôîðìàöèþ äëÿ íà÷àëà êîïèðîâàíèÿ ôàéëîâ. \
     Ù¸ëêíèòå ïî <%Back%>, ÷òîáû ïðîâåðèòü èëè çàíîâî ââåñòè èíôîðìàöèþ äëÿ óñòàíîâêè. \
     ×òîáû íà÷àòü óñòàíîâêó, ù¸ëêíèòå ïî <%Next%>."

    Message
    ""

    Text
    "Êàòàëîã íàçíà÷åíèÿ:
            <%InstallDir%>

    Òèï óñòàíîâêè:
            <%InstallType%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

Uninstall {
    Title
    "Äåèíñòàëëÿöèÿ"

    Subtitle
    "Äåèíñòàëëÿöèÿ <%AppName%>"

    Caption
    "<%GroupBeingUninstalledText%>"

    Message
    ""

    FileValue
    "<%Status%>"

    ProgressValue
    "<%UninstallPercentComplete%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallComplete {
    Caption
    "Äåèíñòàëëÿöèÿ çàâåðøåíà"

    Message
    "<%AppName%> óäàëåíà èç âàøåé ñèñòåìû."

    NextButton
    "<%Finish%>"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

UninstallDetails {
    Title
    "Èíôîðìàöèÿ î äåèíñòàëëÿöèè"

    Subtitle
    "Â ïðîöåññå óäàëåíèÿ ïðîèçîøëè îøèáêè"

    Caption
    "Â ïðîöåññå äåèíñòàëëÿöèè ïðîèçîøëè ñëåäóþùèå îøèáêè:"

    Message
    ""

    Text
    "<%Errors%>"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


UserInformation {
    Title
    "Èíôîðìàöèÿ î ïîëüçîâàòåëå"

    Subtitle
    "Ïîæàëóéñòà, ââåäèòå âàøè äàííûå."

    Caption
    "Ïîæàëóéñòà, ââåäèòå âàøå èìÿ è íàçâàíèå êîìïàíèè, â êîòîðîé âû ðàáîòàåòå."

    Message
    ""

    UserNameLabel
    "Èìÿ ïîëüçîâàòåëÿ:"

    CompanyLabel
    "Êîìïàíèÿ:"

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}


Welcome {
    Caption
    "Âàñ ïðèâåòñòâóåò ìàñòåð óñòàíîâêè InstallJammer äëÿ <%AppName%>"

    Message
    "Ìàñòåð InstallJammer óñòàíîâèò <%AppName%> <%Version%> íà âàøåì êîìïüþòåðå. \
    \n\nÏåðåä íà÷àëîì óñòàíîâêè ðåêîìåíäóåòñÿ çàêðûòü âñå äðóãèå ðàáîòàþùèå\
    ïðîãðàììû.\n\n×òîáû ïðîäîëæèòü, âûáåðèòå <%Next%>, èëè âûáåðèòå <%Cancel%> äëÿ âûõîäà."

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}

InstallPassword {
    Title
    "Ïàðîëü óñòàíîâêè"

    Subtitle
    "Äëÿ ïðîäîëæåíèÿ óñòàíîâêè íåîáõîäèìî óêàçàòü ïàðîëü."

    Caption
    "Ïîæàëóéñòà, ââåäèòå ïàðîëü."

    Message
    ""

    NextButton
    "<%Next%> >"

    BackButton
    "< <%Back%>"

    CancelButton
    "<%Cancel%>"
}
Added Themes/Modern_Wizard/theme.cfg.




























>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Name    "Modern Wizard"
Version 1
Width   500
Height  365
Buttons {
    Back/Next/Cancel
    Back/Next
    Back/Cancel
    Next/Cancel
    Back
    Next
    Cancel
    NONE
}
Added Themes/Modern_Wizard/theme.tcl.














































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::InstallJammer::theme::NewProject { arrayName } {
    upvar 1 $arrayName vars

    if {$vars(includeCustomSetup)} {
        ::InstallJammer::AddPane Install ChooseComponents \
            -parent StandardInstall -index 2
        ::InstallJammer::AddPane Install SetupType \
            -parent StandardInstall -index 2
    }

    foreach pane [GetPaneComponentList] {
        if {[$pane component] ne "SetupComplete"} { continue }

        set y 140
        if {$vars(ViewReadmeCheckbutton)} {
            set act [::InstallJammer::AddAction Install AddWidget \
                -parent $pane -title "View Readme Checkbutton"]
            $act set Type checkbutton X 185 Y $y \
                VirtualText ViewReadme
            $act title "View Readme Checkbutton"
            ::InstallJammer::SetVirtualText en $act Text "<%ViewReadmeText%>"

            set con [::InstallJammer::AddCondition FileExistsCondition \
                -parent $act]
            $con set Filename "<%ProgramReadme%>"

            set con [::InstallJammer::AddCondition StringIsCondition \
                -parent $act]
            $con set Operator false
            $con set String "<%InstallStopped%>"
        }

        if {$vars(LaunchAppCheckbutton)} {
            incr y 20
            set act [::InstallJammer::AddAction Install AddWidget \
                -parent $pane -title "Launch Application Checkbutton"]
            $act set Type checkbutton X 185 Y $y \
                VirtualText LaunchApplication
            $act title "Launch Application Checkbutton"
            ::InstallJammer::SetVirtualText en $act \
                Text "<%LaunchApplicationText%>"

            set con [::InstallJammer::AddCondition FileExistsCondition \
                -parent $act]
            $con set Filename "<%ProgramExecutable%>"

            set con [::InstallJammer::AddCondition StringIsCondition \
                -parent $act]
            $con set Operator false
            $con set String "<%InstallStopped%>"
        }

        if {$vars(DesktopShortcutCheckbutton)} {
            incr y 20
            set act [::InstallJammer::AddAction Install AddWidget \
                -parent $pane -title "Desktop Shortcut Checkbutton"]
            $act set Type checkbutton X 185 Y $y \
                VirtualText CreateDesktopShortcut
            ::InstallJammer::SetVirtualText en $act \
                Text "<%CreateDesktopShortcutText%>"

            set con [::InstallJammer::AddCondition FileExistsCondition \
                -parent $act]
            $con set Filename "<%ProgramExecutable%>"

            set con [::InstallJammer::AddCondition StringIsCondition \
                -parent $act]
            $con set Operator false
            $con set String "<%InstallStopped%>"
        }

        if {$vars(QuickLaunchShortcutCheckbutton)} {
            incr y 20
            set act [::InstallJammer::AddAction Install AddWidget \
                -parent $pane -title "Quick Launch Shortcut Checkbutton"]
            $act set Type checkbutton X 185 Y $y \
                VirtualText CreateQuickLaunchShortcut
            ::InstallJammer::SetVirtualText en $act Text \
                "<%CreateQuickLaunchShortcutText%>"

            set con [::InstallJammer::AddCondition PlatformCondition \
                -parent $act]
            $con set Operator "is"
            $con set Platform "Windows"

            set con [::InstallJammer::AddCondition FileExistsCondition \
                -parent $act]
            $con set Filename "<%ProgramExecutable%>"

            set con [::InstallJammer::AddCondition StringIsCondition \
                -parent $act]
            $con set Operator false
            $con set String "<%InstallStopped%>"
        }
    }
}
Added docs/InstallJammer User Guide.pdf.

cannot compute difference between binary files

Added docs/InstallJammer.chm.

cannot compute difference between binary files

Added docs/html/10.html.
































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.0</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.0">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.0</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="101.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="10rc3.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.0 (June 18th, 2006)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>As of the 1.0 release, InstallJammer is now released under the GNU General Public License (GPL).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Bugs</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug that would cause user input into an entry field to be substituted as a boolean (0 or 1) value as they are typing.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause files that have been installed previously to fail when trying to install over them.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause the Make New Folder button on the Choose Directory dialog to fail.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause the virtual text table to error when switching between languages if an edit was currently active.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that was causing the result virtual text not to be set for an Execute Script action.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/101.html.


















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.0.1</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.0.1">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.0.1</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="102.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="10.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.0.1 (July 5th, 2006)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Bugs</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug where executing some actions before the first pane is displayed would cause an error.&nbsp; InstallJammer was attempting to update the widgets on the pane when there was no pane to update.</span></li>
<li class=rvps1><span class=rvts2>Clicking outside of the entry while making a new folder in the Choose Directory dialog will now finish the edit instead of reverting the text. [</span><span class=rvts3>Bug #1510752</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where specifying the Default Language was not working properly during installation.&nbsp; If Allow Language Selection is No, the Default Language will always be used.&nbsp; If Allow Language Selection is Yes, InstallJammer will first attempt to determine the user's system language, and if available, use that as the default in the language select dialog.&nbsp; If InstallJammer cannot determine the system language (of if it is one we don't have), the language select dialog will default to Default Language [</span><span class=rvts3>Bug #1510750</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Cancel button on the Preferences dialog didn't actually reset the preferences. [</span><span class=rvts3>Bug #1508941</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where auto-complete typing was turned on for the Help Browser combobox in the Preferences dialog.&nbsp; This was causing the user not to be able to type the location of a help browser.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where building from the command-line would include files and directories that were marked as inactive in a project.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Active property of a node in the File Group tree could get out-of-sync with its check image. [</span><span class=rvts3>Bug #1505408</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where InstallJammer was not setting the modified date/time of a file after it was installed on the target system.&nbsp; This meant that every file installed had the current date/time instead of what was stored in the installer. [</span><span class=rvts3>Bug #1505025</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the error dialog when renaming or adding virtual text could get into a weird state if the user was doing a bunch of weird stuff.&nbsp; Instead, we just post the error dialog and cancel the edit to stop the whole process [</span><span class=rvts3>Bug #1509526</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where renaming a virtual text variable was not saving properly. [</span><span class=rvts3>Bug #1509526</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where adding a new virtual text with no value would not get saved. [</span><span class=rvts3>Bug #1511881</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that caused InstallJammer to not recognize versions properly for a Blackdown Java JRE (they use - instead of _). [</span><span class=rvts3>Bug #1511881</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause an error if we were looking for a JRE on a Windows system that had never installed one. [</span><span class=rvts3>Bug #1511871</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause files added in directories that are a direct child of a Windows drive to lose a / and make the files install in the wrong place. [</span><span class=rvts3>Bug #1511627</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where InstallJammer could create a temporary directory as root and then not be able to install later as non-root. [</span><span class=rvts3>Bug #1513795</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that caused InstallJammer to ignore hidden files when building lists of files and directories for packaging.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/102.html.






























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.0.2</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.0.2">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.0.2</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="103.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="101.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.0.2 (August 1st, 2006)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Bugs</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Hooked up the Help button in the New Project Wizard to go to the Step-by-Step tutorial in the help documentation.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Alias property was not reflecting the correct value when switching between nodes in the File Group tree [</span><span class=rvts3>Bug #1521556</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Changed the way multiple selection in the File Group tree works when using shift-click.&nbsp; InstallJammer will now select all of the nodes between two shift-click'd nodes regardless of their parent. [Reported by Scott Specker]</span></li>
<li class=rvps1><span class=rvts2> Fixed a bug where Execute Script would not accurately report back an error. [</span><span class=rvts3>Bug #1521867</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>If the pane changes while moving forward or backward (like due to a Move to Pane action), we want to stop moving because the pane has changed. [</span><span class=rvts3>Bug #1526114</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in Add Windows File Type that caused it to fail on an invalid command. [</span><span class=rvts3>Bug #1530808</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Replaced the Linux installkit with a new non-threaded build.&nbsp; This means that Linux installs will no longer use threads, but it also means that the Linux installs will no longer rely on the pthread library on the target system. [</span><span class=rvts3>Bug #1525293</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Replaced the Windows installkit with a new one that includes a new command to create Windows shortcuts. [</span><span class=rvts3>Bug #1532013</span><span class=rvts2>]</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>The installkit for Windows is now </span><span class=rvts3>500k smaller</span><span class=rvts2> thanks to Jeremy Collake's awesome </span><a class=rvts4 href="http://www.bitsum.com/pec2.asp">PECompact2</a><span class=rvts2> software!</span></li>
<li class=rvps1><span class=rvts2>Record if the main InstallJammer window is maximized on Windows and restore that state when restarting InstallJammer.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/103.html.












































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.0.3</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.0.3">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.0.3</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="104.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="102.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.0.3 (September 19th, 2006)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Bugs</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a typo in the Add Windows File Type action that would cause an error when the Icon Path was specified. [</span><span class=rvts3>Bug #1533420</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where some user systems don't have the %c time format available.&nbsp; We'll use a long-hand version from now on.&nbsp; This would cause an error on some systems when selecting a file in the File Group tree. [</span><span class=rvts3>Bug #1545596</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where just clicking on a File Group in the File Group tree would cause it to go into rename edit mode.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where COMMON_* directories don't work on Windows 9x.&nbsp; From now on, we'll try to use the specific counterpart if the COMMON was not found. [</span><span class=rvts3>Bug #1551016</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a few other bugs related to running InstallJammer on Windows 9x.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where including the TWAPI extension did not actually load the library when the installer started.</span></li>
<li class=rvps1><span class=rvts2>Modified the Script Condition to allow Tcl commands and variables to be substituted within the script.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the "Update files with more recent date" check was not accurately comparing files whose dates were identical.&nbsp; In those cases, the files would be installed anyway when they should be skipped.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Root Key was being ignored for registry keys in the Add Windows Registry Key action. [</span><span class=rvts3>Bug #1557936</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing the text of certain properties could cause an error when trying to save. [</span><span class=rvts3>Bug #1533009</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Message catalogs are now stored in the installer during a quick build.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added German translations (thanks to Hans Hellwege!).</span></li>
<li class=rvps1><span class=rvts2>Added a new File Actions group with some new actions.&nbsp; See the documentation for a description of each new action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Adjust Line Feeds</span><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Backup File</span><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Change File Ownership</span><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Change File Permissions</span><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Create File Link</span><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Copy File</span><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Delete File</span><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Read File Into Virtual Text</span><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Rename File</span><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Replace Text in File</span><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Write Text to File</span><span class=rvts2> action.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/104.html.








































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.0.4</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.0.4">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.0.4</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="11b1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="103.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.0.4 (October 25th, 2006)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release fixes quite a few bugs that have been reported by users (thank you all!), and it adds some new actions and a lot of debugging changes.&nbsp; This release could be called the debug release for all the changes that have gone in to support debugging.&nbsp; This should make it a lot easier for developers and testers alike to track down problems in an installer.&nbsp; The debug output should be very thorough now, but I always like suggestions.&nbsp; If there's something missing, don't hesitate to ask.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Bugs</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts3>*** POTENTIAL INCOMPATIBILITY ***</span><span class=rvts2>&nbsp; Fixed a bug where mismatched []'s in virtual text could cause an error when substituting the text.&nbsp; This was causing installation errors on Japanese systems where the characters were being interpreted as [ in directory paths.&nbsp; This is potentially incompatible if you are using [] inside of virtual text to substitute Tcl commands.&nbsp; </span><span class=rvts3>*NOTE</span><span class=rvts2>: This does not affect Script actions and conditions like Execute Script and Script Condition where the scripts are properly substituted and eval'd as Tcl commands. [</span><span class=rvts3>Bug #1578013</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the installjammer script that would cause startup to fail on 64 bit systems because the MACH was not recognized.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where extra \'s on a registry key would cause a lookup failure.&nbsp; We now strip any extra \'s from the key before looking in the registry.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Launch Web Browser would fail on error.&nbsp; Now, if we're running under KDE or Gnome, the action will attempt to use the default method for launching a URL under those environments.&nbsp; If that fails, or if we're using a different window manager, the action will attempt to find a suitable browser based on environment and known browsers.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Add Widget action that would cause errors if a radiobutton was added with values that looked like booleans.&nbsp; The Value property is now converted to 0 or 1 if it looks like a boolean before creating the radiobuttons. [</span><span class=rvts3>Bug #1583094</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Choose Directory dialog where clicking the X on the window would cause an error. [</span><span class=rvts3>Bug #1565652</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Choose Directory dialog where choosing a root-level directory (like C:/) would not work. [</span><span class=rvts3>Bug #1565665</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in Windows shortcut creation where long paths could not be used and would end up looking like a path with some junk characters at the end. [</span><span class=rvts3>Bug #1565654</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a user could accidentally delete an entire Company directory on Windows without knowing it.&nbsp; Now, we check to see if the directory looks like our &lt;%Company%&gt;, and if it does, we don't delete unless it's totally empty. [</span><span class=rvts3>Bug #1575801</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where installing the Windows uninstall registry entry could fail if we don't have permission to write to HKEY_LOCAL_MACHINE.&nbsp; If it fails, we'll try and write to the HKEY_CURRENT_USER uninstall registry instead. [</span><span class=rvts3>Bug #1578278</span><span class=rvts2>]</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added a lot of new debugging output throughout installation.&nbsp; This will provide more information when running in debug mode.</span></li>
<li class=rvps1><span class=rvts2>Added new variable to specify that debug output should go to the console.&nbsp; When running in debug mode, this will mimic what goes out to the debug log.&nbsp; If not in debug mode, you will still see the debug output but with no debug log.</span></li>
<li class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; With an open console, type: </span><span class=rvts3>set ::debug 1</span><span class=rvts2> upon startup.</span></li>
<li class=rvps1><span class=rvts2>When debugging, any comment on an object is output along with the regular debug output.&nbsp; This allows developers to comment an object for other developers to see when running in debug mode.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Brazilian Portugese translations</span><span class=rvts2> (thanks to Alan Carvalho de Assis!)</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new </span><a class=rvts4 href="LogDebugMessage.html">Log Debug Message</a><span class=rvts3> </span><span class=rvts2>action.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new </span><a class=rvts4 href="ModifyObject.html">Modify Object</a><span class=rvts3> </span><span class=rvts2>action.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new </span><a class=rvts4 href="AddDirectoryToPath.html">Add Directory to Path</a><span class=rvts3> </span><span class=rvts2>action.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new </span><a class=rvts4 href="RemoveDirectoryFromPath.html">Remove Directory from Path</a><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new </span><a class=rvts4 href="AddPaneToOrder.html">Add Pane to Order</a><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new </span><a class=rvts4 href="RemovePaneFromOrder.html">Remove Pane from Order</a><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Window State property</span><span class=rvts2> for </span><a class=rvts4 href="InstallWindowsShortcut.html">Install Windows Shortcut</a><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Add to Uninstall</span><span class=rvts2> </span><span class=rvts3>property</span><span class=rvts2> for </span><a class=rvts4 href="UnpackStoredFile.html">Unpack Stored File</a><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Add to Uninstall</span><span class=rvts2> </span><span class=rvts3>property</span><span class=rvts2> for </span><a class=rvts4 href="AddWindowsRegistryKey.html">Add Windows Registry Key</a><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>The </span><a class=rvts4 href="MoveToPane.html">Move to Pane</a><span class=rvts2> action now appends the specified pane to the back order of the wizard.</span></li>
<li class=rvps1><span class=rvts2>Added entry widget as a possible type for </span><a class=rvts4 href="AddWidget.html">Add Widget</a><span class=rvts2> actions.</span></li>
<li class=rvps1><span class=rvts2>Panes marked as inactive will be skipped.</span></li>
<li class=rvps1><span class=rvts2>Files marked as inactive will be skipped when building the list of files to install.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/10b1.html.








































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.0b1</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.0b1">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 text-indent: -24px;
 margin: 0px 0px 0px 24px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.0b1</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="10b2.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GettingStarted.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.0b1 (February 12th, 2006)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Big Changes</span></p>
<p class=rvps1><span class=rvts2>These changes create incompatibilities with the way InstallJammer currently works.&nbsp; Unless otherwise stated, all incompatibilities will automatically be converted when you load your old project into the new version of InstallJammer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Groups Overhauled</span></p>
<p class=rvps1><span class=rvts2>Changed the way directories in file groups work.&nbsp; Instead of treating the root directory as being installed into the file group directory, every directory in a file group has its directory created.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This gives a more consistent approach to directories in file groups.&nbsp; What you see is what you get.&nbsp; All directories in a file group will be created just as you see them in the file group display.&nbsp; Think of the file group as the root directory created when installing, and every directory contained in the file group will be created underneath it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This means that instead of adding a single directory for your whole application, you'll have to add all of the contents of the directory, but this approach is more in line with how other installers work as well as how most people would expect it to work.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Choosing your application directory when creating a new install will automatically grab the contents of that directory and setup your Program Files file group correctly.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Modify Button Action Replaced</span></p>
<p class=rvps1><span class=rvts2>The Modify Button action has been replaced by a new Modify Widget action.&nbsp; This action is more generic and can execute on any widget in a pane instead of just the wizard buttons.&nbsp; Unlike the Modify Button action, the Modify Widget action can specify multiple widgets (separated by ;) in the same action, and InstallJammer will modify them all at once.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Bugs</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug in the conditions editor where closing the window with the X would put the editor into an unstable state.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where building an install would cause the active component to go blank.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause the status progressbar to disappear between platform builds.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where escaping while editing a property could sometimes cause an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Windows registry actions would still display message on non-Windows systems.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where if the user chose a new installation directory, the application would install into that directory instead of creating a subdirectory beneath it.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the uninstall would not center to the screen during startup.</span></li>
<li class=rvps1><span class=rvts2>Fixed the Select Destination pane to allow configuration of the Destination Folder label [Bug 1370424]</span></li>
<li class=rvps1><span class=rvts2>We no longer install a Windows shortcut if the target does not exist. [Bug 1370423]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that was causing command-line builds to fail. [Bug 1374874]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where unselecting a component in a Custom install would not disable the component during installation.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause the Icon and Image properties to be overwritten anytime a project was loaded [Bug 1367770]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Execute Action action would not execute a single action, only an Action Group.</span></li>
<li class=rvps1><span class=rvts2>Don't auto-scroll the build log if the user has moved up to read something else.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where InstallJammer would forget Build Platforms when saving.</span></li>
</ul>
<p class=rvps2><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Executables are now stored in an output/ subdirectory of the project instead of the root project directory.&nbsp; This puts all of the installers in one place during building and allows for some expansion later.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new File Permission condition</span><span class=rvts2> to check file permissions on a target system.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Modify Widget action</span><span class=rvts2> to change the state and/or text of a widget in a pane.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Locate Java Runtime action</span><span class=rvts2> to locate the best available Java runtime on the target system.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Get Java Property action</span><span class=rvts2> to get the value of a property from a Java properties file.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Wait action</span><span class=rvts2> that will cause InstallJammer to wait a specified amount of time before proceeding with the install.</span></li>
<li class=rvps1><span class=rvts2>Added checks for properties that attempt to verify that any virtual text in the property is complete and valid.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Require Root and Root Install Directory properties</span><span class=rvts2> to UNIX platforms.&nbsp; These let you require the installing user to be root and adjust the default installation directory if the user is installing as root.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new &lt;%Username%&gt; virtual text</span><span class=rvts2> that contains the username of the installing user.</span></li>
<li class=rvps1><span class=rvts2>Added a button to explore test installs to the main toolbar.</span></li>
<li class=rvps1><span class=rvts2>Went through all of the install panes in each theme and made sure that all of the widgets had names so that their properties could be modified in a project.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>Required Component option to components</span><span class=rvts2> to specify that a component should not be allowed to be unselected during a Custom installation.</span></li>
<li class=rvps1><span class=rvts2>Added the ability to drag-and-drop Setup Types and Components to change their ordering.&nbsp; The order changes the order they are displayed during installation.</span></li>
<li class=rvps1><span class=rvts2>Added scrollbars to the main project listing.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Default File Permission and Default Directory Permission properties</span><span class=rvts2> to UNIX platforms to define default permission masks during installation.</span></li>
<li class=rvps1><span class=rvts2>Added a right-click menu option in the File Group tree to create a shortcut for the file to the Windows Desktop or the Program Folder.</span></li>
<li class=rvps1><span class=rvts2>Added a property to the Execute External Program action to specify a text box to update without put while the program is running.&nbsp; Also change the way data is read from the external program so that instead of being line-by-line, the data is read as it becomes available.&nbsp; This makes it possible to do configure and make actions from within an install, and the output will continually update in the text box as it builds.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Edit Pane Code and Restore Original Pane buttons</span><span class=rvts2> to each property window.&nbsp; This allows you to edit the Tcl/Tk code that is used to create the pane and make them look any way you want.</span></li>
<li class=rvps1><span class=rvts2>Added the ability to select multiple file groups, directories and files in the File Group tree and set their permissions all at once.</span></li>
<li class=rvps1><span class=rvts2>InstallJammer will now automatically remove unused file groups and components when building an install.&nbsp; If a component includes a file group that was not saved because it was inactive or for any other reason, the file group will be removed from the component's list of file groups before building.&nbsp; A warning message is output to the build log when this happens.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/10b2.html.






























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.0b2</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.0b2">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.0b2</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="10rc1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="10b1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.0b2 (April 19th, 2006)</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Special Note for 1.0b2</span></p>
<p class=rvps1><span class=rvts2>With the amount of changes in this release, I </span><span class=rvts3>highly recommend</span><span class=rvts2> that you build a new project instead of trying to convert your old project.&nbsp; I tried to make the conversion as smooth as possible, but with the amount of changes, it was very difficult.&nbsp; Except for bug fixes, this will truly be the last release to make changes, so any new project from here until the final 1.0 release will hopefully not need any conversion (unless it's to fix a bug).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Big Changes</span></p>
<p class=rvps1><span class=rvts2>These changes create incompatibilities with the way InstallJammer currently works.&nbsp; Unless otherwise stated, all incompatibilities will automatically be converted when you load your old project into the new version of InstallJammer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Added Multi-Language Support to Installers</span></p>
<p class=rvps1><span class=rvts2>Installers in InstallJammer can now support multiple languages.&nbsp; Included in this release are Spanish (</span><span class=rvts3>thanks to Jose Jurado</span><span class=rvts2>) and French (</span><span class=rvts3>thanks to Olivier Touze</span><span class=rvts2>) message catalogs to support these languages in installers.&nbsp; When converting your project, you will be asked if you want to update all of the text in your project.&nbsp; This will clear any new text you may have added before updating, but you will need to do this to get the new multi-language support.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>New Default Action Groups</span></p>
<p class=rvps1><span class=rvts2>New action groups are added to every new project, and these default groups are executed by InstallJammer automatically.&nbsp; They are:&nbsp; Startup Actions, Finish Actions and Cancel Actions.&nbsp; Please read through the documentation on What are Action Groups? for more information on what these new groups do.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Changed Text Properties to Advanced Properties for some Actions and Conditions</span></p>
<p class=rvps1><span class=rvts2>Since text properties are now localized by language, some text properties in actions and conditions had to be changed over to Standard properties.&nbsp; We don't want scripts and strings that are not messages to be localized by language.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Bugs</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a typo in Add Windows File Command action that was causing it to fail.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where creating a new Setup Type would cause an error. </span><span class=rvts3>[Bug 1453794]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing the name of a File Group would cause an error when trying to save the new name. </span><span class=rvts3>[Bug 1453794]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the uninstall.&nbsp; Clicking No when the uninstall would ask if you wanted to proceed with the uninstall would still proceed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where InstallJammer was not respecting the File Update Method of a file group.&nbsp; All installs were using the default to check for newer files by date.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Install Wrapped Script action that was causing it not to work.</span></li>
<li class=rvps1><span class=rvts2>Fixed the Install Wish Binary action.&nbsp; It previously wasn't working.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where installing a 0 byte file on Windows would cause an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where including files with non-ASCII characters in an installer would cause InstallJammer to fail when building the installer.&nbsp; All filenames should now be acceptable.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the &lt;%Username%&gt; virtual text variable was not being setup properly when the user was root.&nbsp; This meant that Require Root would only work if the user had actually logged into a session as root instead of just SU'ing to root.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where double-clicking on a row border between rows in a table would cause an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that could occur when clicking into another cell while editing a property.</span></li>
<li class=rvps1><span class=rvts2>Changed the way project directories are handled when creating a new install.&nbsp; Creating a project file in a directory without a subdirectory would cause the entire directory to be deleted when deleting the project.&nbsp; All projects are now built with their own subdirectory.</span></li>
<li class=rvps1><span class=rvts2>Normalize the home directory on UNIX platforms.&nbsp; This was causing a bug during uninstallation when trying to remove the .installjammerinfo file.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where trying to exit during a build would cause an error of a bad proc name.&nbsp; You still can't exit or close a project during a build.&nbsp; That's yet to come.</span></li>
<li class=rvps1><span class=rvts2>Save the active component before previewing so that all of the latest changes appear in the preview window.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where some properties would not get saved when switching from one component to the next.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where testing an install that needed to be rebuilt would cause an error due to a missing command.&nbsp; We now wait until the rebuild is done before testing.</span></li>
<li class=rvps1><span class=rvts2>All text boxes in all themes now word wrap instead of character wrap.</span></li>
<li class=rvps1><span class=rvts2>All boolean virtual text is now handled as 0 or 1 and will be auto-converted when setting virtual text.&nbsp; This makes it easier to deal with checkbuttons and true/false checks.</span></li>
<li class=rvps1><span class=rvts2>Changed the display of embedded textboxes.&nbsp; Instead of making the entire fram with scrollbars appear sunken, we only make the textbox itself appear sunken </span><span class=rvts3>[Bug 1453799]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing the text property of a condition would cause an error when trying to save the new text.</span></li>
<li class=rvps1><span class=rvts2>Added checks to make sure files in the Temp and InstallInfoDir directories don't get written out to the install log.&nbsp; These directories are automatically cleaned up by InstallJammer anyway.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where hittin Escape while editing a property in the Conditions Editor would actually cause the window to close.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where some information was not being saved for some platforms if they were not active in the new project.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Platform Information was not accurately being updated when closing and opening install projects.</span></li>
<li class=rvps1><span class=rvts2>When browsing for the install directory during installation, we no longer append our directory to the end of what the user chooses.&nbsp; They do, however, have the option to make a new folder on the target system for installing into.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts3>Added multi-language support for installers</span><span class=rvts2>.&nbsp; This is a HUGE enhancement that was originally slated for a 1.1 release, but the demand was so high that I finished it early.</span></li>
<li class=rvps1><span class=rvts3>Added message catalogs for Spanish and French languages.</span></li>
<li class=rvps1><span class=rvts3>Modified the build and install processes to use threads instead of external processes</span><span class=rvts2>.&nbsp; This will save us the overhead of always starting a new process.&nbsp; </span><span class=rvts3>Install builds are now almost twice as fast as previous releases</span><span class=rvts2>.&nbsp; Installation should see a pretty good speed-up as well.</span></li>
<li class=rvps1><span class=rvts3>Completed the help documentation and hooked it up throughout the install builder.</span><span class=rvts2>&nbsp; This means that clicking the Help button or hitting F1 anywhere in InstallJammer will take you directly to the right place in the documentation.</span></li>
<li class=rvps1><span class=rvts3>Added new properties for files and directories.&nbsp; Every file and directory in an install can now be customized.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new &lt;%ApplicationURL%&gt; virtual text</span><span class=rvts2>.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new &lt;%ShortAppName%&gt; virtual text</span><span class=rvts2>.</span></li>
<li class=rvps1><span class=rvts2>Made the main toolbar buttons 22x22 instead of 16x16.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>Build for Final Release checkbutton</span><span class=rvts2> to the build screen.&nbsp; This checkbutton builds installers without debugging options and with some other things cleaned up so that they are ready for final release to customers.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Install Program Folder for All Users property</span><span class=rvts2> for Windows platforms.</span></li>
<li class=rvps1><span class=rvts2>Added a checkbutton to the Select Program Folder pane to let the user install the program folder for all users instead of just the current user.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Quick Build button</span><span class=rvts2> to the main toolbar.</span></li>
<li class=rvps1><span class=rvts2>Removed the option to rebuild without repackaging files.&nbsp; This is now a Quick Build.</span></li>
<li class=rvps1><span class=rvts2>Removed the option to save main.tcl when building.&nbsp; Build files are now always saved in a build subdirectory in the project directory.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Launch Web Browser action</span><span class=rvts2> that opens a web browser to a specified URL.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Unpack Stored File action</span><span class=rvts2> that will unpack a file stored in the installer to a specified location.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Install Desktop Shortcut action.</span><span class=rvts2>&nbsp; This does exactly what the other install shortcut actions do except that it will automatically install the shortcut on the target desktop for every supported window manager available.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Check for Previous Install action</span><span class=rvts2> that sets the variables &lt;%PreviousInstallExists%&gt; and &lt;%PreviousInstallDir%&gt;.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Set Virtual Text action</span><span class=rvts2> to set the value of a virtual text variable in a specified language.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new features for new projects</span><span class=rvts2> to tell InstallJammer to add checkbuttons to the Setup Complete pane of your installer.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new &lt;%JavaFound%&gt; virtual text</span><span class=rvts2> to the Locate Java Runtime action.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new &lt;%Tail ?filename?%&gt; virtual text</span><span class=rvts2> to get the tail end of a file path.</span></li>
<li class=rvps1><span class=rvts2>Added the ability to substitute message catalog text as a virtual text variable.&nbsp; For example, &lt;%PaneID,BackButton%&gt; will return the Back Button text value for the pane identified by PaneID.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Exit Type property</span><span class=rvts2> to the Exit action that specifies whether we're exiting on a Cancel or Finish condition.&nbsp; This mostly affects what actions InstallJammer will take during exit, including whether the Finish Actions or Cancel Actions action group is called.</span></li>
<li class=rvps1><span class=rvts2>Removed standard InstallJammer virtual text from the Virtual Text screen.&nbsp; From now on, only virtual text added to the project will appear.</span></li>
<li class=rvps1><span class=rvts2>Added new Windows Resource properties to the Install Wrapped Script action.</span></li>
<li class=rvps1><span class=rvts2>Files are now stored in the installer by their ID instead of by filename.&nbsp; This makes things a lot cleaner and also obscures the filenames a bit.</span></li>
<li class=rvps1><span class=rvts2>Changed the default geometry for InstallJammer so that it doesn't fill the entire screen on lower resolution monitors.</span></li>
<li class=rvps1><span class=rvts2>InstallJammer now remembers the size of and placement of panes throughout the install builder.&nbsp; Resizing panes will be remembered between sessions.</span></li>
<li class=rvps1><span class=rvts2>Changed the default file extension on non-Windows systems from .bin to nothing.&nbsp; Most Linux systems seem to recognize that executable files shouldn't have an extension.</span></li>
<li class=rvps1><span class=rvts2>Added a --prefix option to installs that lets the user specify the install directory prefix from the command-line.</span></li>
<li class=rvps1><span class=rvts2>Added new default Action Groups:&nbsp; Cancel Actions and Finish Actions.</span></li>
<li class=rvps1><span class=rvts2>Startup Actions, Cancel Actions and Finish Actions now get called automatically from within the installer and uninstaller.&nbsp; They don't need to be executed from specific panes.</span></li>
<li class=rvps1><span class=rvts2>Removed the Enable InstallJammer Version System option.&nbsp; We're going to to always save the versions from now on.</span></li>
<li class=rvps1><span class=rvts2>When adding the default application directory for a new project, we now just add the directory by itself and set the Destination Directory to &lt;%InstallDir%&gt; instead of adding all of the files contained in the directory.&nbsp; This will achieve the same effect of having the application install in the root install directory.</span></li>
<li class=rvps1><span class=rvts2>Removed the separator from the Custom Blank Pane 1 in the Modern Wizard theme and added a separator underneath the image and text box.&nbsp; This looks more like other modern wizards. </span><span class=rvts3>[Req 1453799]</span></li>
<li class=rvps1><span class=rvts2>An uninstaller will now look for install.log in the InstallJammer info directory if it can't find one stored inside itself.</span></li>
<li class=rvps1><span class=rvts2>Uninstallers now delete the info directory when everything else is done to make sure we cleanup the final traces of the application.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/10rc1.html.






































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.0rc1</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.0rc1">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.0rc1</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="10rc3.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="10b2.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.0rc1 (May 10th, 2006)</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Bugs</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug that was causing installers to not all share the same background color.&nbsp; This would cause the installers to look odd on most UNIX platforms because the colors didn't match.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the radiobuttons on the license pane were not reflecting state properly.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that was causing InstallJammer to ignore the Allow Language Selection property.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the install builder that would cause the builder not to remember paned window locations between sessions.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Execute External Program action that would cause programs to fail if they had spaces or backspaces in their names.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Execute Script actions now execute at the global level.</span></li>
<li class=rvps1><span class=rvts2>Added a Working Directory property to the Execute External Program action.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/10rc3.html.


















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.0rc3</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.0rc3">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.0rc3</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="10.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="10rc1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.0rc3 (May 23rd, 2006)</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Bugs</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug that would cause message boxes to error on Windows during a command-line build.&nbsp; Since Windows doesn't have a console, we can output to, we use message dialogs instead to let the user know when something happens.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that was causing failure in command-line builds [</span><span class=rvts3>Bug 1486397</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause an error in the New Project Wizard if the user didn't go all the way to the last screen of the wizard.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause an unrecognized error if there was an actual error while trying to preview a pane.&nbsp; The message box would never come up and instead come up with an error that doesn't actually tell you what the problem is.</span></li>
<li class=rvps1><span class=rvts2>Fixed the virtual text variables for the user info panes.&nbsp; The variables used now are &lt;%UserInfoName%&gt; and &lt;%UserInfoCompany%&gt;.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the text label for text properties was prepending the word Edit to every label.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause the Unpack Stored File action to fail.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause the wizard to fail on some platforms with an error about "wm resizable ..."</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause an error if the virtual text variables in an Execute External Program action were left blank.</span></li>
<li class=rvps1><span class=rvts2></span></li>
</ul>
<p class=rvps1><span class=rvts3>Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Build and project files now write out with UNIX linefeeds.</span></li>
<li class=rvps1><span class=rvts2>Unpack Stored File will no longer respect the File Update Method for the given file.&nbsp; This isn't very intuitive anyway, and the action can always have its own conditions if it needs them.</span></li>
<li class=rvps1><span class=rvts2>Modified the Choose Directory dialog to show drives on Windows so that the user can change to a different drive.</span></li>
<li class=rvps1><span class=rvts2>Added the last of the missing translation strings.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/11.html.
















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.1</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.1">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.1</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="112.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="11b2.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.1 (February 6th, 2007)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This is a very big release, so not all of the changes are noted here.&nbsp; This is a list of everything I could remember.&nbsp; These release notes are copied from the 1.1b1 release notes to show off everything that is new in the 1.1 release.&nbsp; Some of these changes (as noted) are the final bug fixes from the 1.1b2 release.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Major Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Changed the underlying file format for installers to a homegrown format that allows for more customization.</span></li>
<li class=rvps1><span class=rvts2>Installkits have all been updated.&nbsp; GUI components are now dynamically loaded so that Console and Silent installs can be run on machines with no X libraries.&nbsp; This also resulted in the installkits being much smaller for most platforms.</span></li>
<li class=rvps1><span class=rvts2>Added new platforms: AIX, FreeBSD, HP-UX, and Solaris sparc. [</span><span class=rvts3>Req #1459564, #1487035</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added support for building TAR files (with or without GZIP) from a project.</span></li>
<li class=rvps1><span class=rvts2>Added LZMA compression support. [</span><span class=rvts3>Req #1487034</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added support for "solid" archives.&nbsp; A solid archive is built as one big file before being compressed.&nbsp; This can often result in installers that are much smaller.&nbsp; Solid archives must first be extracted to a temporary location before they can be installed though.</span></li>
<li class=rvps1><span class=rvts2>Added support for defining custom command-line options for (un)installers.</span></li>
<li class=rvps1><span class=rvts2>Added support for specifying a custom build and install location for every file group, directory or file in a project.</span></li>
<li class=rvps1><span class=rvts2>Added support for relative file locations in the install builder. [</span><span class=rvts3>Req #1525104</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added support for customizing the compression for every file group, directory or file in a project.&nbsp; This means some file groups, directories or even single files can all be compressed with different compression methods.&nbsp; The choice is yours.</span></li>
<li class=rvps1><span class=rvts2>Added a Console install mode for installing via a console on non-Windows platforms. [</span><span class=rvts3>Req #1546821</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added a new Test Uninstall section for specifying options when testing an uninstaller.</span></li>
<li class=rvps1><span class=rvts2>Added support for creating shortcuts under Linux (and FreeBSD) program menus. [</span><span class=rvts3>Req #1487037</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added support for prompting the user for root when the installer requires it. [</span><span class=rvts3>Req #1487036</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Deleted files are no longer removed from a project.&nbsp; They are disabled (greyed out) in the file group tree and can be deleted or continue to be part of the project. [</span><span class=rvts3>Req #1525114</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added new Upgrade Application ID property for projects that denotes that a project is an upgrade install of another application.&nbsp; Some actions for new projects have been changed to not be executed on an upgrade install.</span></li>
<li class=rvps1><span class=rvts2>Added support for registering an application with </span><span class=rvts3>RPM</span><span class=rvts2> or </span><span class=rvts3>DPKG</span><span class=rvts2> databases through the </span><a class=rvts4 href="RegisterPackage.html">Register Package</a><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>The InstallJammer documentation now includes a PDF version of the user guide.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Major Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug that was causing non-Latin characters to display incorrectly on Linux (and other UNIX) platforms. [</span><span class=rvts3>Bug #1522660</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where installers could not be built if the name of the installer or path contained non-Latin characters. [</span><span class=rvts3>Bug #1517067</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Symbolic links that are included in a file group are now handled as links by the installer.&nbsp; The same link will be created pointing to the same file on the target system during installation. [</span><span class=rvts3>Bug #1499834</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where multiple installations of an application on the same machine would be removed when only one of the uninstallers was executed. [</span><span class=rvts3>Bug #1533190</span><span class=rvts2>]</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>New Actions</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><a class=rvts4 href="ConsoleAskYesOrNo.html">Console Ask Yes or No</a></li>
<li class=rvps1><a class=rvts4 href="ConsoleClearScreen.html">Console Clear Screen</a></li>
<li class=rvps1><a class=rvts4 href="ConsoleGetUserInput.html">Console Get User Input</a></li>
<li class=rvps1><a class=rvts4 href="ConsoleMessage.html">Console Message</a></li>
<li class=rvps1><a class=rvts4 href="ConsolePause.html">Console Pause</a></li>
<li class=rvps1><a class=rvts4 href="FetchURL.html">Fetch URL</a></li>
<li class=rvps1><a class=rvts4 href="GenerateUID.html">Generate UID</a></li>
<li class=rvps1><a class=rvts4 href="LaunchFile.html">Launch File</a></li>
<li class=rvps1><a class=rvts4 href="AddInstallInfo.html">Add Install Info</a></li>
<li class=rvps1><a class=rvts4 href="GetPreviousInstallInfo.html">Get Previous Install Info</a></li>
<li class=rvps1><a class=rvts4 href="InstallProgramFolderShortcut.html">Install Program Folder Shortcut</a></li>
<li class=rvps1><a class=rvts4 href="RebootOrShutdownSystem.html">Reboot or Shutdown System</a></li>
<li class=rvps1><a class=rvts4 href="RegisterPackage.html">Register Package</a></li>
<li class=rvps1><a class=rvts4 href="ImportWindowsRegistryFile.html">Import Windows Registry File</a></li>
<li class=rvps1><a class=rvts4 href="RemoveWindowsRegistryKey.html">Remove Windows Registry Key</a><span class=rvts2> [</span><span class=rvts3>Req #1596457</span><span class=rvts2>]</span></li>
<li class=rvps1><a class=rvts4 href="FocusOnWidget.html">Focus on Widget</a></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>New Conditions</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><a class=rvts4 href="ExecuteScriptCondition.html">Execute Script Condition</a></li>
<li class=rvps1><a class=rvts4 href="ExecuteScriptCondition.html">Object Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="VirtualTextTestCondition.html">Virtual Text Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="EnvironmentVariableTestCondition.html">Env Variable Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="PackageTestCondition.html">Package Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="PortTestCondition.html">Port Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="FileExtensionExistsCondition.html">File Extension Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="FileTypeExistsCondition.html">File Type Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="RegistryEntryExistsCondition.html">Registry Test Condition</a></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added new Copyright poperty for projects.&nbsp; This is added to the Windows resource information of a Windows executable when built.</span></li>
<li class=rvps1><span class=rvts2>Added new preference to save only toplevel directories and files when saving a project.&nbsp; This is mostly for developers who are using an InstallJammer project as a template that is then built from a command-line.</span></li>
<li class=rvps1><span class=rvts2>Added Default Install Mode property.&nbsp; The current default is a Standard GUI install.</span></li>
<li class=rvps1><span class=rvts2>Added a section for Package Information that is used when adding packages to the local packaging system on Linux.</span></li>
<li class=rvps1><span class=rvts2>Added a common Data property to all objects that can be used to store user-specific data on an object which can then be used by other actions and conditions.</span></li>
<li class=rvps1><span class=rvts2>Added a Target Filename property for files that will allow installed files to be renamed on the target system.&nbsp; This allows for a total re-mapping of files in an installer during installation.</span></li>
<li class=rvps1><span class=rvts2>The Comment and Data properties of objects are not stored in an install if they are blank.&nbsp; This just saves a little space when building.</span></li>
<li class=rvps1><span class=rvts2>Added new Show Setup Type property to Setup Types to specify that the given Setup Type should not be offered as a choice during installation.</span></li>
<li class=rvps1><span class=rvts2>Actions and Panes with conditions are now shown with * beside their title as a quick way to see that they are affected by some action.</span></li>
<li class=rvps1><span class=rvts2>New objects added since the last time the project was opened are added in blue.&nbsp; This is a quick way to see what is new to the project.</span></li>
<li class=rvps1><span class=rvts2>Added a new default Setup Actions action group that will execute before command-line options are parsed.&nbsp; This can (and should only) be used for setting virtual text and manipulating platform-specific command-line options before the installer really gets going.</span></li>
<li class=rvps1><span class=rvts2>Added a new test option for testing in Console mode on non-UNIX platforms.&nbsp; This will open a console window and start the install inside it.</span></li>
<li class=rvps1><span class=rvts2>Added new preferences for specifying custom locations for Themes, Actions and Conditions.&nbsp; This will allow developers to create their own custom components in locations outside of the InstallJammer directories.</span></li>
<li class=rvps1><span class=rvts2>Added a button to stop install builds that are in progress.</span></li>
<li class=rvps1><span class=rvts2>Added new properties to the Add Widget action that allow any non-label widget to have a label included as part of the widget itself.&nbsp; This makes it easier to add new widgets without always having to add a second widget for a label.</span></li>
<li class=rvps1><span class=rvts2>Added new "browse entry" widget to the Add Widget action.&nbsp; This is an entry with a browse button for selecting a file or directory on the target system.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Added a new Auto Update property to the Set Virtual Text action.&nbsp; This just exposes the underlying function of what the API can already do.&nbsp; Setting a virtual text to Auto Update means that the screen should automatically be updated anytime the value changes.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Building a project from the command-line that has not been converted to the new project format will result in an error telling the user they need to upgrade the project before building. [</span><span class=rvts3>Bug #1648310</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Added an Arguments property to the Launch File action to pass arguments to the command-line when launching a file.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2) </span><span class=rvts2>Removed the message box and check for removing leftover files after the main uninstall completes.&nbsp; Users will usually click this box to remove the rest of the components when they don't actually know what they're doing.&nbsp; It's better to leave a few directories lying around than end up deleting something important.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> When converting up from the current version of a project, the auto-conversion routine will attempt to fix any of the broken License panes that have been created in past versions.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Added a new Add to Uninstall property to the Write Text to File action.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Added a new Append Newline property to the Write Text to File action. [</span><span class=rvts3>Bug #1651927</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2) *** POTENTIAL INCOMPATIBILITY ***</span><span class=rvts2>&nbsp; Changed the way Files are handled in the Write Text to File action.&nbsp; It doesn't make sense for this action to accept a list of patterns.&nbsp; Instead, the action now accepts an explicit list of files (not patterns) to write to. [</span><span class=rvts3>Bug #1651928</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Added a new Trim String property to the Read File Into Virtual Text action so that the data read from the file can be trimmed of excess whitespace. [</span><span class=rvts3>Bug #1650962</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> The checkbuttons on the build screen now match the active status of the platforms on startup. [</span><span class=rvts3>Req #1647636</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2) *** POTENTIAL INCOMPATIBILITY ***</span><span class=rvts2>&nbsp; Changed the search order of virtual text substitution.&nbsp; Language-specific text is now checked AFTER non-specific.&nbsp; Since most virtual text variables in an install are specified without a language, those variables should take precedence over the less-important language text.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug where using a Choose Components pane on a non-Custom setup type would result in a blank component list. [</span><span class=rvts3>Bug #1614930</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where files were being included in a platform where the file group had not been included. [</span><span class=rvts3>Bug #1615241</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Choose Components pane would error when populating the component list if a child component was added where the parent was not. [</span><span class=rvts3>Bug #1611703</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the License Agreement pane would not disable the Yes button on first display, which would allow the user to skip the license without checking the Yes button. [</span><span class=rvts3>Bug #1593788</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a typo in the Create File Link action. [</span><span class=rvts3>Bug #1588953</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a File Group that was deactivated during installation would still be installed. [</span><span class=rvts3>Bug #1585473</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a Condition that was deactivated during installation would still be checked. [</span><span class=rvts3>Bug #1585469</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an entry widget added through the Add Widget action would lose its virtual text when the pane was displayed. [</span><span class=rvts3>Bug #1585399</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Fixed a bug where typing into an entry would sometimes cause the first character typed to turn into a 0 or 1.&nbsp; This was a bug in the auto-boolean code handling.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Fixed a bug where the License pane was not disabling the Yes button on display.&nbsp; The user could then proceed without every agreeing to the license. [</span><span class=rvts3>Bug #1642817</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Fixed a bug where the Choose Directory dialog would default to the wrong directory and would blank out when the user hit cancel. [</span><span class=rvts3>Bug #1642718</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Fixed a bug that would cause InstallJammer to say that C:/ is not writable during installation when it actually is. [</span><span class=rvts3>Bug #1642818</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Moved the debug.log into the local InstallJammer home directory for each user instead of the local install directory.&nbsp; When running on a multi-user UNIX system, the debug.log sometimes cannot be written.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Fixed a bug where the #!/bin/sh line got moved down in the installjammer script, and this causes it not to launch.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Fixed a bug where a /version option on the command-line would error on Windows.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Fixed a bug in command-line builds that would result in an error.</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Fixed a bug where creating a new project can fail and error while trying to save project preferences if the InstallJammer home directory does not already exist. [</span><span class=rvts3>Bug #1649235</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Fixed a bug where editing a virtual text value could cause an error in some cases. [</span><span class=rvts3>Bug #1650172</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts3>(1.1b2)</span><span class=rvts2> Fixed a bug where command line builds could not specify a relative project file. [</span><span class=rvts3>Bug #1648430</span><span class=rvts2>]</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/112.html.












































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.1.2</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.1.2">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.1.2</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="12b1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="11.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.1.2 (February 21st, 2007)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>There was a packaging mistake with the 1.1.1 release.&nbsp; 1.1.1 is being repackaged as 1.1.2, and 1.1.1 no longer exists.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Allow multiple files to be selected when adding files to a File Group. [</span><span class=rvts3>Req #1657047</span><span class=rvts2>]</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug where command-line builds on Windows would fail and complain about not being able to find BWidgets. [</span><span class=rvts3>Bug #1653713</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Set Virual Text action where the Substitute Value property was not being respected. [</span><span class=rvts3>Bug #1658071</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in UNIX command-line builds where a relative project file could not be specified.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in command-line builds where solid archives were never completely stored. [</span><span class=rvts3>Bug #1653941</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an installkit that is not writable would cause a failure when building </span><span class=rvts3>[Bug #1658482</span><span class=rvts2>]</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/11b1.html.


















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.1b1</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.1b1">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.1b1</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="11b2.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="104.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.1b1 (January 17th, 2007)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This is a very big release, so not all of the changes are noted here.&nbsp; This is a list of everything I could remember.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Major Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Changed the underlying file format for installers to a homegrown format that allows for more customization.</span></li>
<li class=rvps1><span class=rvts2>Installkits have all been updated.&nbsp; GUI components are now dynamically loaded so that Console and Silent installs can be run on machines with no X libraries.&nbsp; This also resulted in the installkits being much smaller for most platforms.</span></li>
<li class=rvps1><span class=rvts2>Added new platforms: AIX, FreeBSD, HP-UX, and Solaris sparc. [</span><span class=rvts3>Req #1459564, #1487035</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added support for building TAR files (with or without GZIP) from a project.</span></li>
<li class=rvps1><span class=rvts2>Added LZMA compression support. [</span><span class=rvts3>Req #1487034</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added support for "solid" archives.&nbsp; A solid archive is built as one big file before being compressed.&nbsp; This can often result in installers that are much smaller.&nbsp; Solid archives must first be extracted to a temporary location before they can be installed though.</span></li>
<li class=rvps1><span class=rvts2>Added support for defining custom command-line options for (un)installers.</span></li>
<li class=rvps1><span class=rvts2>Added support for specifying a custom build and install location for every file group, directory or file in a project.</span></li>
<li class=rvps1><span class=rvts2>Added support for relative file locations in the install builder. [</span><span class=rvts3>Req #1525104</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added support for customizing the compression for every file group, directory or file in a project.&nbsp; This means some file groups, directories or even single files can all be compressed with different compression methods.&nbsp; The choice is yours.</span></li>
<li class=rvps1><span class=rvts2>Added a Console install mode for installing via a console on non-Windows platforms. [</span><span class=rvts3>Req #1546821</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added a new Test Uninstall section for specifying options when testing an uninstaller.</span></li>
<li class=rvps1><span class=rvts2>Added support for creating shortcuts under Linux (and FreeBSD) program menus. [</span><span class=rvts3>Req #1487037</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added support for prompting the user for root when the installer requires it. [</span><span class=rvts3>Req #1487036</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Deleted files are no longer removed from a project.&nbsp; They are disabled (greyed out) in the file group tree and can be deleted or continue to be part of the project. [</span><span class=rvts3>Req #1525114</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added new Upgrade Application ID property for projects that denotes that a project is an upgrade install of another application.&nbsp; Some actions for new projects have been changed to not be executed on an upgrade install.</span></li>
<li class=rvps1><span class=rvts2>Added support for registering an application with </span><span class=rvts3>RPM</span><span class=rvts2> or </span><span class=rvts3>DPKG</span><span class=rvts2> databases through the </span><a class=rvts4 href="RegisterPackage.html">Register Package</a><span class=rvts2> action.</span></li>
<li class=rvps1><span class=rvts2>The InstallJammer documentation now includes a PDF version of the user guide.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Major Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug that was causing non-Latin characters to display incorrectly on Linux (and other UNIX) platforms. [</span><span class=rvts3>Bug #1522660</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where installers could not be built if the name of the installer or path contained non-Latin characters. [</span><span class=rvts3>Bug #1517067</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Symbolic links that are included in a file group are now handled as links by the installer.&nbsp; The same link will be created pointing to the same file on the target system during installation. [</span><span class=rvts3>Bug #1499834</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where multiple installations of an application on the same machine would be removed when only one of the uninstallers was executed. [</span><span class=rvts3>Bug #1533190</span><span class=rvts2>]</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>New Actions</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><a class=rvts4 href="ConsoleAskYesOrNo.html">Console Ask Yes or No</a></li>
<li class=rvps1><a class=rvts4 href="ConsoleClearScreen.html">Console Clear Screen</a></li>
<li class=rvps1><a class=rvts4 href="ConsoleGetUserInput.html">Console Get User Input</a></li>
<li class=rvps1><a class=rvts4 href="ConsoleMessage.html">Console Message</a></li>
<li class=rvps1><a class=rvts4 href="ConsolePause.html">Console Pause</a></li>
<li class=rvps1><a class=rvts4 href="FetchURL.html">Fetch URL</a></li>
<li class=rvps1><a class=rvts4 href="GenerateUID.html">Generate UID</a></li>
<li class=rvps1><a class=rvts4 href="LaunchFile.html">Launch File</a></li>
<li class=rvps1><a class=rvts4 href="AddInstallInfo.html">Add Install Info</a></li>
<li class=rvps1><a class=rvts4 href="GetPreviousInstallInfo.html">Get Previous Install Info</a></li>
<li class=rvps1><a class=rvts4 href="InstallProgramFolderShortcut.html">Install Program Folder Shortcut</a></li>
<li class=rvps1><a class=rvts4 href="RebootOrShutdownSystem.html">Reboot or Shutdown System</a></li>
<li class=rvps1><a class=rvts4 href="RegisterPackage.html">Register Package</a></li>
<li class=rvps1><a class=rvts4 href="ImportWindowsRegistryFile.html">Import Windows Registry File</a></li>
<li class=rvps1><a class=rvts5 href="RemoveWindowsRegistryKey.html">Remove Windows Registry Key</a><span class=rvts2> [</span><span class=rvts3>Req #1596457</span><span class=rvts2>]</span></li>
<li class=rvps1><a class=rvts4 href="FocusOnWidget.html">Focus on Widget</a></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>New Conditions</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><a class=rvts4 href="ExecuteScriptCondition.html">Execute Script Condition</a></li>
<li class=rvps1><a class=rvts4 href="ExecuteScriptCondition.html">Object Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="VirtualTextTestCondition.html">Virtual Text Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="EnvironmentVariableTestCondition.html">Env Variable Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="PackageTestCondition.html">Package Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="PortTestCondition.html">Port Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="FileExtensionExistsCondition.html">File Extension Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="FileTypeExistsCondition.html">File Type Test Condition</a></li>
<li class=rvps1><a class=rvts4 href="RegistryEntryExistsCondition.html">Registry Test Condition</a></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added new Copyright poperty for projects.&nbsp; This is added to the Windows resource information of a Windows executable when built.</span></li>
<li class=rvps1><span class=rvts2>Added new preference to save only toplevel directories and files when saving a project.&nbsp; This is mostly for developers who are using an InstallJammer project as a template that is then built from a command-line.</span></li>
<li class=rvps1><span class=rvts2>Added Default Install Mode property.&nbsp; The current default is a Standard GUI install.</span></li>
<li class=rvps1><span class=rvts2>Added a section for Package Information that is used when adding packages to the local packaging system on Linux.</span></li>
<li class=rvps1><span class=rvts2>Added a common Data property to all objects that can be used to store user-specific data on an object which can then be used by other actions and conditions.</span></li>
<li class=rvps1><span class=rvts2>Added a Target Filename property for files that will allow installed files to be renamed on the target system.&nbsp; This allows for a total re-mapping of files in an installer during installation.</span></li>
<li class=rvps1><span class=rvts2>The Comment and Data properties of objects are not stored in an install if they are blank.&nbsp; This just saves a little space when building.</span></li>
<li class=rvps1><span class=rvts2>Added new Show Setup Type property to Setup Types to specify that the given Setup Type should not be offered as a choice during installation.</span></li>
<li class=rvps1><span class=rvts2>Actions and Panes with conditions are now shown with * beside their title as a quick way to see that they are affected by some action.</span></li>
<li class=rvps1><span class=rvts2>New objects added since the last time the project was opened are added in blue.&nbsp; This is a quick way to see what is new to the project.</span></li>
<li class=rvps1><span class=rvts2>Added a new default Setup Actions action group that will execute before command-line options are parsed.&nbsp; This can (and should only) be used for setting virtual text and manipulating platform-specific command-line options before the installer really gets going.</span></li>
<li class=rvps1><span class=rvts2>Added a new test option for testing in Console mode on non-UNIX platforms.&nbsp; This will open a console window and start the install inside it.</span></li>
<li class=rvps1><span class=rvts2>Added new preferences for specifying custom locations for Themes, Actions and Conditions.&nbsp; This will allow developers to create their own custom components in locations outside of the InstallJammer directories.</span></li>
<li class=rvps1><span class=rvts2>Added a button to stop install builds that are in progress.</span></li>
<li class=rvps1><span class=rvts2>Added new properties to the Add Widget action that allow any non-label widget to have a label included as part of the widget itself.&nbsp; This makes it easier to add new widgets without always having to add a second widget for a label.</span></li>
<li class=rvps1><span class=rvts2>Added new "browse entry" widget to the Add Widget action.&nbsp; This is an entry with a browse button for selecting a file or directory on the target system.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug where using a Choose Components pane on a non-Custom setup type would result in a blank component list. [</span><span class=rvts3>Bug #1614930</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where files were being included in a platform where the file group had not been included. [</span><span class=rvts3>Bug #1615241</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Choose Components pane would error when populating the component list if a child component was added where the parent was not. [</span><span class=rvts3>Bug #1611703</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the License Agreement pane would not disable the Yes button on first display, which would allow the user to skip the license without checking the Yes button. [</span><span class=rvts3>Bug #1593788</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a typo in the Create File Link action. [</span><span class=rvts3>Bug #1588953</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a File Group that was deactivated during installation would still be installed. [</span><span class=rvts3>Bug #1585473</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a Condition that was deactivated during installation would still be checked. [</span><span class=rvts3>Bug #1585469</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an entry widget added through the Add Widget action would lose its virtual text when the pane was displayed. [</span><span class=rvts3>Bug #1585399</span><span class=rvts2>]</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/11b2.html.


































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.1b2</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.1b2">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.1b2</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="11.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="11b1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.1b2 (January 23rd, 2007)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a typo in ::BuilderAPI::GetAction.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Default Language was not being written out to the installer.&nbsp; This meant that even if a Default Language was specified, it was being ignored by the installer on startup.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the help documentation for command line options was pointing to a non-existent page.</span></li>
<li class=rvps1><span class=rvts2>Fixed a typo that causes a startup failure when the auto-update fails for some reason.</span></li>
<li class=rvps1><span class=rvts2>Turned off the auto-update check by default until it's ready.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where InstallJammer would fail if it could not create its registry directory in Program Files on Windows.&nbsp; If Program Files is not writable, InstallJammer will attempt to create its registry in the COMMON_APPDATA directory instead.</span></li>
<li class=rvps1><span class=rvts2>Replaced the LZMA binaries on Windows with the proper ones.&nbsp; This fixes error that occur in installers that are compiled with LZMA on Windows.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an install would fail if the Default Setup Type did not exist in the installer.&nbsp; InstallJammer will now pick the first Setup Type in the list if the default does not exist.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/12.html.


























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="121.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="12b2.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2 (October 21st, 2007)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains mostly minor bug fixes and enhancements, but some of the enhancements may cause incompatibilties with previous behavior.&nbsp; They are listed first.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Possible Incompatible Changes</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>The command-line parsing routines were rewritten.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This allows for spaces in a command-line to be interpreted correctly as being part of an argument.&nbsp; This means that some of the logic in the command-line parser was changed and may cause problems for some command-lines.&nbsp; Generally, as long as -- is the last argument before the project file name, all should be well.&nbsp; This is a good practice anyway since it denotes exactly where the arguments end and where the file name begins.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Virtual text values are no longer automatically substituted for boolean values</span><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This means that if you were previously counting on InstallJammer to turn "Yes" into 1 or "No" into 0 for you, that behavior is now incompatible.&nbsp; You really should be using the String Is condition to check for true or false because it will always be correct no matter what your true or false value is.&nbsp; If you were relying on this behavior for your variables, I'm sorry that it has to change.&nbsp; The behavior causes more problems than it solves and a lot more confusion because InstallJammer is doing something tricky that people don't expect.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new ::InstallAPI::EncodeURL API</span><span class=rvts2> call.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Zip Archive platform</span><span class=rvts2> for building .zip files from within InstallJammer.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Refresh File List Before Building project preference</span><span class=rvts2> that is Yes by default to continue the current behavior.&nbsp; This can now be turned off, and InstallJammer will not automatically search for new / deleted files and directories when building.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Refresh File Groups button</span><span class=rvts2> to the File Groups tree.&nbsp; This will go and search directories in each file group for new and deleted files and adjust the tree to match.</span></li>
<li class=rvps1><span class=rvts2>When searching for file patterns, the pattern itself will now be substituted for virtual text BEFORE it is split on ;.&nbsp; This means that the virtual text itself can contain a ; and it will be handled properly.</span></li>
<li class=rvps1><span class=rvts2>Added progress output for building .tar and .zip files.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new On and Off Value properties for the Add Widget action</span><span class=rvts2> to handle checkbuttons now that boolean values are not substituted.&nbsp; If the On and Off Values remain 1 and 0, the value of the virtual text will be altered when the checkbutton is created, but the virtual text will not be manipulated after that except by the checkbutton itself.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Restore on Uninstall property</span><span class=rvts2> to the Add Windows Registry Key action.</span></li>
<li class=rvps1><span class=rvts2>Allow the Copy File action to specify multiple patterns as the Source instead of just a single file or directory.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Watch Regular Expression property to Execute External Program</span><span class=rvts2> to specify the regular expression pattern to watch for instead of just always watching for a single pattern.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Echo Input property to the Console Get User Input action</span><span class=rvts2>.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new --build-dir command-line argument</span><span class=rvts2> to specify the temporary build directory.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new --output-dir command-line argument</span><span class=rvts2> to specify the output directory for the installers.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new --verbose command-line argument</span><span class=rvts2> to show more verbose build output.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new &lt;%COMMON_QUICK_LAUNCH%&gt; virtual directory on Windows.</span></li>
</ul>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug in Execute External Program that caused progressive output for console installs to fail.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where root installs failed after a change in 1.2b2.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing virtual text would sometimes fail with a missing variable error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where comments were not being shown correctly for files and directories.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the pane size settings for the main window were not being remembered.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where symlinks on *NIX systems were not being recognized properly.&nbsp; Symlinks should now be included in an installer as a symlink and rebuilt on the target system as such.</span></li>
<li class=rvps1><span class=rvts2>When a command-line build fails for missing files, the build will not properly fail if the option has been selected, and if a previous install existed, it will not be deleted if the build fails for a missing file.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where newly-created action groups could not be used as the target of drag-and-drop actions.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Env Variable Test condition where the Variable property was not being substituted for virtual text before checking.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Remove Windows Registry Key action where specifying a Value meant that the Value would never actually be removed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in Uninstall Selected Files where paths on Windows were not being removed.</span></li>
<li class=rvps1><span class=rvts2>Make sure we only add a directory once in Add Directory to Path.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Install Program Folder Shortcut where the folder name was being ignored on Windows.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in Modify Object where the active property wasn't properly reflect across all of the object.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in Execute External Program where using Include Stderr would leave a $1 file behind.</span></li>
<li class=rvps1><span class=rvts2>\r bytes are now removed from output in Execute External Program before the text is checked for watch patterns.</span></li>
<li class=rvps1><span class=rvts2>Fixed some bugs in Execute External Program where errors were not being propertly returned.</span></li>
<li class=rvps1><span class=rvts2>Fixed some bugs in a few file actions where the linefeeds were being mangled.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in Locate Java Runtime on Windows where JDK directories were not being searched.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where not including English as a language in an installer meant that some messages appeared as blank.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/121.html.






































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.1</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.1">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.1</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="122.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="12.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.1 (October 23rd, 2007)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains minor bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>A note on command-line changes</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The command-line parsing was changed in the 1.2 release, and this has caused a bit of pain for some users.&nbsp; I would recommend reading the help page on the command-line, but the long and short of it is that </span><span class=rvts3>if you are building from the command-line, the safest bet is to make --build the last switch before your project file name.</span><span class=rvts2>&nbsp; Some new command-line options were added to this release, and I urge you to read the documentation to learn their uses, but the note about --build being last is important.&nbsp; It's not required, but you're going to get into a lot less trouble if you heed my advice. :)</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added an official exception to the GPL license for installers.&nbsp; See License for details.</span></li>
<li class=rvps1><span class=rvts2>Added new Rename Project option for projects.</span></li>
<li class=rvps1><span class=rvts2>Added new Duplicate Project option for projects.</span></li>
<li class=rvps1><span class=rvts2>Made Delete Project a lot safer and made the message dialogs a clearer as to what is about to be deleted.</span></li>
<li class=rvps1><span class=rvts2>Removed the Save as option from the File menu.&nbsp; It only caused confusion.&nbsp; Use Duplicate Project instead.</span></li>
<li class=rvps1><span class=rvts2>Made the New option on the File menu create a new project with all the defaults.</span></li>
<li class=rvps1><span class=rvts2>Added a new New Project Wizard option under the File menu to create a new project with the existing wizard.</span></li>
<li class=rvps1><span class=rvts2>Added some debug output to the uninstall process and cleanup.</span></li>
</ul>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Updated the FreeBSD binaries.&nbsp; They were missed in the last release.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would cause command-line builds to fail if they discovered a new file before building.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Target Filename property on files was being ignored.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a project that needed conversion that was built from the command-line would fail with an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a typo that caused the Add Windows Registry Key action to disappear from the last release.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an Add to Uninstall action that added a directory to be forcefully removed wasn't actually being forcefully removed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a missing option bug in Launch Web Browser.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/1210.html.






































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.10</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.10">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.10</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="1211.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="1210b1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.10 (November 13th, 2008)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains minor bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug in the InstallDrive virtual text by defaulting it to the drive where PROGRAM_FILES is located.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the GetWidgetPath API where it would get the path of an enclosing frame instead of the real widget if a widget was added with a label.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where required components could be unchecked by their parent if the parent was unchecked.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Add Widget action could be executed from an action group with no pane as its parent.&nbsp; This would cause a "bad window" error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Uninstall Leftover Files action</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where specifying Categories in the Additional Arguments of the Install UNIX Shortcut action would cause an error instead of working like it should.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where it was impossible to post a message box in a silent install.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Launch Web Browser action where an &amp; in the URL would truncate the URL.&nbsp; This was due to Windows' command-line parsing rules.&nbsp; The new method is to create a URL shortcut in the temp directory and then invoke that shortcut to launch the browser.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where error messages in a command-line build were not output to stderr as they should be.</span></li>
<li class=rvps1><span class=rvts2>Fixed several bugs in the build of zip and tar files.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where silent install would still show a progress bar.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Install Windows Shortcut action that would prevent it from creating a URL shortcut.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Encode URL API.&nbsp; The entire URL was being encoded, which would percent-encode the hostname as well as the query, which is the wrong thing to do.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the new split archives code that was causing split archives not to work on non-Windows platforms.</span></li>
<li class=rvps1><span class=rvts2>Fix a bug where larger installs would fail even on 64 bit systems.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where variables defined on the command-line were being defined after the control script.&nbsp; The control script should have access to the correct values.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where setting platform variables from the command-line would not be set properly.&nbsp; Passing -DExecutable, for example, works now.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the default actions to modify button states on the License and Copy Files panes were happening after the pane had been displayed, which would give the user time to quickly zip by them before the buttons were changed.&nbsp; This change only affects new projects.&nbsp; Older projects will have to be modified to fix this bug.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where file installation would sometimes not reach 100%.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an error during a command-line build would not exit with an error code.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where symlink'd files were being included in the installer instead of a link to the file being created on the target machine.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Move to Pane could not select a pane from the uninstall.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Move Forward and Move to Pane actions would still execute any remaining actions on the current pane after moving forward.&nbsp; Moving now means that any actions after the move are not executed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an installer that specifically did not allow language selection could still get English if the system language was such.&nbsp; This should be addressed further in another version.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Locate Java Runtime action was not accurately picking up the paths from the Windows registry.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Add Directory to Path would fail for .cshrc when the variable didn't already exist.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the language chosen for the installer was not being propagated to the uninstaller correctly.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing text properties for languages with a space in the name (like Brazilian Portuguese) failed to save the edited text correctly.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would sometimes cause an error in the builder after deleting an object and then coming back to that tab.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Install Program Folder Shortcut action where specifying a subfolder in the folder name would be ignored, and the icon would just be installed in the root program folder.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an error during file installation would show an error popup and then just freeze with no way to cancel the installer.&nbsp; The error is now returned up the stack to the Install Selected Files action where it can be handled.&nbsp; This also adds a new &lt;%InstallErrors%&gt; virtual text that contains the error message from the unpack process.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Add Environment Variable action on Windows where the path in the registry would not get expanded for some reason.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the uninstall process would error if no directories were being removed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where building from the command-line would still include debug options even when building for release. (thanks to John Bratteli for the fix).</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the uninstall could exit with an error on cleanup when being executed from another uninstall.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Windows exe information was not being substituted for virtual text when the installer is built.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing the Install Version would cause it to roll back to 1.0.0.0 each time.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the version variables derived from InstallVersion were not being set properly.&nbsp; Passing version information on the command-line should also work as expected now.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added a new Follow File Links property to file groups.&nbsp; This property tells InstallJammer whether to include file links as files or links when building.</span></li>
<li class=rvps1><span class=rvts2>Added a new RollbackInstall API.</span></li>
<li class=rvps1><span class=rvts2>Removed AIX, FreeBSD 4, FreeBSD 5 and HPUX as builder platforms.&nbsp; This does not mean these platforms are no longer supported.&nbsp; It means they are no longer supported as GUI builder platforms.&nbsp; They also do not support LZMA compression when building on these platforms.</span></li>
<li class=rvps1><span class=rvts2>Added a new CopyObject API call.</span></li>
<li class=rvps1><span class=rvts2>Added a new Encoding property to the Replace Text in File and Write Text to File actions.</span></li>
<li class=rvps1><span class=rvts2>Editable text widgets now tab to the next widget when hitting Tab instead of inserting a tab in the text box.&nbsp; A Control-Tab can be used to insert a tab if it's really necessary.</span></li>
<li class=rvps1><span class=rvts2>Added a new Append Text to Widget action.</span></li>
<li class=rvps1><span class=rvts2>Added a new SetExitCode API.</span></li>
<li class=rvps1><span class=rvts2>Added a new Exit Code property to the Exit action.</span></li>
<li class=rvps1><span class=rvts2>The special platforms "tar" and "zip" are now acceptable as platforms to enable the tar and zip archive targets.</span></li>
<li class=rvps1><span class=rvts2>Added a new Build Separate Archives property to all platforms.&nbsp; This property allows installers to be built with files being separate archives that are mounted on startup.&nbsp; This means that the installers are no longer one single executable, but it makes it possible to avoid some size limitations on 32 bit platforms.</span></li>
<li class=rvps1><span class=rvts2>Added a new progress bar for console installs.&nbsp; A new Show Console Progress property was added to the Install Selected Files action which is enabled by default.</span></li>
<li class=rvps1><span class=rvts2>Added a new Clear Progressive Widget property to the Execute External Program action to specify whether the progressive output widget should be cleared before the program exits.&nbsp; The default is Yes, which was the previous behavior.</span></li>
<li class=rvps1><span class=rvts2>Added a new Install Executable Description property to Windows that is used as the File Description in the exe properties.&nbsp; This defaults to what it has always been: &lt;%AppName%&gt; &lt;%Version%&gt; Setup.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/1210b1.html.
































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.10b1</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.10b1">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.10b1</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="1210.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="129.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.10b1 (October 16th, 2008)</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>This release contains minor bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug where the default actions to modify button states on the License and Copy Files panes were happening after the pane had been displayed, which would give the user time to quickly zip by them before the buttons were changed.&nbsp; This change only affects new projects.&nbsp; Older projects will have to be modified to fix this bug.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where file installation would sometimes not reach 100%.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an error during a command-line build would not exit with an error code.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where symlink'd files were being included in the installer instead of a link to the file being created on the target machine.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Move to Pane could not select a pane from the uninstall.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Move Forward and Move to Pane actions would still execute any remaining actions on the current pane after moving forward.&nbsp; Moving now means that any actions after the move are not executed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an installer that specifically did not allow language selection could still get English if the system language was such.&nbsp; This should be addressed further in another version.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Locate Java Runtime action was not accurately picking up the paths from the Windows registry.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Add Directory to Path would fail for .cshrc when the variable didn't already exist.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the language chosen for the installer was not being propagated to the uninstaller correctly.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing text properties for languages with a space in the name (like Brazilian Portuguese) failed to save the edited text correctly.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would sometimes cause an error in the builder after deleting an object and then coming back to that tab.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Install Program Folder Shortcut action where specifying a subfolder in the folder name would be ignored, and the icon would just be installed in the root program folder.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an error during file installation would show an error popup and then just freeze with no way to cancel the installer.&nbsp; The error is now returned up the stack to the Install Selected Files action where it can be handled.&nbsp; This also adds a new &lt;%InstallErrors%&gt; virtual text that contains the error message from the unpack process.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Add Environment Variable action on Windows where the path in the registry would not get expanded for some reason.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the uninstall process would error if no directories were being removed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where building from the command-line would still include debug options even when building for release. (thanks to John Bratteli for the fix).</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the uninstall could exit with an error on cleanup when being executed from another uninstall.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Windows exe information was not being substituted for virtual text when the installer is built.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing the Install Version would cause it to roll back to 1.0.0.0 each time.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the version variables derived from InstallVersion were not being set properly.&nbsp; Passing version information on the command-line should also work as expected now.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug introduced in 1.2.8 where an install registry would not get cleaned up properly.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where cleaning up a canceled install could cause errors and freeze the installer under certain conditions.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an uninstaller would sometimes report that a directory could not be removed because it was not empty when it actually was.&nbsp; This fix now means that directories are not necessarily removed in the same order they were installed.</span></li>
<li class=rvps1><span class=rvts2>Fix a possible error case when attempting to set file permissions on a file that doesn't exist.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where stopping an install might still try to execute some further code after things had stopped.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an error in an action would not get propagated up to show an error message.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a message box in an uninstaller could fail and hang without an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an uninstall that did not have permissions would attempt to do a lot of things that just weren't possible.&nbsp; The uninstall should fail gracefully now and give the user proper error messages.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added a new Build Separate Archives property to all platforms.&nbsp; This property allows installers to be built with files being separate archives that are mounted on startup.&nbsp; This means that the installers are no longer one single executable, but it makes it possible to avoid some size limitations on 32 bit platforms.</span></li>
<li class=rvps1><span class=rvts2>Added a new progress bar for console installs.&nbsp; A new Show Console Progress property was added to the Install Selected Files action which is enabled by default.</span></li>
<li class=rvps1><span class=rvts2>Added a new Clear Progressive Widget property to the Execute External Program action to specify whether the progressive output widget should be cleared before the program exits.&nbsp; The default is Yes, which was the previous behavior.</span></li>
<li class=rvps1><span class=rvts2>Added a new Install Executable Description property to Windows that is used as the File Description in the exe properties.&nbsp; This defaults to what it has always been: &lt;%AppName%&gt; &lt;%Version%&gt; Setup.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/1211.html.














































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.11</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.11">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.11</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="1212.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="1210.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.11 (December 1st, 2008)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains minor bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fix a bug in the uninstaller that can occur on Windows systems where the .vbs file extension is messed up in the registry.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Uninstall Selected Files action that would sometimes occur when using the Remove from Uninstall action.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would only occur on some Windows system where a permission denied error would appear on startup.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where &lt;%Platform%&gt; was not expanded in the name of archive files.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where passing /help as an argument to an installer on Windows would show a message box with the title "In-Valid Argument."</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where double-clicking a check box in an option tree would cause the check button to toggle twice, but the command wouldn't fire. &nbsp;This leaves some components in the wrong state.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where going back-and-forth between a custom setup component screen could leave the components in an unknown state.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Add Directory to Path and Add Environment Variable will now also make the same change to the running installer's environment.</span></li>
</ul>

</div></body></html>
Added docs/html/1212.html.


























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.12</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.12">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.12</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="1213.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="1211.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.12 (December 2nd, 2008)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This is a minor bug fix release.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug in the URLIsValid API.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Windows installkits that was causing installers signed with a digital signature to fail.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/1213.html.






























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.13</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.13">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333399" face="Verdana"><b>1.2.13</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="1214.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="1212.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.13b2 (May 3rd, 2009)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains minor bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug where the Select Destination pane would not properly substitute the destination label when updating the pane.</span></li>
<li class=rvps1><span class=rvts2>Installing UNIX shortcuts as root will not install them for all users and not for the root user.&nbsp; This does not count for desktop icons, only for program folders and shortcuts.</span></li>
<li class=rvps1><span class=rvts2>Removed the code to restart the gnome-panel on Gnome desktops.&nbsp; It seems like the panel will automatically pick up the changes on its own now.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the default system language was not getting picked up properly on some Windows systems.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug with the choose directory dialog on Vista where it was still looking for My Documents even though Vista just calls it Documents.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where trying to launch explorer in a directory on Vista would just open the explorer to the My Computer screen.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where tar and zip archives did not auto refresh files when the Refresh File List Before Building preference was turned on.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Create File Link action where it would fail on UNIX systems if the link target did not already exist.&nbsp; This will remain a requirement for Windows platforms however.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Execute External Program action where the Progressive Output Widget could not be found when the action was nested in an action group.</span></li>
<li class=rvps1><span class=rvts2>Cleaned up all of the message catalogs to remove double spaces when displaying text in some panes.&nbsp; These extra spaces were part of the actual message catalog and not a bug in the installers.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where some actions (like WriteTextToFile) that log files would error out when running inside of an uninstaller.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing some text fields would not cause the project to become modified.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where setting Windows file attributes on a non-Windows platform would then cause an error during installation.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Platform Condition where not all platforms were available.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Execute External Program action where watching for output to the Status virtual text could cause an infinite loop error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Uninstall Leftover Files was failing on console installs.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where actions after a Move Forward or Move to Pane action would still be executed when they should be skipped.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where icons and menus were not being properly removed during uninstall on the Linux platform.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that broke solid compression builds on all platforms.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where using an install password would fail due to a missing function.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug when running multiple installers and closing a child installer would delete the temporary directory out from under the parent.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Locate Java Runtime action where it would attempt to prompt the user with a dialog in a console install.&nbsp; For now, there is no prompt for the user in a console install, it is simply ignored.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Modify Widget action could end up clearing a text widget even if no text was specified.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a file group's size was not accurate when following</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where tar and zip archives with no files would error with a big, ugly error message.&nbsp; It's a little more graceful now.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where upgrade installers were not being included as part of the original install during uninstall because of a mismatch in the registry info.</span></li>
<li class=rvps1><span class=rvts2>Fixed several bugs related to installers running under WINE.&nbsp; Installers and uninstallers should now run successfully under WINE.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Reboot or Shutdown System action for UNIX systems where no time was specified.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in uninstall on HP-UX.&nbsp; All platforms now perform the same uninstall that was previously reserved for Windows.&nbsp; Which is to say that the uninstaller is copied off to a temporary location before executing it so that the original uninstaller can be deleted in place.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would affect launching installers that launch other installers where the child installer would delete the temporary directory out from under the parent, leaving the parent to error out.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where creating desktop shortcuts on Linux Gnome desktops would fail if the desktop directory was not called Desktop, as it is on non-English systems.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the uninstall on Windows would leave a hanging process after exiting.&nbsp; This would cause problems when the uninstaller was called from some other program.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in message dialogs where the X button on the window would do nothing.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in message dialogs where the initial focus button was not correct.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing a virtual text string from the editor would not save when the editor closed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Launch Web Browser action would not work properly on some versions of Windows.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where passing /version to an uninstaller would cause an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the UNIX permissions were being flipped in the builder.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added a new VirtualTextAPI API call.</span></li>
<li class=rvps1><span class=rvts2>Added a new LanguageAPI API call.</span></li>
<li class=rvps1><span class=rvts2>Added a new Require Administrator option to the Windows platform.</span></li>
<li class=rvps1><span class=rvts2>Added a new Use Uncompressed Binaries option to the Windows platform.</span></li>
<li class=rvps1><span class=rvts2>Added a new RequireAdministratorText virtual text to the English message catalog.&nbsp; This message will appear when the user doesn't have the required administrator privileges.</span></li>
<li class=rvps1><span class=rvts2>Added a new Installkit property to the Install Wrapped Script action.</span></li>
<li class=rvps1><span class=rvts2>Added a new ConfigAPI API call to configure internal settings.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the system language might not get used even when the message catalog is compiled into the installer.</span></li>
<li class=rvps1><span class=rvts2>Added a new Default To System Language install feature to specify that the default language on the installing system should be used if it exists within the installer's message catalog.&nbsp; Otherwise, the Default Language will be used.</span></li>
<li class=rvps1><span class=rvts2>Added new permissions to the File Permission Condition.</span></li>
<li class=rvps1><span class=rvts2>Added new &lt;%ErrorFiles%&gt; and &lt;%ErrorDirs%&gt; virtual text that are set during uninstallation when it fails to remove files or directories.</span></li>
<li class=rvps1><span class=rvts2>In most properties, widgets can now be specified as &lt;pane&gt;.&lt;widget&gt; to specify exactly which pane and widget is meant.</span></li>
<li class=rvps1><span class=rvts2>Added a new Install UNIX Program Folder action to allow creating program folders with more options like icons.</span></li>
<li class=rvps1><span class=rvts2>Added new "matches" and "does not match" operators to the Platform Condition.</span></li>
<li class=rvps1><span class=rvts2>Added the ability to enable response files for installers.&nbsp; Response files let a user save their responses from an install and replay them in another install later.</span></li>
<li class=rvps1><span class=rvts2>Added a new Enable Response Files install feature.&nbsp; This will be true by default in projects using version 1.2.13 and higher.</span></li>
<li class=rvps1><span class=rvts2>Added a new Add Response File Info action to enable adding virtual text to a response file when they are enabled.</span></li>
<li class=rvps1><span class=rvts2>Made the SelectedComponents virtual text writable.&nbsp; Whenever this virtual text is changed, it will overwrite the current set of selected components.</span></li>
<li class=rvps1><span class=rvts2>Added a new ComponentAPI API call.</span></li>
<li class=rvps1><span class=rvts2>Added a new CommandLineAPI API call.</span></li>
<li class=rvps1><span class=rvts2>Added a new ResponseFileAPI API call.</span></li>
<li class=rvps1><span class=rvts2>Added a new Disable / Revert Wow64 Redirection and action to disable Windows 64 bit filesystem redirection.</span></li>
<li class=rvps1><span class=rvts2>The Locate Java Runtime action now includes a full version number in the &lt;%JavaAvailableVersions%&gt; virtual text.</span></li>
<li class=rvps1><span class=rvts2>Added a new &lt;%JavaVersionMinor%&gt; that is set by the Locate Java Runtime action.</span></li>
<li class=rvps1><span class=rvts2>The Locate Java Runtime action now substitutes virtual text properly in the search path.&nbsp; Also added some debugging to see where the action is looking for Java on the system.</span></li>
<li class=rvps1><span class=rvts2>The Locate Java Runtime action now handles Java versions properly, so you can use a version like 1.6.0_10 as a minimum or maximum.&nbsp; Previously, the version after the _ was invalid.</span></li>
<li class=rvps1><span class=rvts2>Added a new Vendor ID to the UNIX shortcut actions to allow for shortcuts to be grouped together under a particular vendor.&nbsp; This makes it easy for multiple installers to create shortcuts in the same program folders.</span></li>
<li class=rvps1><span class=rvts2>The Focus on Widget action should now work for built-in widgets as well, not just ones added with an Add Widget action.</span></li>
<li class=rvps1><span class=rvts2>Added a new Save Files property to file groups and directories to allow for finer-grained access to the Save Only Toplevel Directories project preference.</span></li>
<li class=rvps1><span class=rvts2>Added a new Application ID property to the Get Previous Install Info action.</span></li>
<li class=rvps1><span class=rvts2>Added a new ReadInstallInfo API.</span></li>
<li class=rvps1><span class=rvts2>Added a new AddInstallInfo API.</span></li>
<li class=rvps1><span class=rvts2>Added a new PreviousInstallIDs virtual text that is set after reading previous install info.</span></li>
<li class=rvps1><span class=rvts2>Added a new --build-log-file command-line option to the install builder.</span></li>
<li class=rvps1><span class=rvts2>Doing a full build (not quick) now automatically jumps to the build screen before the build begins to show the log.</span></li>
<li class=rvps1><span class=rvts2>The Modify Widget action should now properly handle textboxes when modifying the text property.</span></li>
<li class=rvps1><span class=rvts2>Added a new DestroyWidget API call.</span></li>
<li class=rvps1><span class=rvts2>The Destroy Widget action can now take a list of widgets separated by ;.</span></li>
<li class=rvps1><span class=rvts2>InstallDirSuffix can now contain more than a single directory, and the whole string will be joined with the InstallDir anytime it is changed.</span></li>
<li class=rvps1><span class=rvts2>Added a new Selectable property to Components that, if false, will turn a component in the component tree into a header with no check or radio button.</span></li>
<li class=rvps1><span class=rvts2>Added NONE as an option for buttons on a pane.</span></li>
<li class=rvps1><span class=rvts2>Made the text in the language selection dialog part of the English message catalog instead of a hard-coded value.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/1214.html.


























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.14</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.14">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 text-indent: -48px;
 margin: 0px 0px 0px 48px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333399" face="Verdana"><b>1.2.14</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ReleaseNotes.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="1213.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.14 (September 18th, 2009)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains minor bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: -24px; margin-left: 48px; list-style-position: outside;">
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where the uninstaller on Windows would sometimes fail to delete the uninstall.exe which would cause an empty directory error.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where the uninstaller would pop up an error message after finishing if the machine had host scripting disabled.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where desktop icons were not being created on the Linux-x86_64 platform.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where desktop icons created when installing as root could not be read by a normal user.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where desktop icons need to be created with the executable bit set for some platforms and window managers.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where clicking the delete button in the virtual text tab would not delete the virtual text currently being edited.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where the Default to System Language property was not being saved in the installer, so the value was ignored.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed the display of Polish language strings in the installer and uninstaller.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug in the Create File Link action where the order of the link and its target were accidentally reversed on non-Windows platforms.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where toggling components in certain cases could cause an error.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where attempting to focus on a browse entry widget would focus on nothing when it should focus on the browse button.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where if the last pane of a wizard was conditional, the wizard could end up displaying a blank pane at the end instead of exiting when the wizard moved forward.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where editing the long description of a command-line option would fail in an error.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where writing out script properties in project files could make them end up very difficult to read.  This changes the way object properties are written for anyone manipulating project files by hand.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where encrypted installers would not install files correctly on non-Windows platforms.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where Add Directory to Path on non-Windows systems could mangle the PATH environment variable after executing.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Removed more hard-coded English strings from the uninstaller.  They still require translation for other languages, but they're no longer hard-coded into the code.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a selection bug in the choose directory dialog.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where the selection in the entry of the choose directory dialog would incorrectly highlight the directory.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where the builder would not run propertly on x86_64 Linux machines.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where specifying a password did not encrypt separate archives when in Build Separate Archives mode.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where the Install UNIX Shortcut action did not offer the Command Line Arguments property even though it was supposed by other actions.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fix a bug in the Execute External Program action where terminals taken from the TERM environment variable could fail because of the hard-coded -t title option.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where building Windows installers on non-Windows platforms could result in symlinks being packaged incorrectly as links and not followed as files.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where --version on non-Windows platforms would error out.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug where the "can create" operator in the File Test condition was reporting incorrectly on non-Windows platforms.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Fixed a bug that removed the hidden value for the Window State property of the Install Windows Shortcut action.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: -24px; margin-left: 48px; list-style-position: outside;">
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Added a Control-click to the virtual text table to select a row for deletion without editing the contents.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Added a Shift-click to the virtual text table to select multiple rows within the table for deletion.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Added Czech translations (thanks to Kamil P?\195?\161ral!)</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Changed the title of the default silent actions and the main install action on the Copy Files pane to better represent what is going on when reading the tree.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Added new &lt;%InstallStartupDir%&gt; and &lt;%UninstallStartupDir%&gt; virtual text variables that contain the directory the (un)installer was launched from.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Changed the wording of the Yes and No buttons on the license pane.  They were a holdover from the Classic Wizard, and the text doesn't make sense in the context of the new pane.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Added a new WizardAPI API call.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Added a new Description property to the Create Windows Service action that will allow the action to specify a description of the service being created.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Added titles to the default console actions to give a better idea of what's going on when looking at them in the tree.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Added a new SetInstallPassword API.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Made it possible to copy-and-paste objects between two different instances of InstallJammer.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Added a new PropertyFileAPI API call to handle reading .properties files.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Added new &lt;%Tolower string%&gt; and &lt;%Toupper string%&gt; virtual text.</span></li>
<li class=rvps2 style="margin-left: 0; text-indent: -24px"><span class=rvts2>Removed the "Install Error" and "Exit Setup" hard-coded English strings and added new virtual text in the English message catalog to replace them.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/122.html.






























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.2</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.2">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.2</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="123.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="121.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.2 (October 25th, 2007)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This is a minor bug fix release.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug on UNIX platforms where creating a directory that isn't writable would cause the rest of the install to fail when it tried to write into that directory.&nbsp; Directory permissions are now set after all files have been installed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a typo in Uninstall Selected Files that would cause a failure when restoring a registry value on Windows. [</span><span class=rvts3>Bug #1819503</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a typo in ::InstallAPI::EncodeURL that would cause Launch Web Browser actions to fail. [</span><span class=rvts3>Bug #1819487</span><span class=rvts2>]</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/123.html.




























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.3</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.3">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.3</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="124.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="122.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.3 (October 26th, 2007)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This is a minor bug fix release.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a typo Add Windows Registry action.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Alias handling code that caused new projects to fail with an error saying Install Actions could not be found.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that causes multiple projects loaded in the same session to build and output into the wrong directories.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/124.html.




















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.4</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.4">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.4</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="125.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="123.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.4 (January 13rd, 2008)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains minor bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed some minor bugs in the Choose Directory dialog.</span></li>
<li class=rvps1><span class=rvts2>Added a check for illegal characters in a directory name.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in keyboard navigation in the choose directory dialog.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in Modify Widget where modifying existing text properties was not modifying the text properly.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where populating components with radiobuttons where no button was checked would make them all checked.</span></li>
<li class=rvps1><span class=rvts2>Reading project files no longer assumes a UTF-8 encoding.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the WINDOWS virtual text was being reported incorrectly on some systems.&nbsp; Despite my better judgment, we'll trust the environment variables.</span></li>
<li class=rvps1><span class=rvts2>Symbolic links are now created using the system 'ln -s'.&nbsp; The built-in Tcl 'file link' command seems to be poorly thought out.</span></li>
<li class=rvps1><span class=rvts2>Removed dummy license text from all but English translations so that a single license will display correctly in all languages.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the buttons on the new project wizard would sometimes not appear correctly.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Read File Into Virtual Text now reads files as text instead of binary by default.</span></li>
<li class=rvps1><span class=rvts2>Added new Remove From Uninstall action.</span></li>
<li class=rvps1><span class=rvts2>Added new actions to deal with Windows services.</span></li>
<li class=rvps1><span class=rvts2>Added new Windows Service Test condition for testing Windows services.</span></li>
<li class=rvps1><span class=rvts2>Installs are now built entirely to a temporary file and only renamed to their final location once the build has completely successfully.&nbsp; This means that broken builds will not overwrite good installers that area already there.</span></li>
<li class=rvps1><span class=rvts2>If a build fails with errors, it is now reported as having failed instead of completed.</span></li>
<li class=rvps1><span class=rvts2>The files being packed are now shown as full paths instead of filenames.&nbsp; This makes it easier to identify files within a build at the expense of some clutter.</span></li>
<li class=rvps1><span class=rvts2>Building solid archives now shows packing log messages.</span></li>
<li class=rvps1><span class=rvts2>Added a new debugging command to turn debugging on and off more easily from the console as well as log debug information to a file.</span></li>
<li class=rvps1><span class=rvts2>Browsing for a directory will now initialize to the current directory if it exists.</span></li>
<li class=rvps1><span class=rvts2>Checking conditions can now have a boolean AND or OR instead of just always being AND.</span></li>
<li class=rvps1><span class=rvts2>Added the ability to specify that conditions should be matched with an AND (Match all of the following) or an OR (Match any of the following).</span></li>
<li class=rvps1><span class=rvts2>Added a Build Failure project preference to tell InstallJammer how to handle missing files when building from the GUI.</span></li>
<li class=rvps1><span class=rvts2>Added new ExecuteAction API call.</span></li>
<li class=rvps1><span class=rvts2>Added Dutch translations (thanks to Jethro Borsje!).</span></li>
<li class=rvps1><span class=rvts2>Added Italian translations (thanks to LukenShiro!).</span></li>
<li class=rvps1><span class=rvts2>Added Hungarian translations (thanks to Nagy Istvan!).</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/125.html.


























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.5</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.5">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.5</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="126.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="124.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.5 (February 5th, 2008)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains minor bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Open and Save project files with a utf-8 encoding so that non-ASCII text is automatically translated and made correct with each load and save.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where copying and pasting and object would miss the text properties.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Windows Service Test condition where the condition would error-out if the service did not exist.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Modify Widget action that didn't handle framed widgets.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Focus on Widget action where it didn't handle widgets embedded in frames.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added new Size property to Components.</span></li>
<li class=rvps1><span class=rvts2>Added new Size property to File Groups.</span></li>
<li class=rvps1><span class=rvts2>Added new Display Name property to Components.</span></li>
<li class=rvps1><span class=rvts2>Added new Display Name property to Setup Types.</span></li>
<li class=rvps1><span class=rvts2>Added a new Encoding property to the Read File Into Virtual Text action.</span></li>
<li class=rvps1><span class=rvts2>Added new Register Windows Library action.</span></li>
<li class=rvps1><span class=rvts2>Added new Unregister Windows Library action.</span></li>
</ul>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/126.html.










































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.6</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.6">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.6</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="127.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="125.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.6 (June 22nd, 2008)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains minor bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fix a bug where modified files don't get updated in the unpack process, so changes to file objects never get noticed when unpacked.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the classic wizard init that would cause it to fail.</span></li>
<li class=rvps1><span class=rvts2>Fixed a missing quote in the Dutch translations for the Classic Wizard that would cause an error when creating a new project with this theme.</span></li>
<li class=rvps1><span class=rvts2>Fix a bug where using \ in an image path can cause the image to get lost at runtime.</span></li>
<li class=rvps1><span class=rvts2>Fixed a nasty little bug where the File Update Method was not being respected for files being installed.&nbsp; This would cause things like date checks to fail and overwrite modified, existing files.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where canceling during installation would sometimes cause the process to freeze until killed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where canceling during installation could cause an error because the unpack proceeds and tried to update a file that wasn't installed.</span></li>
<li class=rvps1><span class=rvts2>Committed the correct version of the LZMA library on Windows.&nbsp; This will fix issues with building installers using LZMA compression on Windows.</span></li>
<li class=rvps1><span class=rvts2>Modernized the choose directory dialog.&nbsp; The label showing the directory is gone, and the entry now reflects the entire folder path.&nbsp; The entire path is now checked for valid characters before closing the dialog.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that caused integer overflows in diskspace calculations on non-Windows platforms.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where errors could cause errors with install title text.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where changing the language would not update the install title with the appropriate title for the new language.</span></li>
<li class=rvps1><span class=rvts2>Several fixes to dialog transient parent handling and some new variables to control native dialogs.</span></li>
<li class=rvps1><span class=rvts2>Fix a bug in the bgerror handler.</span></li>
<li class=rvps1><span class=rvts2>Fix a bug that causes an error message when building with no files.</span></li>
<li class=rvps1><span class=rvts2>Removed the dummy test for Readma panes so that they don't display the wrong information in a language other than English.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the various move wizard actions would always move on step extra because the wizard was not noticing that the actions had moved forward.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where not all languages would appear as choices in the builder.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where opening the condition editor could cause copy-and-paste actions to not work anymore.</span></li>
<li class=rvps1><span class=rvts2>Fixed a typo in the &lt;%FileGroup%&gt; virtual text that caused an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in Execute External Program where using progressive output would not accurately set the exit status on error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the SetActiveSetupType API where it was not repopulating the components correctly.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Unpack Stored File action would create the original install directory for the packed file by mistake.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Execute Script action where returning a value would result in an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that would not allow multiple directories with the same name to exist in a file group.</span></li>
<li class=rvps1><span class=rvts2>Made builds more robust when we hit unexpected errors.&nbsp; The errors should now go correctly to the build log, and the builder should go back to a known state so that the build can be tried again.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where multiple channels were opened to the debug log.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in shortcut actions where setting Command Line Properties did not propagate on UNIX platforms.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where passing --temp on the command line would not actually set the Temp virtual text.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where attempting to paste an object with conditions would cause an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed several bugs with message boxes on non-Windows platforms.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug and an inconsistency with the SpaceAvailable virtual text on non-Windows platforms.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where deleting objects from the system would not remove all of their virtual text from the project file.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where opening a project from the right-click menu in the project list would result in an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in ::InstallAPI::FindProcesses on Windows.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where using tk_getOpenFile would error on non-Windows platforms.</span></li>
<li class=rvps1><span class=rvts2>Fixed several bugs relating to "match any" conditions.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where opening a choose directory dialog from a Windows network share would error out.</span></li>
<li class=rvps1><span class=rvts2>Removed the entry box on the choose directory dialog.&nbsp; Make New Folder is sufficient for specifying a folder name, and the entry was just confusing.</span></li>
<li class=rvps1><span class=rvts2>Fixed several bugs between setting Aliases of objects and their title in the component tree.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that caused the Setup Actions group to never actually execute.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in ::InstallAPI::PromptForFile on Windows.</span></li>
<li class=rvps1><span class=rvts2>Fix a small bug for command-line builds.</span></li>
<li class=rvps1><span class=rvts2>Fix a bug in installers with non-ASCII characters.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where condition failure messages would pop up in the wrong place on some systems.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where symlink'd files on UNIX were being truncated once installed on Windows.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a symlink'd directory would end up creating a recursive symlink on the target system during installation.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Modify Widget action where the parent could not be determined if the action was attached to a checkbutton or something else.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Added more functionality to the debugging command to allow for specifying whether you want to debug to the console or file or both.</span></li>
<li class=rvps1><span class=rvts2>Added a new Validate Entry On property to the Add Widget action.&nbsp; This will allow entry widgets to specify an action that is executed when certain events happen.</span></li>
<li class=rvps1><span class=rvts2>Install Windows Shortcut will now use TWAPI as its method of creating the shortcut when it is available.&nbsp; This will fix the problems many people are having installing shortcuts on Asian character sets in Windows.</span></li>
<li class=rvps1><span class=rvts2>Added a -encoding option to the LoadMessageCatalog API.</span></li>
<li class=rvps1><span class=rvts2>Added the ability to specify configuration options at the top of a message catalog file in the form of key-value pairs. (-encoding utf-8 etc...).</span></li>
<li class=rvps1><span class=rvts2>Added a new "All" language to text fields that will set all languages with the same message when used.&nbsp; When retrieving text for the All language, text will only be retrieved if all languages have the same text.&nbsp; Otherwise, the text is blank.</span></li>
<li class=rvps1><span class=rvts2>Added a link on the Help menu to the Support Forums.</span></li>
<li class=rvps1><span class=rvts2>Adding Russian translations (thanks to Stanislav Borutsky</span></li>
<li class=rvps1><span class=rvts2>The order of Before Pane is Displayed actions and conditions has been reversed.&nbsp; Previously, the actions would execute first, but this is the opposite of the way every other check works.&nbsp; The conditions will now be checked before the pane is displayed, and if they fail, the wizard will move forward without ever executing the actions.</span></li>
<li class=rvps1><span class=rvts2>Added a new AddLanguage API call.</span></li>
<li class=rvps1><span class=rvts2>Added new PromptForDirectoryNewFolderText virtual text to the English message catalog.&nbsp; This is the default text for the Make New Folder button on the Choose Directory dialog.&nbsp; Translations will be added as they become available.</span></li>
<li class=rvps1><span class=rvts2>Added a new -object option the SetVirtualText API.&nbsp; This allows for setting virtual text on objects like panes and actions.</span></li>
<li class=rvps1><span class=rvts2>Added new LoadMessageCatalog API.</span></li>
<li class=rvps1><span class=rvts2>Added a new, powerful FindObjects API for locating just about anything in the system.</span></li>
<li class=rvps1><span class=rvts2>The system default language will now be used as the default language in the installer if it is supported.&nbsp; If the installer does not include the language for the user's system, the Default Language will be used in its place.</span></li>
<li class=rvps1><span class=rvts2>Added a new Editor external program preference to specify an editor to use when editing multi-line text.&nbsp; InstallJammer will create a temporary file, execute the selected editor and watch for changes on the file and propagate them back into the project.</span></li>
<li class=rvps1><span class=rvts2>Re-enabled the Save as button for projects.&nbsp; With the new Duplicate Project option, this shouldn't be nearly as confusing as before.</span></li>
<li class=rvps1><span class=rvts2>Added a check when saving to see if the project file is writable.&nbsp; If it's not, InstallJammer can attempt to make the file writable before saving at the user's request.</span></li>
<li class=rvps1><span class=rvts2>Added a new Watch Virtual Text property to allow matching of patterns without an actual virtual text variable in the pattern.&nbsp; Regular expressions with less than two sub match patterns will use this variable as the default.</span></li>
<li class=rvps1><span class=rvts2>Added new Include TWAPI property to the Install Wrapped Script action.&nbsp; This allows wrapped scripts on the target system to include the TWAPI extension on Windows platforms.&nbsp; The script will be automatically modified with a small header to load the TWAPI extension automatically.</span></li>
<li class=rvps1><span class=rvts2>Added the ability to specify images in an installer at runtime.&nbsp; Image properties can now contain a file on the build system, a file on the target system or an ID or Alias to a file stored within the installer.</span></li>
<li class=rvps1><span class=rvts2>Added a new Command Line Actions group that replaces the Setup Actions group in terms of location.&nbsp; The Command Line Actions group executes before the command-line options have been parsed, and the Setup Actions group now executes after the command-line options have been parsed.</span></li>
<li class=rvps1><span class=rvts2>Added a new Test Component property to Panes, Actions and Conditions.&nbsp; This property tells the (un)installer whether the given component should be executed when the installer is run in test mode.&nbsp; This allows to disabling things like license panels and other annoying things when a developer is testing.</span></li>
<li class=rvps1><span class=rvts2>Changed Test Component feature to Include with more options than just Yes or No.</span></li>
<li class=rvps1><span class=rvts2>Added new --test-without-installing command-line build option to pass the --test option to the installer when testing.</span></li>
<li class=rvps1><span class=rvts2>Made it legal to pass a directory on the command-line, and the builder will figure out which project file in the directory to use if it can.</span></li>
<li class=rvps1><span class=rvts2>When a project is converted to a new version, it is now automatically saved, and a backup is made of the previous project file.</span></li>
<li class=rvps1><span class=rvts2>Added new Wizard Height and Wizard Width properties to the Install Features section.&nbsp; These allow the developer to alter the size of the wizard during (un)installation.</span></li>
<li class=rvps1><span class=rvts2>Added a new Default Directory Location to the Project Preferences.&nbsp; This property, if set, specifies the Location to use for all files and directories that are direct descendants of a file group if their own Location is not set.</span></li>
<li class=rvps1><span class=rvts2>The SetVirtualText API now recognizes update actions and commands on language-specific virtual text.&nbsp; This allows tracking changes to language text.</span></li>
<li class=rvps1><span class=rvts2>The SetVirtualText API's -language option now accepts the language code or full language name (en or English, etc...).</span></li>
<li class=rvps1><span class=rvts2>The title of the installer and wizard are now specified in the InstallTitleText virtual text.&nbsp; Both will update automatically anytime this virtual text changes.</span></li>
<li class=rvps1><span class=rvts2>Windows command-line builds are now done synchronously through a new installjamemr.com binary.&nbsp; This will better allow scripting builds on the Windows platform.</span></li>
<li class=rvps1><span class=rvts2>Added a -glob argument to ::InstallAPI::FindProcesses (Windows-only currently).</span></li>
<li class=rvps1><span class=rvts2>Installers will now focus on the Next button by default when moving panes.</span></li>
<li class=rvps1><span class=rvts2>When editing a property, clicking away from the property will now auto-save the property.&nbsp; You no longer have to hit Return to save the change.&nbsp; This may cause some problems with errors in properties.</span></li>
<li class=rvps1><span class=rvts2>Added new Require Response property to the Console Get User Input action.&nbsp; This says that the user cannot provide an empty response and must give something.</span></li>
<li class=rvps1><span class=rvts2>Added a Package Databases property to the Register Package action.&nbsp; This allows the developer to specify that they only want to support RPM, DPKG or all package managers.&nbsp; All is the default for backward compatibility.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/127.html.










































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.7</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.7">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.7</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="128.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="126.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.7 (July 7th, 2008)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains major bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Major Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fix a nasty bug where clicking File -&gt; New to create a new project does not close any open project and will instead overwrite the open project and blow it away.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug where moving an Add Widget action to another pane wouldn't actually change its preview parent, so clicking Preview Pane on the action would preview its old pane.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where building the uninstaller on some systems would build an uninstall that fails in GUI mode.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the uninstall could delete the Install Dir even if the installer was not the one who created it.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Setup Actions could error checking conditions.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where executing an action with an alias could end up deleting the alias, which would cause subsequent executions of that action by-alias to fail.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the new project wizard dialog was not modal.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where configuring some install or uninstall mode that did not exist would cause an error in the install.&nbsp; Each will now use the standard mode if the given mode is bogus.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where building from the command line would expose the Install Password in the Install Password pane during installation.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the order of UNIX file permissions.&nbsp; The checkbuttons were in the correct order, but the code was not picking up the permissions in the correct order.&nbsp; The read and execute bits were flipped.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Reworked the Add Widget action's properties page to separate type-specific properties into an Advanced Properties tab with the standard widget properties under a Widget Properties tab.</span></li>
<li class=rvps1><span class=rvts2>Added a new File Types property to the Add Widget action for browse entry widgets.</span></li>
<li class=rvps1><span class=rvts2>Added a new combobox widget type to the Add Widget action.</span></li>
<li class=rvps1><span class=rvts2>Added a new Separator property to the Add Directory to Path action.</span></li>
<li class=rvps1><span class=rvts2>Added a new Separator property to the Remove Directory from Path action.</span></li>
<li class=rvps1><span class=rvts2>Added a new Normalize Paths property to the Add Directory to Path action.</span></li>
<li class=rvps1><span class=rvts2>Set correct default and cancel buttons for standard message dialogs.</span></li>
<li class=rvps1><span class=rvts2>Added a new Preserve Windows File Attributes project preference.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/128.html.














































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.8</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.8">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.8</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="129.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="127.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.8 (August 3rd, 2008)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This is a minor bug fix release.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug where loading a corrupted preferences file would cause a crash.&nbsp; A corrupted preferences file should just be deleted.</span></li>
<li class=rvps1><span class=rvts2>All calls to the external stty command are now wrapped in a catch to prevent failures.&nbsp; This doesn't mean that stty won't fail, it just means that InstallJammer won't fail as a result of it.&nbsp; This could mean that some console actions do not work as expected on some systems, but the errors seem to be very limited to a small number of machines.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the AND/OR operator for conditions was not propagated to temporary objects created during execution.</span></li>
<li class=rvps1><span class=rvts2>Fix a bug where selecting a single file in a multi-select file chooser would fail if the file selected had a space in the path.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a space in the command line of a UNIX shortcut would fail because the filename wasn't properly quoted.&nbsp; Double quotes are now added around a command with spaces before writing out the shortcut file.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where duplicate directories could show up in file groups.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug introduced in the last release.&nbsp; Files in Write Text to File that are relative are made relative to the install dir as the docs correctly say.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an empty pattern in some file actions would return the install directory.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where editing virtual text can sometimes cause a ::TMP error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where installing a wrapped script fails to substitute virtual text in Windows version information.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where Write Text to File paths were relative to the current directory instead of the installdir.</span></li>
<li class=rvps1><span class=rvts2>The Value property was accidentally removed for several widget types in the Add Widget action properties frame.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/129.html.








































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2.9</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2.9">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2.9</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="1210b1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="128.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.9 (August 11th, 2008)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This is a minor bug fix release.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug introduced in 1.2.8 where an install registry would not get cleaned up properly.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where cleaning up a canceled install could cause errors and freeze the installer under certain conditions.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an uninstaller would sometimes report that a directory could not be removed because it was not empty when it actually was.&nbsp; This fix now means that directories are not necessarily removed in the same order they were installed.</span></li>
<li class=rvps1><span class=rvts2>Fix a possible error case when attempting to set file permissions on a file that doesn't exist.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where stopping an install might still try to execute some further code after things had stopped.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an error in an action would not get propagated up to show an error message.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a message box in an uninstaller could fail and hang without an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where an uninstall that did not have permissions would attempt to do a lot of things that just weren't possible.&nbsp; The uninstall should fail gracefully now and give the user proper error messages.</span></li>
<li class=rvps1><span class=rvts2>Fix a bug where the Display Name property was being ignored in the Create Windows Service action.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/12b1.html.




















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2b1</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2b1">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2b1</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="12b2.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="112.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2b1 (May 28th, 2007)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains many new enhancements and bug fixes.&nbsp; The installkits have been recompiled with new features, which is the biggest reason for a minor revision bump instead of just a patch level.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Major Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Installkit binaries have been recompiled with new features.&nbsp; FreeBSD remains to be compiled but will be completed before the final 1.2 release.</span></li>
<li class=rvps1><span class=rvts2>Added the ability to copy-and-paste panes, actions and conditions through right-click and the Edit menu. [</span><span class=rvts3>Req #1664096</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added new Install Password property to encrypt installers with a password. [</span><span class=rvts3>Req #1557456</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added support for mounting and handling zip files from within an installer.</span></li>
<li class=rvps1><span class=rvts2>Added a new section to specify which languages are supported by an installer instead of just being all or none. [</span><span class=rvts3>Req #1661645</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Unzip File action</span><span class=rvts2> to unzip standard .zip files during installation.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Major Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug where the uninstaller would not remember the settings from its installer. [</span><span class=rvts3>Bug #1676588</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where loading a project with a lot of files could take minutes to load. [</span><span class=rvts3>Req #1665160</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where newly-created installs would inherit the Application ID of the last install opened. [</span><span class=rvts3>Bug #1689940</span><span class=rvts2>]</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Quick builds should be a lot faster now, especially on large projects with a lot of files.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new FetchURL API</span><span class=rvts2> call to fetch a web URL.</span></li>
<li class=rvps1><span class=rvts2>Added debug output on API calls to show when they are called and with what arguments.</span></li>
<li class=rvps1><span class=rvts2>Added debug output on several actions that didn't have any.</span></li>
<li class=rvps1><span class=rvts2>Added an option to preserve file permissions for files on non-Windows platforms.</span></li>
<li class=rvps1><span class=rvts2>Reordered the check buttons on UNIX file permissions tabs to reflect the standard order.</span></li>
<li class=rvps1><span class=rvts2>Only languages included are stored within an installer which decreases size a little.</span></li>
<li class=rvps1><span class=rvts2>Automatically include the TWAPI extension Windows if any code uses it.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Require JDK property</span><span class=rvts2> to the Locate Java Runtime action to require a full JDK instead of just a JRE.&nbsp; This will set a new virtual text: &lt;%JavacExecutable%&gt; if the JDK is found. [</span><span class=rvts3>Req #1690206</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Foreground property</span><span class=rvts2> to the Add Widget action to specify the text color of most widgets.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new label frame widget type</span><span class=rvts2> to the Add Widget action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>text widget type</span><span class=rvts2> to the Add Widget action.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new readonly state</span><span class=rvts2> to the Modify Widget action that can be applied to entry and text widgets.</span></li>
<li class=rvps1><span class=rvts2>Changed the popup when testing a modified project.&nbsp; Now, instead of just asking whether you want to save and build, you have the option to quick build or do a full build.</span></li>
<li class=rvps1><span class=rvts2>Only show the aliases of actions when selecting from a list instead of showing object IDs that don't mean anything to the user. [</span><span class=rvts3>Req #1664071</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added new Watch Progressive Output property to the Execute External Program action to watch the output of a program for special cues to InstallJammer.&nbsp; This allows external programs to change the values of virtual text in InstallJammer when running for a long time so they can update messages and progress bars, etc...</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed a bug where clicking twice on a grouping in the user interface tree (like attempting to rename) would cause an error [</span><span class=rvts3>Bug #1665811</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where selecting multiple panes and then adding a new action would cause an error.&nbsp; Actions are now added to the last pane selected.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where substituting text for eval would break if the virtual text had multiple words.</span></li>
<li class=rvps1><span class=rvts2>Fixed a minor bug in the text edit window when cancelling an edit.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the PromptForFile API that would cause an error if the user hit cancel.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Populate Components action that would populate components that were marked inactive.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where adding multiple files to a file group would cause an error. [</span><span class=rvts3>Bug #1702000</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Some fixes were made to attempt better cleanup of stopped builds. [</span><span class=rvts3>Bug #1664102</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where UNIX file permissions were not set properly based on the mask. [</span><span class=rvts3>Bug #1661644</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Launch File action that would cause backslashes to be substituted.</span></li>
<li class=rvps1><span class=rvts2>Removed the requirement in the Install Windows Shortcut action that the target file must exist to create the shortcut.&nbsp; This will allow for creating shortcuts that point to launching programs. [</span><span class=rvts3>Req #1682449</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed the Windows Registry actions to propertly substitute virtual text. [</span><span class=rvts3>Bug #1685186</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a destroyed window can still be in the parent window list and cause an error. [</span><span class=rvts3>Bug #1672859</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>The Ask Yes or No condition now includes the Console Ask Yes or No action and will use that when installing in console mode. [</span><span class=rvts3>Bug #1713635</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where checking for the existence of a registry key without a value would always return false.</span></li>
<li class=rvps1><span class=rvts2>Cleanup failed previews better.&nbsp; Currently, if a preview fails, you can't preview that window again because of further errors. [</span><span class=rvts3>Bug #1546595</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a small, blank window would popup during silent installs and uninstalls on Windows.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Execute External Program action where the Status Virtual Text was not being accurately set with the exit code from the external program.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where deleting a condition while still editing a property could cause an error in the condition editor. [</span><span class=rvts3>Bug #1708594</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where message boxes could popup as non-transient windows.</span></li>
<li class=rvps1><span class=rvts2>Added missing icons to installers. [</span><span class=rvts3>Bug #1707437</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed several smaller bugs on Windows 98. [</span><span class=rvts3>Bug #1684175</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>The choose directory dialog no longer has hard-coded English strings.&nbsp; I still need to get translations for the other languages though. [</span><span class=rvts3>Bug #1512658</span><span class=rvts2>]</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/12b2.html.
















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>1.2b2</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="1.2b2">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>1.2b2</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="12.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="12b1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2b2 (July 23rd, 2007)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains bug fixes since the last beta as well as some minor enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>File installation performance should be greatly improved on larger installs. [</span><span class=rvts3>Req #1665160</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Fall Back to Console platform property</span><span class=rvts2> that tells InstallJammer to fall back to a console install if the GUI initialization fails.&nbsp; This is for non-Windows platforms only and is true by default.&nbsp; This option should be disabled if you do not plan to support a console mode. [</span><span class=rvts3>Req #1757285</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>When building an installer, InstallJammer will now look for Tcl packages in the project directory and include any found in the installer.&nbsp; Platform-specific packages should be placed in a subdirectory named after the platform.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new ::BuilderAPI::ModifyObject</span><span class=rvts2> command.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new ::BuilderAPI::SetPlatformProperty</span><span class=rvts2> command.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new &lt;%ScriptExt%&gt; virtual text</span><span class=rvts2> that is set to .bat on Windows and .sh on UNIX platforms.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new &lt;%InstallRegistryInfo%&gt; virtual text</span><span class=rvts2> that, if set to false, will prevent InstallJammer from installing registry information in a separate directory location.&nbsp; The registry information will instead be stored directly into the uninstaller.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new &lt;%InstallDirSuffix%&gt; virtual text</span><span class=rvts2> that, if it exists, will be appended to the &lt;%InstallDir%&gt; anytime it changes if it does not already equal the suffix.&nbsp; This allows an installer to always have its Application Name appended to the install directory if the user chooses a different location, for example.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new &lt;%InstallDrive%&gt; virtual text</span><span class=rvts2> on Windows that equals the drive letter of whatever drive is being installed to (C:, D:, etc...).</span></li>
<li class=rvps1><span class=rvts2>Several actions were updated to tell InstallJammer that a change had been made to the Windows registry.&nbsp; If the registry is changed during installation, a broadcast will be issued to running processes to update their environments on exit.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new ::InstallAPI::ErrorMessage</span><span class=rvts2> command to display error messages.</span></li>
<li class=rvps1><span class=rvts3>Updated ::InstallAPI::FindProcesses</span><span class=rvts2> to add support for Windows through the TWAPI extension.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new ::InstallAPI::SetObjectProperty</span><span class=rvts2> API to set properties on objects.</span></li>
<li class=rvps1><span class=rvts3>Added -action and -command arguments to ::InstallAPI::SetVirtualText</span><span class=rvts2> that allow for an action or Tcl command to be called anytime a virtual text variable is updated.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new ::InstallAPI::URLIsValid</span><span class=rvts2> API to validate a URL.</span></li>
<li class=rvps1><span class=rvts2>Changing the Alias of a pane, action or action group will automatically update its title in the builder. [</span><span class=rvts3>Req #1664071</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Action groups can now be reordered in the builder. [</span><span class=rvts3>Req #1729054</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Action groups can now check conditions before and after they execute.&nbsp; Any conditions that occur before the next action will cause the action group to execute over again.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Include Stderr property to the Execute External Program action</span><span class=rvts2> that will include output from the standard error channel in the collected output.</span></li>
<li class=rvps1><span class=rvts2>Show Progressive Output on an Execute External Program action now shows output in Console mode.</span></li>
<li class=rvps1><span class=rvts2>The Unzip File action can now show percentage complete and status update.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Set Object Property action</span><span class=rvts2> to set properties on any object.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Add to Uninstall property to the Add Directory to Path action</span><span class=rvts2> that will automatically remove added paths on uninstall.</span></li>
<li class=rvps1><span class=rvts2>Updated the Add Directory to Path actions to work on UNIX platforms.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Add Environment Variable action</span><span class=rvts2> that adds environment variables on all platforms.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Delete Environment Variable action</span><span class=rvts2> for Windows platforms.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Action property to the Add Widget action</span><span class=rvts2> that specifies an action to execute whenever a user clicks a button or modifies the value of a radiobutton or checkbutton.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new button Type to the Add Widget action</span><span class=rvts2>.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new Operators: "does not exist" and "exists" to the Object Test Condition</span><span class=rvts2> that will test for the existence of objects.</span></li>
<li class=rvps1><span class=rvts2>Added </span><span class=rvts3>new "was set from the command line" Operator to the Virtual Text Test Condition</span><span class=rvts2> that will allow checking for virtual text values that were set as a result of options passed on the command line.</span></li>
<li class=rvps1><span class=rvts2>Added a </span><span class=rvts3>new Command Line Test condition</span><span class=rvts2> for testing options passed on the command line.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>When installing on Vista, program folder icons will always be installed for All Users. [</span><span class=rvts3>Bug #1744543</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>If the Cancel button is disabled on the current pane, the X will now be disabled as well.</span></li>
<li class=rvps1><span class=rvts2>When the uninstall fails to remove all of the files for any reason, the uninstaller will remain on the system to remove the rest of the files later.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where a Message Box with Abort/Retry/Ignore buttons would also get a No button by mistake. [</span><span class=rvts3>Bug #1735003</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where calling an installer with .. in the path would cause it to error with usage information. [</span><span class=rvts3>Bug #1729508</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where wrapped text on a console with just the right length would go over by one character.</span></li>
<li class=rvps1><span class=rvts2>The Target Filename property on files will now be substituted for virtual text during installation. [</span><span class=rvts3>Bug #1741526</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where conditions failing in console or silent mode would cause an error. [</span><span class=rvts3>Bug #1738957, Bug #1733622</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where pasting text would paste twice. [</span><span class=rvts3>Bug #1737485, Bug #1727391</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where cancelling an exit without saving could cause the builder to get into an unknown state where the window title would not update.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where aliases on files were not being saved with an installer, so files could not be referenced by alias.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the calculation of the required install size. [</span><span class=rvts3>Bug #1729654</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where some messages were wrongly being output during a Silent install.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where passing --prefix while root would not work. [</span><span class=rvts3>Bug #1731561</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where multiple calls to ::</span><span class=rvts3>InstallAPI::FetchURL</span><span class=rvts2> with proxy arguments would remember the proxy between calls.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that made previewing panes on UNIX platforms impossible. [</span><span class=rvts3>Bug #1729643</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the </span><span class=rvts3>Console Get User Input action</span><span class=rvts2> where the input would not be properly saved to the virtual text if the virtual text did not exist before the action was called.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the </span><span class=rvts3>Execute Action action</span><span class=rvts2> would not check conditions of an action group it was executing. [</span><span class=rvts3>Bug #1737786</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the </span><span class=rvts3>Execute External Program ac</span><span class=rvts2>tion would never set the status variable on completion thereby causing the installer to hang. [</span><span class=rvts3>Bug #1742712</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the </span><span class=rvts3>Unzip File action</span><span class=rvts2> where multiple calls to the action could result in files being compounded. [</span><span class=rvts3>Bug #1747116</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the </span><span class=rvts3>Text Window action</span><span class=rvts2> would error in non-GUI modes.&nbsp; The action is not valid for non-GUI modes.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the </span><span class=rvts3>Add Windows Registry Key action</span><span class=rvts2> where the keys were not being properly added to the uninstall. [</span><span class=rvts3>Bug #1734957</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the </span><span class=rvts3>Populate Components action</span><span class=rvts2> that was causing components population on the Choose Components screen to act very odd when the user moved back and forth through an install. [</span><span class=rvts3>Bug #1757505</span><span class=rvts2>]</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the </span><span class=rvts3>File Permission Condition</span><span class=rvts2> that would cause installations to a root drive on Windows to hang in an infinite loop.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where changing the order of Components in the builder would not reflect in the installer. [</span><span class=rvts3>Bug #1737930</span><span class=rvts2>]</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/ActionStandardProperties.html.
















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Standard Action Properties</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Action Standard Properties">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts5
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Standard Action Properties</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="WhatAreActionGroups.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ConsoleAskYesOrNo.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>ID</span></p>
<p class=rvps1><span class=rvts2>A unique identifier for this object.&nbsp; This ID is generated when the object is created and does not change throughout the life of the object.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Component</span></p>
<p class=rvps1><span class=rvts2>This property tells you what action was originally used to create this object.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Active</span></p>
<p class=rvps1><span class=rvts2>This tells InstallJammer whether this object is active or not.&nbsp; An inactive object is not packaged when building an installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Alias</span></p>
<p class=rvps1><span class=rvts2>An alias is an alias by which to call an object ID.&nbsp; Any object in InstallJammer that has an ID can also have an alias.&nbsp; This makes it easier to remember objects by their alias instead of their object ID.&nbsp; For example, the Install Actions group that is created for a new project is aliased to be called Install Actions to make it easier to call from other actions.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Comment</span></p>
<p class=rvps1><span class=rvts2>Comments are sometimes provided by InstallJammer to tell you what an object is doing, but they are usually set by someone building the project.&nbsp; Comments are not used by InstallJammer for anything and can contain any text you want.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Conditions</span></p>
<p class=rvps1><span class=rvts2>This tells you if there are any conditions placed on the object that will be checked during installation.&nbsp; Selecting this property will let you bring up the Conditions Editor to see and modify any conditions on the object.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Data</span></p>
<p class=rvps1><span class=rvts4>This property is used to hold user-specific data.&nbsp; Just like comments, this data is not used by InstallJammer and is safe for you to store anything you want into it.&nbsp; This can be helpful for storing other bits of relevant data with an object in the system for use by other objects, actions or conditions.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Execute Action&nbsp; </span></p>
<p class=rvps1><span class=rvts2>This tells InstallJammer when to execute the given action.&nbsp; The descriptions of when to execute mean just what they say.&nbsp; The default is After Pane is Displayed, which means to execute the action after the given pane has been displayed to the user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Ignore Errors</span></p>
<p class=rvps1><span class=rvts2>This tells InstallJammer to ignore any errors that might occur while executing this action.&nbsp; Errors usually occur because of bad data, but they can be as a result of bugs.&nbsp; If this option is set to Yes, InstallJammer will keep moving to the next action / pane when it encounters an error instead of stopping the install.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddDirectoryToPath.html.






















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Directory to Path</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Directory to Path">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Directory to Path</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallWindowsShortcut.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddEnvironmentVariable.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to add a directory to a path variable of the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add to Uninstall</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the added paths will automatically be removed from the system during uninstallation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Directory</span></p>
<p class=rvps1><span class=rvts2>A list of directories separated by a ; to be added to the path variable.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Level</span></p>
<p class=rvps1><span class=rvts2>This specifies whether the directory should be added to the path variable for every user on the system or just the current user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Location</span></p>
<p class=rvps1><span class=rvts2>This specifies whether the given directory should be prepended to the beginning of the path variable or appended to the end.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Normalize Paths</span></p>
<p class=rvps1><span class=rvts2>If this property is true, each path added to the variable will be normalized appropriately for the current platform before it is added.&nbsp; This makes sure that any path that is relative or has incorrect directory separators is made to be legal for the current platform.&nbsp; Default is Yes.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Separator</span></p>
<p class=rvps1><span class=rvts2>This property specifies what separator to use between the paths for the given variable.&nbsp; Defaults to &lt;%PathSeparator%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Variable</span></p>
<p class=rvps1><span class=rvts2>This property specifies the variable to add your path to.&nbsp; By default, this is PATH, but it could easily be something like CLASSPATH to add to the Java class path on the target system.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddEnvironmentVariable.html.










































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Environment Variable</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Environment Variable">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Environment Variable</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddDirectoryToPath.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="DeleteEnvironmentVariable.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to add a new environment variable to the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add to Uninstall</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the added paths will automatically be removed from the system during uninstallation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Level</span></p>
<p class=rvps1><span class=rvts2>This specifies whether the variable should be added for every user on the system or just the current user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Restore on Uninstall (Windows only)</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer to remember the value of the environment variable if it already exists and then restore it during uninstall.&nbsp; This is only valid for Windows because this is always the case on UNIX systems because of the way variables are added.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Value</span></p>
<p class=rvps1><span class=rvts2>The value to set the new environment variable to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Variable</span></p>
<p class=rvps1><span class=rvts2>This property specifies the name of the environment variable to add to the target system.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddInstallInfo.html.














































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Install Info</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Install Info">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Courier';
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Install Info</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="Wait.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddResponseFileInfo.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to add your own information to the InstallJammer registry for the installed application.&nbsp; This information can be retrieved later through a </span><a class=rvts4 href="CheckForPreviousInstall.html">Check for Previous Install</a><span class=rvts2> action or just by reading the install registry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Key</span></p>
<p class=rvps1><span class=rvts2>The name of the property to store to the registry.&nbsp; This should be a short key containing alpha numeric characters.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Value</span></p>
<p class=rvps1><span class=rvts2>The value to store in the registry under Key.&nbsp; This value will automatically be substituted for virtual text before it is stored to the registry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would record the install mode the user used during installation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Key:&nbsp;&nbsp; Mode</span></p>
<p class=rvps1><span class=rvts5>Value: &lt;%InstallMode%&gt;</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Then, when using Check for Previous Install, you would have a virtual text &lt;%PreviousInstallMode%&gt; that equals whatever mode the user installed with (Console, Silent, Standard, etc...).</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddInstallInfo1.html.










































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>AddInstallInfo</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="AddInstallInfo">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>AddInstallInfo</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="WhatIsTheInstallAPI.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddLanguage.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::AddInstallInfo</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Add information to be stored in the install log for this installation.&nbsp; InstallJammer automatically creates a log file for every installation that contains a default set of values for each installation.&nbsp; This API lets you add information to that log so that it can be fetched on subsequent installs.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty String</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-key &lt;key&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The key to store the value under.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-value &lt;value&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The value to store with the key.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>The following example adds the Spanish language.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::AddInstallInfo -key Foo -value bar</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2>This would add a key "Foo" with the value "bar" to the install log.&nbsp; When using a Check for Previous Install action on subsequent installations, you would get a new virtual text called &lt;%PreviousInstallFoo%&gt; that contains "bar".</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddLanguage.html.






































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>AddLanguage</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Language">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>AddLanguage</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddInstallInfo1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CommandLineAPI.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::AddLanguage</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Add a language and language code to the list of available languages in the current installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty String</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-language &lt;language name&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The name of the language as it will be displayed to the user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-languagecode &lt;language code&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The language code for the given language.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>The following example adds the Spanish language.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::AddLanguage -language Spanish -languagecode es</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddPaneToOrder.html.






















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Pane to Order</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Pane to Order">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Pane to Order</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="StopWindowsService.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddWidget.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will take the given pane and add it to the wizard's back order at the given index.&nbsp; This is useful for controlling how the wizad behaves in tricky installs.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Index</span></p>
<p class=rvps1><span class=rvts2>This property specifies where in the current back order of the wizard this pane should be added.&nbsp; This can be a number, the word end, or another pane ID.&nbsp; If the index is a number, it means that the given pane should be inserted just before that index in the order.&nbsp; If the index is the word end, it means to append the pane to the end of the order.&nbsp; If the index is another pane, it means that the given pane should be inserted just before that pane in the current order.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Pane</span></p>
<p class=rvps1><span class=rvts2>The ID or alias of a pane to be added to the back order of the wizard.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddResponseFileInfo.html.
























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Response File Info</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Response File Info">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Response File Info</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddInstallInfo.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddToUninstall.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to add virtual text variables to the list of variables to saved to a response file when writing.&nbsp; If the user has passed --save-response-file on the command line, signifying that they want to save the responses from the installer to a file on exit, only virtual text which has been designated to save will be saved.&nbsp; Use this action to add virtual text to the list of what to save.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>The default virtual text variables saved with every response are:</span>
<br><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>CreateDesktopShortcut</span></p>
<p class=rvps1><span class=rvts5>CreateQuickLaunchShortcut</span></p>
<p class=rvps1><span class=rvts5>InstallDir</span></p>
<p class=rvps1><span class=rvts5>InstallMode</span></p>
<p class=rvps1><span class=rvts5>InstallType</span></p>
<p class=rvps1><span class=rvts5>LaunchApplication</span></p>
<p class=rvps1><span class=rvts5>ProgramFolderName</span></p>
<p class=rvps1><span class=rvts5>SelectedComponents</span></p>
<p class=rvps1><span class=rvts5>ViewReadme</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text</span></p>
<p class=rvps1><span class=rvts2>This is a list of virtual text variables separated by ;.&nbsp; Each virtual text can also be specified with a type that will tell the installer how it should be saved to a file and read back in.&nbsp; The current types supported are described below</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=1 cellpadding=1 cellspacing=2 style="border-color: #000000; border-style: solid;">
<tr valign=top>
<td width=63 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>boolean</span></p>
</td>
<td width=699 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>the virtual text will be saved as "Yes" or "No" depending on its current value</span></p>
</td>
</tr>
<tr valign=top>
<td width=63 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>list</span></p>
</td>
<td width=699 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>the virtual text is considered a valid Tcl list and will be saved as a comma-separated list</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>When specifying your list of virtual text, you can specify the type by adding it after the virtual text name.</span></p>
<p class=rvps1><span class=rvts2></span>
<br><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>Virtual Text: Foo; Bar list; MyBool boolean</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This would add the three virtual text variables: Foo, Bar and MyBool to the list of variables to be stored in the response file.&nbsp; Foo would be stored as-is with no interpretation.&nbsp; Bar would be stored as a list, which means that &lt;%Bar%&gt; contains a valid Tcl list, and it will be stored as a comma-separated list in the response file.&nbsp; MyBool is a boolean, so the installer will take whatever value is in &lt;%MyBool%&gt; and determine if it is true or false and convert it's value in the response file to Yes or No.&nbsp; Any boolean value is perfectly valid within a response file, but Yes and No are used to make it easier on the user to read the file.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddToUninstall.html.






























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add to Uninstall</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add to Uninstall">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add to Uninstall</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddResponseFileInfo.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CheckForPreviousInstall.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will add a directory, file or registry entry to the install log so that InstallJammer will attempt to uninstall it during uninstallation.&nbsp; This allows you to add things to the uninstall that might be generated by your application but you don't want to bother the user with deleting themselves.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>If this action is used during uninstallation before the uninstall actually begins, the directory, file or registry key will be added to the list of files about to be uninstalled.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Component Name</span></p>
<p class=rvps1><span class=rvts2>The name of the component to uninstall.&nbsp; This is either the name of a file or directory, or the name of a Windows registry key to uninstall.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Component Type</span></p>
<p class=rvps1><span class=rvts2>This tells InstallJammer what type of component is being added to the uninstall.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Forcefully Remove Directory</span></p>
<p class=rvps1><span class=rvts2>If this value is true, InstallJammer will delete the directory regardless of whether it has anything in it or not.&nbsp; By default, InstallJammer will not delete a directory that is not empty.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Registry Value</span></p>
<p class=rvps1><span class=rvts2>If this value is non-empty, it tells InstallJammer to remove a value of the specified registry key instead of the registry key itself.&nbsp; If this value is left blank, InstallJammer will uninstall the entire registry entry.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddWidget.html.








































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Widget</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Widget">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts6
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts7, span.rvts7
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts7:hover { color: #0000ff; }
span.rvts8
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Widget</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddPaneToOrder.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AppendTextToWidget.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will add a new widget to an install pane.&nbsp; Widgets are any type of control that is drawn on a pane, which includes: buttons, checkbuttons, labels, radiobuttons and more.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts8>Setting the Text on any widget type other than a label will cause a label to be drawn in combination with the specified widget.&nbsp; This is the easiest way to add a label with a widget rather than having to add a separate label widget.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Action</span></p>
<p class=rvps1><span class=rvts2>This property specifies an action that should be executed if the user clicks a button or modifies the value of a checkbutton or radiobutton.&nbsp; The action also applies to entry, browse entry and password entry widgets when the Validate Entry On property is set.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Background</span></p>
<p class=rvps1><span class=rvts2>The background color of the new widget.&nbsp; The most common are system, which is the main system color for the background of windows, and white.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Browse Type</span></p>
<p class=rvps1><span class=rvts2>If the widget is a browse entry, this property specifies what you are browsing for.&nbsp; A directory will use a choose directory dialog.&nbsp; An open file will use a file dialog that is expecting a file that already exists.&nbsp; A save file will use a file dialog that will tell the user the file will be overwritten if it already exists.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Checked</span></p>
<p class=rvps1><span class=rvts2>When adding a radiobutton or checkbutton, this property tells InstallJammer that the button should be checked on by default when displayed.&nbsp; If this property is left blank, the status of the button will depend on the virtual text property attached to it.&nbsp; In the case of a checkbutton, if the virtual text property is true, the checkbutton will be checked.&nbsp; In the case of a radiobutton, the radiobutton whose value matches the current value of the virtual text will be checked.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Editable</span></p>
<p class=rvps1><span class=rvts2>If the widget type is a combobox, this property specifies whether the value in the entry of the combobox should be editable or not.&nbsp; If the value is not editable, the user may only choose from the given list of values.&nbsp; If the combobox is editable, the user can either choose from the given values or type in their own value.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Types</span></p>
<p class=rvps1><span class=rvts2>If the widget type is a browse entry for choosing files, this property tells the file chooser popup what file types to allow.&nbsp; The File Types property must contain a list of pairs containing a description of the file type and a list of extensions to include with the file type.&nbsp; Example:&nbsp; "Source Files" ".c .cpp .h .hpp" "Text Files" ".txt" "All Files "*"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Foreground</span></p>
<p class=rvps1><span class=rvts2>The foreground color of the new widget.&nbsp; The most common are system, which is the main system color for the foreground text of windows, and black.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Height</span></p>
<p class=rvps1><span class=rvts2>The height of the widget.&nbsp; Usually, this option should be left blank, and InstallJammer will make the widget as tall as it needs to be.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Label Side</span></p>
<p class=rvps1><span class=rvts2>On any widget that is not a label, setting the Text property will cause a label to be drawn with the corresponding widget.&nbsp; This property tells InstallJammer where you want the label to appear in relation to the widget.&nbsp; The choices are on top or to the left.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Label Width</span></p>
<p class=rvps1><span class=rvts2>This property specifies the width of the text label when it is present next to another widget.&nbsp; Using this property with your label on the left side, you can make all of your labels line up evenly by giving them all the same width.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Off Value</span></p>
<p class=rvps1><span class=rvts2>This is the value the virtual text will be set to when a checkbutton is off.&nbsp; This is only valid for checkbuttons.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>On Value</span></p>
<p class=rvps1><span class=rvts2>This is the value the virtual text will be set to when a checkbutton is on.&nbsp; This is only valid for checkbuttons.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Text</span></p>
<p class=rvps1><span class=rvts2>If the widget type is a label, the text property specifies what should be displayed in the label.&nbsp; If the widget is not a label, setting the text property to any string will cause a label to be drawn with the given widget.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Type</span></p>
<p class=rvps1><span class=rvts2>The type of widget to add.&nbsp; The list currently includes: browse entry, button, checkbutton, combobox, entry, label, label frame, password entry, radiobutton or text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Validate Entry On</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer when to validate the contents of an entry widget when the type of widget added is an entry, and the action property is not empty.&nbsp; The following values are acceptable as either a single value or as a list of values separated by ;.&nbsp; Create, Focus, FocusIn, FocusOut and Key.&nbsp; Create means that the value will be validated when the widget is created.&nbsp; Focus, FocusIn and FocusOut mean the entry is validated when the focus of the entry changes.&nbsp; Key means the entry will be validated anytime a key is pressed inside the entry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Value</span></p>
<p class=rvps1><span class=rvts2>For a radiobutton, this is the value stored in the virtual text when this radiobutton is selected.&nbsp; Please read the section titled </span><span class=rvts6>Boolean Values in Virtual Text</span><span class=rvts5> in </span><a class=rvts7 href="WhatIsVirtualText.html">What is Virtual Text?</a><span class=rvts5> for information on using boolean-type values as a value for a radiobutton.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts8>Setting the value on an entry or browse entry will set the default value of the virtual text to the given value, which will make the value appear in the entry box.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Values</span></p>
<p class=rvps1><span class=rvts2>If the widget type is a combobox, this property specifies a list of values to display in the dropdown menu of the combobox.&nbsp; This must be a valid list with each item quoted.&nbsp; Example:&nbsp; "Item a" "Item b" "Item c" "Item d"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text</span></p>
<p class=rvps1><span class=rvts2>The virtual text variable to store the result in.&nbsp; Radiobuttons are grouped together by all sharing the same virtual text variable.&nbsp; The selected radiobutton will set the value of the virtual text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Width</span></p>
<p class=rvps1><span class=rvts2>The width of the widget.&nbsp; If this option is left blank, InstallJammer will make the widget as wide as it needs to be.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>X</span></p>
<p class=rvps1><span class=rvts2>The x coordinate on the pane to place this widget.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Y</span></p>
<p class=rvps1><span class=rvts2>The y coordinate on the pane to place this widget.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddWindowsFileCommand.html.




























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Windows File Command</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Windows File Command">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Windows File Command</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="RevertWow64Redirection.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddWindowsFileExtension.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will add a new command to a file type on the target Windows system.&nbsp; This means that a new command will appear in the right-click menu for this file type.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Command</span></p>
<p class=rvps1><span class=rvts2>This is the actual command to execute when someone clicks on the menu entry for this command.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Command Name</span></p>
<p class=rvps1><span class=rvts2>This is the name of the command to be added.&nbsp; Usually something like Open, Edit or Print.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Type</span></p>
<p class=rvps1><span class=rvts2>This is the file type to add this command to on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Menu Name</span></p>
<p class=rvps1><span class=rvts2>If specified, this sets the title to display on the menu for this command.&nbsp; If this property is empty, the Command Name will be used as the menu title.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddWindowsFileExtension.html.
















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Windows File Extension</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Windows File Extension">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Windows File Extension</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddWindowsFileCommand.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddWindowsFileType.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action adds a new file extension to the Windows registry and attaches it to a given file type.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Extension</span></p>
<p class=rvps1><span class=rvts2>This is the file extension to add.&nbsp; It should include the ., so it would be something like .tcl or .mpi.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Type</span></p>
<p class=rvps1><span class=rvts2>This is the file type to add this command to on the target system.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddWindowsFileType.html.


































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Windows File Type</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Windows File Type">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Windows File Type</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddWindowsFileExtension.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddWindowsRegistryKey.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action adds a new File Type to the Windows registry of the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Type</span></p>
<p class=rvps1><span class=rvts2>The name of the file type to be added.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon Path</span></p>
<p class=rvps1><span class=rvts2>This property specifies the file to use for the icon for all files of this file type.&nbsp; This can be a .ico, .exe or any other file containing icon information.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon Path Index</span></p>
<p class=rvps1><span class=rvts2>The index into the file that Windows uses when looking for an icon.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Show File Extensions</span></p>
<p class=rvps1><span class=rvts2>Tells Windows whether to display the file extensions for all files of this file type.&nbsp; If not specified, files of this type will behave according to the system or folder defaults.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Title</span></p>
<p class=rvps1><span class=rvts2>The title of this file type.&nbsp; This title is displayed in the Type column of Windows Explorer for all files matching this file type.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddWindowsRegistryKey.html.
















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Windows Registry Key</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Windows Registry Key">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Windows Registry Key</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddWindowsFileType.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddWindowsUninstallEntry.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action adds a new registry key and/or value to the Windows registry on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>By default, this action will add the new registry key to the uninstall, and it will be removed along with the files and directories when the application is uninstalled.&nbsp; This can be prevented by setting Add to Uninstall to No.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add to Uninstall</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer whether or not to add this registry key to the list of things to be uninstalled.&nbsp; If it is set to No, the key will not be uninstalled with the rest of the application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Data Type</span></p>
<p class=rvps1><span class=rvts2>This property specifies the type of data that will be stored in the registry key.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Key</span></p>
<p class=rvps1><span class=rvts2>The name of the key to create in the registry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Name</span></p>
<p class=rvps1><span class=rvts2>The name of a value to add to this registry key.&nbsp; If this property is empty, the value will be set as the default value for this registry key.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Value</span></p>
<p class=rvps1><span class=rvts2>The actual value of the data stored in the value being added to this registry key.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Restore on Uninstall</span></p>
<p class=rvps1><span class=rvts2>If this property is true, InstallJammer will check if the registry key already exists on the system before installing.&nbsp; If the registry key / value already exists, the value will be remembered and then restored during uninstallation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Root Key</span></p>
<p class=rvps1><span class=rvts2>The root key in the registry to add this key to.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AddWindowsUninstallEntry.html.














































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Add Windows Uninstall Entry</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Add Windows Uninstall Entry">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Add Windows Uninstall Entry</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddWindowsRegistryKey.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ImportWindowsRegistryFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will add a new entry to the Windows Add or Remove Programs registry.&nbsp; This can be accessed from the Control Panel and is the usual way for Windows users to remove installed applications from their system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>InstallJammer adds one of these actions to a new install by default so that Windows users will have a way to remove your application in a way that is already familiar to them.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Comments</span></p>
<p class=rvps1><span class=rvts2>This property stores comments for this entry in the Windows registry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Contact</span></p>
<p class=rvps1><span class=rvts2>This property specifies contact information displayed to the user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Display Name</span></p>
<p class=rvps1><span class=rvts2>This property tells Windows what to display in the Add or Remove Programs window for this applicaiton.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Display Icon</span></p>
<p class=rvps1><span class=rvts2>This property specifies the file to use for the icon for this entry.&nbsp; This can be a .ico, .exe or any other file containing icon information.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Display Version</span></p>
<p class=rvps1><span class=rvts2>This property tells Windows what version to display for this program.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Help Link</span></p>
<p class=rvps1><span class=rvts2>A URL to the homepage of your application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Help Telephone</span></p>
<p class=rvps1><span class=rvts2>Your contact telephone number for support.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Install Date</span></p>
<p class=rvps1><span class=rvts2>The date of installation in the format of %Y%m%d.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Install Location</span></p>
<p class=rvps1><span class=rvts2>The installation directory.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Install Source</span></p>
<p class=rvps1><span class=rvts2>The directory the installer was originally run from.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Publisher</span></p>
<p class=rvps1><span class=rvts2>The name of the company or person publishing this application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Quiet Uninstall String</span></p>
<p class=rvps1><span class=rvts2>The command to execute to quietly uninstall your application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Readme</span></p>
<p class=rvps1><span class=rvts2>The location of the README file for your application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Registry Key Name</span></p>
<p class=rvps1><span class=rvts2>The key to use in the uninstall registry.&nbsp; By using &lt;%ApplicationID%&gt;, it ensures that subsequent installs of your application will always use the same uninstall registry entry instead of adding a new one for every version of your software.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Uninstall String</span></p>
<p class=rvps1><span class=rvts2>The command to execute to uninstall your application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>URL Info About</span></p>
<p class=rvps1><span class=rvts2>A URL that points to information about your application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>URL Update Info</span></p>
<p class=rvps1><span class=rvts2>A URL that points to information about updating your application.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AdjustLineFeeds.html.






























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Adjust Line Feeds</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Adjust Line Feeds">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Courier';
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Adjust Line Feeds</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ExecuteScript.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="BackupFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to adjust the line feeds of the given files.&nbsp; This can convert text files to either UNIX (lf) or Windows (crlf) line feeds as specified.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Files</span></p>
<p class=rvps1><span class=rvts2>A list of files or patterns separated by a ;.&nbsp; Any pattern or file that is a relative path is automatically made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Line Feed</span></p>
<p class=rvps1><span class=rvts2>The type of linefeeds for the specified files.&nbsp; The following choices are available:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Auto - choose the linefeeds based on the target install platform.</span></li>
<li class=rvps1><span class=rvts2>Unix - Use UNIX linefeeds (lf)</span></li>
<li class=rvps1><span class=rvts2>Windows - Use Windows linefeeds (crlf)</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would convert all .txt and .sh files in &lt;%InstallDir%&gt; to UNIX linefeeds.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Files:&nbsp;&nbsp;&nbsp;&nbsp; *.txt;*.sh</span></p>
<p class=rvps1><span class=rvts5>Line Feed: Unix</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AppendTextToWidget.html.




























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Append Text to Widget</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Append Text to Widget">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Append Text to Widget</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddWidget.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CreateInstallPanes.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will append text to a text widget in the current pane displayed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Auto Scroll</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the text widget will automatically scroll to the bottom after the text is appended.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Clear Widget</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the text widget will be cleared of any text before adding the new text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Widget</span></p>
<p class=rvps1><span class=rvts2>The name of the text widget to append to.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ApplicationInformation.html.


















































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Application Information</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Application Information">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 font-weight: bold;
}
span.rvts5
{
 font-family: 'Verdana';
}
span.rvts6
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts7
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #ff0000;
}
a.rvts8, span.rvts8
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts8:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Application Information</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="Command-LineOptions.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PlatformInformation.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>Application Information</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Application ID</span></p>
<p class=rvps1><span class=rvts5>A unique identifier for this application.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>The Application ID is defined when the project is first created and is used to identify the application on subsequent installs to the same machine and during uninstallation.&nbsp; The Application ID can be accessed with the &lt;%ApplicationID%&gt; vitrual text.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Application Name</span></p>
<p class=rvps1><span class=rvts5>The name of the application you are installing.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>This name will be used throughout the install when the application name is used. It can be accessed by using the virtual text &lt;%AppName%&gt;.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Application URL</span></p>
<p class=rvps1><span class=rvts5>This is the main web address for information about your application.&nbsp; This is used for information to tell users where they can find your application on the web.&nbsp; The application URL can be accessed by using the &lt;%ApplicationURL%&gt; virtual text.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Company</span></p>
<p class=rvps1><span class=rvts5>Your company name.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>This field can be used throughout the install as an easy way to retrieve the name of the company producing the application. By default, InstallJammer uses the company in its default install location. The company name can be accessed by using the virtual text &lt;%Company%&gt;.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Copyright</span></p>
<p class=rvps1><span class=rvts5>This property specifies your copyright notice, if any.&nbsp; This will be included in the Copyright field in the resources of a Windows executable.&nbsp; The copyright can be accessed by using the &lt;%Copyright%&gt; virtual text.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Install Icon</span></p>
<p class=rvps1><span class=rvts5>The icon used throughout the install.&nbsp; If the icon path given is a relative path, InstallJammer will first attempt to locate the image file in the project's own directory and then in InstallJammer's root directory.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>By default, all panes within the install that contain an icon use this icon, but most install themes will allow you to change the icon for each pane. If the pane is not modified, this icon will be used when applicable. The install icon can be accessed by using the virtual text &lt;%Icon%&gt;.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Install Image</span></p>
<p class=rvps1><span class=rvts5>The main image used throughout the install.&nbsp; If the image path given is a relative path, InstallJammer will first attempt to locate the image file in the project's own directory and then in InstallJammer's root directory.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>By default, all panes within the install that contain an image use this image, but most install themes will allow you to change the image for each pane. If the pane is not modified, this image will be used when applicable. The install image can be accessed by using the virtual text &lt;%Image%&gt;.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Install Version</span></p>
<p class=rvps1><span class=rvts5>A numeric version used by InstallJammer for your application.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>Install versions are used during installation to determine what version files within the install are. This is useful for when you want to overwrite certain files that may already exist but only if the install has a higher version. The version can be accessed by using the virtual text &lt;%InstallVersion%&gt;.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Short Application Name</span></p>
<p class=rvps1><span class=rvts5>A shortened name for your application.&nbsp; This is usually all lowercase and contains no spaces and is used on UNIX systems in the installation directory.&nbsp; Even though most all modern UNIX systems support spaces in file and directory names, it's usually considered bad form.&nbsp; The short application name can be accessed by using the virtual text &lt;%ShortAppName%&gt;.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Upgrade Application ID</span></p>
<p class=rvps1><span class=rvts5>If this property is not null, it specifies the Application ID of another install project that this project is meant to upgrade.&nbsp; An upgrade installer is one that skips some of the procedures of a regular installer and adds its information to the uninstall of the previously-installed application.&nbsp; This upgrade application ID can be accessed by using the &lt;%UpgradeApplicationID%&gt; virtual text.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Version String</span></p>
<p class=rvps1><span class=rvts5>The version of the application.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>The version string is for you to identify the release version of your application.&nbsp; InstallJammer does not use this version for anything, so it can be anything you like.&nbsp; The version string can be accessed by using the virtual text &lt;%Version%&gt;.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Install Features</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Allow Language Selection</span></p>
<p class=rvps1><span class=rvts5>If this property is true, the user will be allowed to select the language to use for messages during installation.&nbsp; If it is false, the Default Language is always used.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Cancelled Install Action</span></p>
<p class=rvps1><span class=rvts5>What InstallJammer should do if an install is cancelled.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>If the user cancels an install after the main installation of files has already begun, some of the application is already copied onto the system. This option lets the installer rollback any modifications that have been made by the installer since it started running. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Default Language</span></p>
<p class=rvps1><span class=rvts5>This property specifies the default language to use when installing.&nbsp; InstallJammer will attempt to determine the best language based on the user's system settings, but if no settings can be found, this language will be the default in the language selection.&nbsp; If no language selection is allowed, this default language will always be used.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Default to System Language</span></p>
<p class=rvps1><span class=rvts5>If this property is true, the installer will use the default language on the target system if that language has been compiled into the installer.&nbsp; If the system language is not part of the installer or if this property is false, the Default Language will be used.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Enable Response File</span></p>
<p class=rvps1><span class=rvts5>If this property is true it will enable the --response-file and --save-response-file command-line options in your installer.&nbsp; This allows a user to pass --save-response-file when running an installer and save their responses to an output file that can then be read back in during later installs using the --response-file option.&nbsp; This is very handy for users who need to run an installer on multiple machines or for multiple people where it should all be run the same way.&nbsp; Read more about what virtual text is included in a response file in the </span><a class=rvts8 href="AddResponseFileInfo.html">Add Response File Info</a><span class=rvts5> action.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Extract Solid Archives on Startup</span></p>
<p class=rvps1><span class=rvts5>If this property is true, and the installer includes any solid archives, they will be extracted as soon as the installer starts up.&nbsp; The user will be shown a progress bar as the archives are extracted.&nbsp; This option is only useful if you need your files extracted before you begin the actual installation process.&nbsp; By default, InstallJammer will extract the solid archives just before it begins the actual file installation.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Wizard Height</span></p>
<p class=rvps1><span class=rvts5>Specifies the height of the installer and uninstaller wizard window.&nbsp; Defaults to whatever is the default for the chosen installer theme.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Wizard Width</span></p>
<p class=rvps1><span class=rvts5>Specifies the width of the installer and uninstaller wizard window.&nbsp; Defaults to whatever is the default for the chosen installer theme.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Project Preferences</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Command Line Failure Action</span></p>
<p class=rvps1><span class=rvts5>What InstallJammer should do if a file is missing from an install when building from the command-line.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>When InstallJammer is building from the command-line (by passing a -b option), the user doesn't have the ability to recognize problems and correct them. This option specifically deals with the case that a file that should be part of the install is missing, and InstallJammer needs to know what to do.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Compression Level</span></p>
<p class=rvps1><span class=rvts5>Define the compression level to use when packing files.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>This tells InstallJammer what level of compression to use when packing files in an installer.&nbsp; 1 means lower compression levels but a faster rate of packing and unpacking.&nbsp; 9 means higher compression but sometimes slower unpacking.&nbsp; The default level is 6.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Compression Method</span></p>
<p class=rvps1><span class=rvts5>This specifies the default compression method to use when packing files into the installer.&nbsp; The choices are:</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts5>lzma</span></li>
<li class=rvps1><span class=rvts5>lzma (solid)</span></li>
<li class=rvps1><span class=rvts5>none</span></li>
<li class=rvps1><span class=rvts5>zlib</span></li>
<li class=rvps1><span class=rvts5>zlib (solid)</span></li>
</ul>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>A solid archive is when all of the files to be packaged are actually packed into a single file before they are compressed into the installer.&nbsp; This has the advantage of a much higher rate of compression since the entire file is compressed at once instead of a bunch of little files compressed separately.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>Solid archives cannot be read directly from within the installer though, so they must first be extracted to a temporary location before they can be installed.&nbsp; This will require the target system to have a temporary location that is big enough to hold your entire, uncompressed archive before installation begins.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts6>ZLIB is the default compression method because it is fast, efficient, and it doesn't require a separate extraction step.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts6>LZMA can be a much better compression method in some cases, but it is </span><span class=rvts7>highly recommended</span><span class=rvts6> that you not use lzma compression unless it is a solid archive.&nbsp; LZMA compression is very slow and doesn't gain much on most files over ZLIB, but it can be a big win when using solid archives.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts6>If you have a larger file that would benefit from LZMA compression, you can always compress just that one file by specifying the Compression Method in the file group tree.&nbsp; InstallJammer can easily compress every single file in an installer with a different compression method if you want.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts4>Default Directory Location</span></p>
<p class=rvps1><span class=rvts5>If this property is set, it specifies the default Location to use for all files and directories that are direct descendants of a file group if their own Location property is not set.&nbsp; This allows a project to specify that every file or directory in a project should be located in a particular place on the system or relative to the project file, for example.&nbsp; If a file or directory specifies its own Location, it overrides this default value.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Include Install Debugging Options</span></p>
<p class=rvps1><span class=rvts5>Include command-line debugging options in the install.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>During testing, InstallJammer includes a small set of debugging options that can be passed to installs on the command-line. These options allow the install builder to debug their install while it is running.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts6>Debugging options should be turned off before distributing a release of your installer.&nbsp; This can be done by disabling this option or by building your installs for final release.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Preserve UNIX File Permissions</span></p>
<p class=rvps1><span class=rvts5>If this property is true, InstallJammer will record the current file permissions on each file and directory stored in the installer and restore them when they are installed.&nbsp; Any permissions which have been set for a file or directory in the project will override these permissions, but by default, the permissions recorded on the build system will be restored on the target install system.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Preserve Windows File Attributes</span></p>
<p class=rvps1><span class=rvts5>If this property is true, InstallJammer will remember the file attributes on each file and directory stored in the installer and restore them when they are installed.&nbsp; Any attributes which have been set for a file or directory in the project will override these attributes, but by default, the attributes recorded on the build system will be restored on the target install system.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Refresh File List Before Building</span></p>
<p class=rvps1><span class=rvts5>If this property is true, InstallJammer will automatically search for new and deleted files in directories before building any installers.&nbsp; This will automatically pick up any changes made to the directories in your installer before the new installers are built.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Save Only Toplevel Directories</span></p>
<p class=rvps1><span class=rvts5>This option tells InstallJammer that you only want to save the files and directories that are a direct child of a file group.&nbsp; This means that directories in a file group will not be saved recursively.&nbsp; This option is useful for building projects dynamically using command-line tools where you don't want the GUI builder to save the files for you.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>File Groups and Directories in a project have a Save Files property which basically acts as a finer-grained version of this property.&nbsp; You can set that a particular File Group or directory should not save its files instead of the entire project.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts6>Saving only toplevel directories should be used with caution.&nbsp; Any change you make to any file or directory that is not a toplevel will be lost since it will not be saved in the install project.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts4>Skip Unused File Groups</span></p>
<p class=rvps1><span class=rvts5>If this property is true, it means that InstallJammer will skip any file groups it finds that are not being used by a component.&nbsp; This can be an easy way of disabling an entire file group without removing it from the project.&nbsp; If this property is false, all file groups will be included in the installer regardless of whether they are used.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/AskYesOrNo.html.




























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Ask Yes or No</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Ask Yes or No">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Ask Yes or No</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PortTestCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FileExtensionExistsCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition posts a message box that asks the user a question and expects a yes or no response.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Default Button</span></p>
<p class=rvps1><span class=rvts2>The button to highlight as the default when the message box posts.&nbsp; This will be the button clicked if the user hits Return.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon</span></p>
<p class=rvps1><span class=rvts2>The standard icon to use for the message box.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Result Virtual Text&nbsp; </span></p>
<p class=rvps1><span class=rvts2>The virtual text variable to hold the result of the message box.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>True Value</span></p>
<p class=rvps1><span class=rvts2>Specifies which value of the message box will return a true value for the condition.&nbsp; If the user clicks Yes, and Yes is the true value, this condition will pass, etc...</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/BackupFile.html.


























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Backup File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Backup File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Backup File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AdjustLineFeeds.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ChangeFileOwnership.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will take the specified files and back them up to a new file name.&nbsp; Given the new file extension, each file will be copied to a new file combined of its own file name plus the new extension.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Files</span></p>
<p class=rvps1><span class=rvts2>A list of files or patterns separated by a ;.&nbsp; Any pattern or file that is a relative path is automatically made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Extension</span></p>
<p class=rvps1><span class=rvts2>The new extension to append to each file being backed up.&nbsp; A %d in the string will be substituted for a number in the extension.&nbsp; The number will increment until an unused file name is found.&nbsp; </span><span class=rvts3>Default is .bak%d</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Overwrite Files</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the action will overwrite a file that already exists when backing up instead of continuing to look for a new file name that does not exist.&nbsp; </span><span class=rvts3>Default is No</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Rename Files</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the files specified will be renamed to the new file instead of just being copied.&nbsp; This is useful if you want to move the current file out of the way.&nbsp; </span><span class=rvts3>Default is No</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Starting Backup</span></p>
<p class=rvps1><span class=rvts2>The number to start at when backing up files.&nbsp; </span><span class=rvts3>Default is 1</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would backup all .conf files in the &lt;%InstallDir%&gt;/conf directory.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Files: conf/*.conf</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>foo.conf would become foo.conf.bak1</span></p>
<p class=rvps1><span class=rvts4>bar.conf would become bar.conf.bak1</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would backup foo.cfg in &lt;%InstallDir%&gt; to foo.cfg.orig, but if the file already exists, nothing will happen and InstallJammer will throw an error.&nbsp; We will just tell InstallJammer to ignore the error.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Ignore Errors:&nbsp; Yes</span></p>
<p class=rvps1><span class=rvts4>Files:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foo.cfg</span></p>
<p class=rvps1><span class=rvts4>File Extension: .orig</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>foo.cfg would become foo.cfg.orig</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ChangeFileOwnership.html.


























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Change File Ownership</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Change File Ownership">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Change File Ownership</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="BackupFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ChangeFilePermissions.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will change the ownership or group of a given list of files on the target system.&nbsp; The installing user must have permission to change the ownership to the given owner/group, or this action will fail.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All UNIX</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Files</span></p>
<p class=rvps1><span class=rvts2>A list of files or patterns separated by a ;.&nbsp; Any pattern or file that is a relative path is automatically made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Owner</span></p>
<p class=rvps1><span class=rvts2>The new owner.&nbsp; This can be either a username or UID on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Group</span></p>
<p class=rvps1><span class=rvts2>The new group.&nbsp; This can be either a group name or GID on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would change the ownership of every file in the &lt;%InstallDir%&gt; to owner root, group wheel.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Files: *</span></p>
<p class=rvps1><span class=rvts4>Group: wheel</span></p>
<p class=rvps1><span class=rvts4>Owner: root</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ChangeFilePermissions.html.


















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Change File Permissions</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Change File Permissions">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Change File Permissions</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ChangeFileOwnership.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CopyFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will change the UNIX file permissions of the files given.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All UNIX</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Files</span></p>
<p class=rvps1><span class=rvts2>A list of files or patterns separated by a ;.&nbsp; Any pattern or file that is a relative path is automatically made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Permissions</span></p>
<p class=rvps1><span class=rvts2>The UNIX permissions mask (in octal format).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would make all of the .txt files in &lt;%InstallDir%&gt; read-only.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Files:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *.txt</span></p>
<p class=rvps1><span class=rvts4>Permissions: 0444</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CheckForPreviousInstall.html.








































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Check for Previous Install</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Check for Previous Install">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Check for Previous Install</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddToUninstall.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GetPreviousInstallInfo.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action checks the target system for a previous install of your application and sets up virtual text variables as a result.&nbsp; When searching for a previous install, InstallJammer uses the Application ID of your project to find them.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following virtual text variables are set as a result of this action:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>Version 1.0 of InstallJammer only defined the &lt;%PreviousInstallExists%&gt; and &lt;%PreviousInstallDir%&gt; variables.&nbsp; You should use a </span><a class=rvts4 href="VirtualTextTestCondition.html">Virtual Text Exists Condition</a><span class=rvts5> if you are unsure of whether the previous install virtual text you want exists.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>If &lt;%PreviousInstallExists%&gt; is false, none of the rest of this virtual text is set.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallApplicationID%&gt;</span></p>
<p class=rvps1><span class=rvts2>The Application ID of the previously installed application.&nbsp; This should match your own Application ID unless the previous install was an upgrade install.&nbsp; In that case, the Upgrade Install ID should match your application ID.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallDate%&gt;</span></p>
<p class=rvps1><span class=rvts2>The install date of the last install in clock seconds.&nbsp; This can be formatted using the &lt;%Date%&gt; virtual text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallCount%&gt;</span></p>
<p class=rvps1><span class=rvts2>The number of previous installations found on the target system.&nbsp; Only the last install, by date, will be used for this information.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallDir%&gt;</span></p>
<p class=rvps1><span class=rvts2>The installation directory of the last install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallDirExists%&gt;</span></p>
<p class=rvps1><span class=rvts2>A convenience value that tells you whether or not the previous install dir still exists on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallExecutable%&gt;</span></p>
<p class=rvps1><span class=rvts2>The full path of the previous install executable when it was run.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallExists%&gt;</span></p>
<p class=rvps1><span class=rvts2>This value will be true if a previous install was found, or false if one was not found.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallID%&gt;</span></p>
<p class=rvps1><span class=rvts2>The Install ID of the last install.&nbsp; This is the ID that is generated everytime an installer is run, so this ID will change with each subsequent install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallIDs%&gt;</span></p>
<p class=rvps1><span class=rvts2>This virtual text contains a list of all previous install IDs that have been installed for this application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallRealUser%&gt;</span></p>
<p class=rvps1><span class=rvts2>The real username of the person who installed last.&nbsp; This is the real username even if the user was running as root.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallSource%&gt;</span></p>
<p class=rvps1><span class=rvts2>The directory where the previous installer was run from.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallUninstaller%&gt;</span></p>
<p class=rvps1><span class=rvts2>The full path to the uninstaller of the last install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallUpgradeID%&gt;</span></p>
<p class=rvps1><span class=rvts2>The Upgrade Application ID of the last install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallUser%&gt;</span></p>
<p class=rvps1><span class=rvts2>The username of the person who installed last.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallVersion%&gt;</span></p>
<p class=rvps1><span class=rvts2>The install version (1.0.1.0, etc...) of the last install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallVersionString%&gt;</span></p>
<p class=rvps1><span class=rvts2>The install version string (1.0a1, etc...) of the last install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>Other variables can also be set if a developer has added information to the install registry through the </span><a class=rvts4 href="AddInstallInfo.html">Add Install Info</a><span class=rvts5> action.&nbsp; Any variable added through that action will also appear in virtual text as a result of this action.&nbsp; For example:</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>If the Key Foo was added with the Value Bar, you would get the variable &lt;%PreviousInstallFoo%&gt; that would equal Bar.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/Command-LineOptions.html.














































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install Builder Command Line Options</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Command-Line Options">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install Builder Command Line Options</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallBuilderPreferences.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ApplicationInformation.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>InstallJammer can be started with several command-line options that make building installs easier for some jobs. In most cases, these are used to provide quick builds of a single project or build projects using scripts and other programs.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Usage</span><span class=rvts2>:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class=rvts3>installjammer ?option option ... --build? ?ProjectFile?</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>If you are building from the command-line, it is generally recommended that --build be the last option before the project file name</span><span class=rvts2>.&nbsp; It tells InstallJammer where the options and switches end and where the project file name begins.&nbsp; Every argument after the --build will be joined together to make the file name, so you can include spaces on the command-line, and InstallJammer will join them properly.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The same is true for other options.&nbsp; Anytime an argument is encountered that doesn't match one of the given switches or options, its value will be appended to the value of the previous option.&nbsp; This allows for spaces on the command-line, and InstallJammer will join them properly where it makes the most sense.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>installjammer -DAppName My Application --quick-build --build /path/to/my/project file.mpi</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The arguments of this command-line will be joined like this:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>-DAppName "My Application" --quick-build --build "/path/to/my/project file.mpi"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Command-line Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--build</span></p>
<p class=rvps1><span class=rvts2>This option specifies that the given project file should be loaded and built without loading the install builder GUI. This option is good for building installs from other programs or at regular times using scheduling.&nbsp; </span><span class=rvts3>This should generally be the last switch specified before the project file name.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--build-dir &lt;directory&gt;</span></p>
<p class=rvps1><span class=rvts2>Specifies a directory to use as the temporary directory when building.&nbsp; InstallJammer will attempt to create the directory if it does not already exist.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--build-for-release</span></p>
<p class=rvps1><span class=rvts2>If this option is specified, the project file being built will be built for final release.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--build-log-file</span></p>
<p class=rvps1><span class=rvts2>Specifies a filename to save the build log information to.&nbsp; The default is build.log in the project directory.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--control-script &lt;scriptFile&gt;</span></p>
<p class=rvps1><span class=rvts2>This option specifies a script to source in when InstallJammer is building from the command line.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-D&lt;option&gt; &lt;value&gt;</span></p>
<p class=rvps1><span class=rvts2>Set the value of option to value. Example:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>-DAppName "My Software"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Will override the default value stored in AppName with the value My Software. This is useful for over-setting options in different installs during command-line builds so that a single project file can be manipulated to be many different builds.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Any number of options can be specified in this manner. Each one will be processed in the order in which it was specified on the command line.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--help</span></p>
<p class=rvps1><span class=rvts2>Displays usage information for InstallJammer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--output-dir &lt;directory&gt;</span></p>
<p class=rvps1><span class=rvts2>Specifies the output directory to store the resulting installers in when they are built.&nbsp; InstallJammer will attempt to create the directory if it does not already exist.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--platform &lt;platform&gt;</span></p>
<p class=rvps1><span class=rvts2>This option can be specified with the -b option to tell InstallJammer to only build certain platforms. Each platform name specified with a -p will be built instead of building all of the platforms (the default option). More than one -p platform can be specified, and each platform will be appended to the build list. </span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--quick-build</span></p>
<p class=rvps1><span class=rvts2>If this option is specified, the given project file will be rebuilt without repackaging the files for the installer just as a quick build in the GUI.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--quiet</span></p>
<p class=rvps1><span class=rvts2>Turn off messages from InstallJammer while building.&nbsp; Errors will still be reported on stderr.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--test</span></p>
<p class=rvps1><span class=rvts2>This option can be specified with the --build option to tell InstallJammer to test the install once it has been built. The install builder GUI will still not be loaded, and the install will execute when the build is complete.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--verbose</span></p>
<p class=rvps1><span class=rvts2>This option tells InstallJammer to show verbose output when building.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>--version</span></p>
<p class=rvps1><span class=rvts2>Display version information for InstallJammer and exit.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CommandLineAPI.html.


























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>CommandLineAPI</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="CommandLineAPI">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>CommandLineAPI</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddLanguage.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ComponentAPI.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::CommandLineAPI</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This API is used to manipulate and query command line options in an installer or uninstaller.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>See options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-do</span></p>
<p class=rvps1><span class=rvts2>Specifies the action the API should take.&nbsp; Possible values are:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=78>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; check</span></p>
</td>
<td width=684>
<p class=rvps1><span class=rvts2>Check to see if the option given by -option was passed on the command line.</span></p>
<p class=rvps1><span class=rvts2>Returns 1 if the option was passed or 0 if it was not.</span></p>
</td>
</tr>
<tr valign=top>
<td width=78>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; exists</span></p>
</td>
<td width=684>
<p class=rvps1><span class=rvts2>Check to see if the option given by -option exists as a possible option.</span></p>
<p class=rvps1><span class=rvts2>Returns 1 if the option exists or 0 if it does not.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-option</span></p>
<p class=rvps1><span class=rvts2>The command line option to check.&nbsp; Any - or / is stripped from the left side of the option before it is checked.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CommandLineOptions.html.




































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Command Line Options</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Command Line Options">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts5
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts6
{
 font-family: 'Verdana';
 font-style: italic;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 0px 0px 0px 24px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Command Line Options</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PanesAndActions.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="VirtualText.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts5>The command line options panel allows you to specify the different command-line options that will be available in your (un)installer.&nbsp; InstallJammer sets up some default options for each new projects, but these can all be removed if you want.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts4>There are a few options that are defined internally during startup that cannot be overriden by your options.&nbsp; They are:</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>--help, which displays the usage information for the (un)installer</span></p>
<p class=rvps1><span class=rvts4>--temp, which allows the user to specify a temporary directory</span></p>
<p class=rvps1><span class=rvts4>--version, which shows version information for the (un)installer</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>If response files are enabled, the following options are also added to each installer:</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>--response-file, which specifies a response file to read in</span></p>
<p class=rvps1><span class=rvts4>--save-response-file, which specifies that responses should be saved to the given file</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>InstallJammer automatically defines the character that precedes an option depending on platform, and this cannot be changed.&nbsp; The characters are removed from the option before processing, so options should be specified without any preceding characters.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts4>A / is used as the option character on Windows, and -- is used on UNIX, but it really doesn't matter.&nbsp; InstallJammer will accept either one on either platform, but it will always display the correct one when showing usage information.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Command Line Option Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Option</span></p>
<p class=rvps1><span class=rvts2>The name of the option not including any preceding option characters.&nbsp; Options are case-insensitive when specified on the command-line by the user, but they will maintain case when displaying them in the usage information.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text</span></p>
<p class=rvps1><span class=rvts2>The name of the virtual text (without &lt;% and %&gt;) to store the result of the option into.&nbsp; What is stored in the virtual text result depends on what type of option is being used.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Type</span></p>
<p class=rvps1><span class=rvts2>Each option is of a specific type, and each type behaves differently.&nbsp; The types are:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps2><span class=rvts3>Boolean</span></p>
<p class=rvps2><span class=rvts5>A boolean option means that the user must specify Yes or No or some equivalent as the argument to the option.&nbsp; The virtual text will be set to 0 if the user specified No or 1 if they specified Yes.</span></p>
<p class=rvps2><span class=rvts3><br></span></p>
<p class=rvps2><span class=rvts3>Choice</span></p>
<p class=rvps2><span class=rvts5>A choice is an option that has a list of possible choices the user can choose from.&nbsp; The choices are all case-insensitive, but the virtual text will be set case-sensitive.&nbsp; For example, if you had the option </span><span class=rvts6>check</span><span class=rvts5> that accepted </span><span class=rvts6>Foo</span><span class=rvts5> or </span><span class=rvts6>Bar</span><span class=rvts5>, the user could pass /check foo on the command-line, but your virtual text would still be set to Foo eventhough the user passed an all lowercase version.</span></p>
<p class=rvps2><span class=rvts3><br></span></p>
<p class=rvps2><span class=rvts3>Prefix</span></p>
<p class=rvps2><span class=rvts5>A prefix option means that the given option is only a prefix that can be specified along with any option after the prefix and a given value.&nbsp; This can be used to provide a generic option for specifying many things in your installer.&nbsp; Any option provided to a prefix switch is set as virtual text with the given value.&nbsp; If the Virtual Text property is not null, it is prepended to the option given.</span></p>
<p class=rvps2><span class=rvts5><br></span></p>
<p class=rvps2><span class=rvts5>For example, if you had the prefix option D with Virtual Text CommandLine, the user could pass:</span></p>
<p class=rvps2><span class=rvts5><br></span></p>
<p class=rvps2><span class=rvts5>/DFoo bar</span></p>
<p class=rvps2><span class=rvts5><br></span></p>
<p class=rvps2><span class=rvts5>On the command-line, and you would have the virtual text &lt;%CommandLineFoo%&gt; set to bar.</span></p>
<p class=rvps2><span class=rvts3><br></span></p>
<p class=rvps2><span class=rvts3>String</span></p>
<p class=rvps2><span class=rvts5>A string option means that the user can specify anything they want and no checks are done for validity.&nbsp; You will have to check the value yourself using an action.&nbsp; The virtual text will be set to the value of the given string.</span></p>
<p class=rvps2><span class=rvts3><br></span></p>
<p class=rvps2><span class=rvts3>Switch</span></p>
<p class=rvps2><span class=rvts5>A switch means that the option is specified with no argument and simply turns on the option.&nbsp; The virtual text will be set to 1 if this option is passed on the command-line or not set at all if it is not passed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Debug</span></p>
<p class=rvps1><span class=rvts2>This tells InstallJammer whether the given command-line option is meant to be a debugging option or not.&nbsp; If the option is a debugging option, it will not be included in the options when building without debugging options or when building for final release.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Hide</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the given command-line option will not appear in the list of option when showing the usage of the (un)installer.&nbsp; The option will still be included in the build, but the user will not be able to see that it is there.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Value(s)</span></p>
<p class=rvps1><span class=rvts2>This property has different meanings depending on the type of option.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps2><span class=rvts3>Boolean</span></p>
<p class=rvps2><span class=rvts5>If the option is a boolean option, Values can specify a list of two values that translate to Yes and No.&nbsp; The user will still have to pass Yes or No on the command-line, but if Values is not null, InstallJammer will set the virtual text to the first value if the user specified Yes or the second value if they specified No.</span></p>
<p class=rvps2><span class=rvts2><br></span></p>
<p class=rvps2><span class=rvts3>Choice</span></p>
<p class=rvps2><span class=rvts5>If the option is a choice, Values must contain a list of possible values that are legal for the given option.&nbsp; The list can be anything you want, but the values themselves will be case-insensitive when the user passes them.</span></p>
<p class=rvps2><span class=rvts2><br></span></p>
<p class=rvps2><span class=rvts3>Prefix</span></p>
<p class=rvps2><span class=rvts5>If the option is a prefix, values contains a list of possible options the user can pass.&nbsp; If values is empty, the user can pass any option they want on the command-line with the prefix.</span></p>
<p class=rvps2><span class=rvts2><br></span></p>
<p class=rvps2><span class=rvts3>Switch</span></p>
<p class=rvps2><span class=rvts5>If the option is a switch, Values can contain a string that will be set in the virtual text if the user passes the option on the command line.&nbsp; If Values is null, the virtual text will be set to 1.</span></p>
<p class=rvps2><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Description</span></p>
<p class=rvps1><span class=rvts2>This is a short description telling the user what this option is meant to do.&nbsp; When the user passes an incorrect option or specifies --help on the command-line, usage information will be displayed that contains all of the non-hidden options and their descriptions.&nbsp; The usage information for each option will be different for each option depending on its type, but the description can briefly tell the user what the option is for.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CommandLineTestCondition.html.












































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Command Line Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Command Line Test Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 0px 0px 0px 24px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Command Line Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FilePermissionCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ExecuteScriptCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition can check values passed by the user on the command line</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<p class=rvps2><span class=rvts3>exists</span></p>
<p class=rvps2><span class=rvts2>True if the command line option exists.</span></p>
<p class=rvps2><span class=rvts2><br></span></p>
<p class=rvps2><span class=rvts3>does not exist</span></p>
<p class=rvps2><span class=rvts2>True if the command line option does not exist.</span></p>
<p class=rvps2><span class=rvts2><br></span></p>
<p class=rvps2><span class=rvts3>was passed on the command line</span></p>
<p class=rvps2><span class=rvts2>True if the option was passed on the command line.</span></p>
<p class=rvps2><span class=rvts2><br></span></p>
<p class=rvps2><span class=rvts3>was not passed on the command line</span></p>
<p class=rvps2><span class=rvts2>True if the option was not passed on the command line.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Option</span></p>
<p class=rvps1><span class=rvts2>The name of the option to test.&nbsp; Note that any leading - or / characters will be removed before checking.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ComponentAPI.html.






















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>ComponentAPI</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="ComponentAPI">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>ComponentAPI</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CommandLineAPI.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ConfigAPI.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::ComponentAPI</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This API is used to manipulate and query components within an installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>See options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-active</span></p>
<p class=rvps1><span class=rvts2>If this option is specified, the active state of each of the given components will be made active or inactive.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-components</span></p>
<p class=rvps1><span class=rvts2>A list of components to act on.&nbsp; The word "all" can be passed to signify that all components in the install should be acted on.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-updateinfo</span></p>
<p class=rvps1><span class=rvts2>If this option is true, it tells the installer to update all of the information relating to selected components.&nbsp; The default is 1.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following example would deactivate all components in the current installer</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::ComponentAPI -components all -active 0</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This example would activate a component called "Component 1"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::ComponentAPI -components [list "Component 1"] -active 1</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Notice that because -components expects a list of components, we use the [list] command to make a proper list before passing the arguments to the API.&nbsp; In this case, it is a list with a single element.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/Components.html.
















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Components</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Components">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts5
{
 font-family: 'Verdana';
 font-weight: bold;
}
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Components</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FilesAndDirectories.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SetupTypes.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>Components are used to group file groups in your install into user-friendly categories.&nbsp; Each component can contain any of the file groups in your project, and if the user is presented with the option, they can choose which components they wish to install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>By default, a single component called Default Component is created for your project, and it contains the Program Files file group.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Standard Properties</span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts6 href="StandardProperties.html">Standard Properties</a><span class=rvts3>.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Checked</span></p>
<p class=rvps1><span class=rvts3>If this property is true, this component will be displayed as checked when it is first added to a component tree.&nbsp; This will automatically set the active status of the component depending on the value when it is first added to a tree.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Component Group</span></p>
<p class=rvps1><span class=rvts3>If this property is specified, it tells InstallJammer to put this component into a specific group with other components.&nbsp; Each component that shares the exact same name of group will be grouped together as radio buttons instead of check buttons.&nbsp; You must make sure that each component you want in a radio group shares the same exact Component Group name.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Name</span></p>
<p class=rvps1><span class=rvts3>The name of this component.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Required Component</span></p>
<p class=rvps1><span class=rvts3>This option tells InstallJammer that this component is required for all installations and will therefore not be available for the user to uncheck during installation.&nbsp; The component will still appear in the list of available components, but it will be disabled for the user.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Selectable</span></p>
<p class=rvps1><span class=rvts3>If this property is set to No, the component is displayed in a component tree as a header with no check or radio button.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Show Component</span></p>
<p class=rvps1><span class=rvts3>If this property is false, the component will not be added to a component tree when it is drawn.&nbsp; This can be used to hide components that you don't want shown during installation.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Size</span></p>
<p class=rvps1><span class=rvts3>If the size property is specified, it tells InstallJammer to override what may actually be the size of the files stored in the component and use the given size instead.&nbsp; The size should be given as an integer only which will automatically be converted to a readable size during installation.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Text Properties</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Description</span></p>
<p class=rvps1><span class=rvts3>This is a brief description of the contents of this component.&nbsp; If the user is able to choose which components they wish to install (during a Custom installation) they will see this description for each component to tell them what is in it.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Display Name</span></p>
<p class=rvps1><span class=rvts3>The name of the component to display when populating the components on a pane.&nbsp; If this property is left blank for a given language, the installer will use the standard Name property instead.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Build Platforms</span></p>
<p class=rvps1><span class=rvts3>This is a list of all the platforms that are supported by InstallJammer and whether or not this component should be built for each platform. If a platform is marked No, this component will not be included when the installer for that platform is built.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>It is possible to build a component into multiple platforms and then not install the component based on parameters during installation, but this option specifically tells InstallJammer to not even include this component for the given platform.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Creating a new component</span></p>
<p class=rvps1><span class=rvts2>Click the Add New Component button on the toolbar to add a new component to your install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>A new component is created with default values that you can change after its creation.&nbsp; Since components can be nested, your new component will be a child of whatever component is currently selected when you create your new component.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Deleting a component</span></p>
<p class=rvps1><span class=rvts2>Select the component you wish to delete and click the Delete Component button on the toolbar or the delete key on your keyboard.</span></p>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ConditionStandardProperties.html.






























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Standard Condition Properties</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Condition Standard Properties">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts5
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts6
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts7
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Standard Condition Properties</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="WhatAreConditions.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FileExistsCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>ID</span></p>
<p class=rvps1><span class=rvts2>A unique identifier for this object.&nbsp; This ID is generated when the object is created and does not change throughout the life of the object.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Component</span></p>
<p class=rvps1><span class=rvts2>This property tells you what condition was originally used to create this object.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Active</span></p>
<p class=rvps1><span class=rvts2>This tells InstallJammer whether this object is active or not.&nbsp; An inactive object is not packaged when building an installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Alias</span></p>
<p class=rvps1><span class=rvts2>An alias is an alias by which to call an object ID.&nbsp; Any object in InstallJammer that has an ID can also have an alias.&nbsp; This makes it easier to remember objects by their alias instead of their object ID.&nbsp; For example, the Install Actions group that is created for a new project is aliased to be called Install Actions to make it easier to call from other actions.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Check Condition</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer when to check this condition.&nbsp; This property is only valid for panes and actions and does not appear for conditions applied to other object types.&nbsp; The possible choices are different depending on if you are currently modifying a pane or an action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts4>When the Check Condition property on an Action is set to </span><span class=rvts7>Before Next Action is Executed</span><span class=rvts4>, it will cause the current action to be executed again if the condition fails.&nbsp; This is mostly useful during Console installations where you want the action to execute again to display its message and prompt the user for input.&nbsp; The user cannot continue to the next action until the condition is satisfied.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Comment</span></p>
<p class=rvps1><span class=rvts2>Comments are sometimes provided by InstallJammer to tell you what an object is doing, but they are usually set by someone building the project.&nbsp; Comments are not used by InstallJammer for anything and can contain any text you want.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Data</span></p>
<p class=rvps1><span class=rvts5>This property is used to hold user-specific data.&nbsp; Just like comments, this data is not used by InstallJammer and is safe for you to store anything you want into it.&nbsp; This can be helpful for storing other bits of relevant data with an object in the system for use by other objects, actions or conditions.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts6>Failure Focus</span></p>
<p class=rvps1><span class=rvts5>A widget to move the focus to if the condition fails.&nbsp; If Failure Message is not empty, the message will be displayed, and then the focus will be moved to the Failure Focus widget.&nbsp; If no message is displayed, the focus will simply move to the Failure Focus widget.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Failure Message</span></p>
<p class=rvps1><span class=rvts2>A message to display to the user if this condition is checked and fails.&nbsp; If this property is left blank, no message will be displayed to the user.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ConfigAPI.html.




















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>ConfigAPI</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="ConfigAPI">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333399" face="Verdana"><b>ConfigAPI</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ComponentAPI.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CopyObject.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::ConfigAPI</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This API is used to manipulate and query internal configuration options in an installer or uninstaller.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>See options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-usenativedirectorydialog</span></p>
<p class=rvps1><span class=rvts2>If this option is turned on, the installer will use the native dialog when choosing a directory.&nbsp; This only applies to Windows and OS X where native dialogs exist.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-usenativefiledialog</span></p>
<p class=rvps1><span class=rvts2>If this option is turned on, the installer will use the native dialog when choosing a file from the system.&nbsp; This only applies to Windows and OS X where native dialogs exist.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-usenativemessagebox</span></p>
<p class=rvps1><span class=rvts2>If this option is turned on, the installer will use the native dialog when displaying messages to the user.&nbsp; This only applies to Windows and OS X where native dialogs exist.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ConsoleAskYesOrNo.html.






























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Console Ask Yes or No</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Console Ask Yes or No">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Console Ask Yes or No</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ActionStandardProperties.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ConsoleClearScreen.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used in a console install to ask the user a question that requires a Yes or No answer.&nbsp; The user is required to provide a valid answer before the installation continues.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>UNIX</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Default</span></p>
<p class=rvps1><span class=rvts2>This property specifies the default value if the user hits Enter when asked the question.&nbsp; A default value of None means that the user must enter an answer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Prompt</span></p>
<p class=rvps1><span class=rvts2>The prompt to display the user when asking the question.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text</span></p>
<p class=rvps1><span class=rvts2>The virtual text variable (without &lt;% and %&gt;) to store the user's answer in.&nbsp; As per the rules of boolean values in virtual text, the result will be 0 if the user chooses No or 1 if they choose yes.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ConsoleClearScreen.html.




































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Console Clear Screen</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Console Clear Screen">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Console Clear Screen</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ConsoleAskYesOrNo.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ConsoleGetUserInput.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used in a console install to clear the screen.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>UNIX</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ConsoleGetUserInput.html.










































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Console Get User Input</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Console Get User Input">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Console Get User Input</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ConsoleClearScreen.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ConsoleMessage.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used in a console install to get a string of input from the user.&nbsp; The string is not checked for validity in any way, so it is up to you to use an action to check the user's response.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>UNIX</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Echo Input</span></p>
<p class=rvps1><span class=rvts2>If this property is false, the input will not be echoed as the user types.&nbsp; This is useful for asking for passwords and other information that should not be seen on the screen.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Prompt</span></p>
<p class=rvps1><span class=rvts2>The prompt to display the user when asking the question.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Require Response</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the user cannot enter empty data for a response.&nbsp; The action will continue to prompt for the information until a response is entered.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Trim Result</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the user's result will be trimmed of all white spaces before it is set to the resulting virtual text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text</span></p>
<p class=rvps1><span class=rvts2>The virtual text variable (without &lt;% and %&gt;) to store the user's answer in.&nbsp; As per the rules of boolean values in virtual text, the result will be 0 if the user chooses No or 1 if they choose yes.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ConsoleMessage.html.




























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Console Message</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Console Message">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Console Message</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ConsoleGetUserInput.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ConsolePause.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used in a console install to display a message to the user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>UNIX</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Allow Quit</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the user will be allowed to quit reading the message if it is a long message and pagination is turned on.&nbsp; If the message all fits on the screen without paging, or if pagination is turned off, this property means nothing.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Paginate Message</span></p>
<p class=rvps1><span class=rvts2>If this property is true, a long message will be displayed to the user a page at a time to allow them to read it before continuing on to the next page.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Wrap Text</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the text of the message will be wrapped, by word, to the size of the user's screen when it is displayed.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ConsolePause.html.






































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Console Pause</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Console Pause">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Console Pause</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ConsoleMessage.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ExecuteAction.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used in a console install to pause before the next action is executed.&nbsp; The user is asked to press the space bar to continue.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>UNIX</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ContinueInstall.html.












































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Continue Install</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Continue Install">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Continue Install</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="UnzipFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="Exit.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action continues file installation if it was previously paused using the </span><a class=rvts5 href="PauseInstall.html">Pause Install</a><span class=rvts2> action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ContinueWindowsService.html.




































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Continue Windows Service</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Continue Windows Service">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 7px 0px 7px 0px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Continue Windows Service</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="UnregisterWindowsLibrary.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CreateWindowsService.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will continue a Windows service that is in a paused state.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Database</span></p>
<p class=rvps2><span class=rvts2>Specifies the service control database to be operated on. By default, this is the active service control database on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Service Name</span></p>
<p class=rvps1><span class=rvts2>The name of the service to perform the action on.&nbsp; This can be the internal or the display name of the service.&nbsp; If the display name is given, it will automatically be translated to the internal service name for the action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>System</span></p>
<p class=rvps2><span class=rvts2>Specifies the name of the system on which the command should be invoked. By default, this is the local system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Wait</span></p>
<p class=rvps1><span class=rvts2>If not null, this specifies a number of milliseconds to wait for the action to complete.&nbsp; InstallJammer will wait until the action completes or for the specified number of milliseconds, whichever comes first. </span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CopyFile.html.


















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Copy File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Copy File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Copy File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ChangeFilePermissions.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CreateFileLink.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will copy a single file or directory on the target system to another name.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Source</span></p>
<p class=rvps1><span class=rvts2>The path to the file or directory to be copied.&nbsp; If the path is relative, it will be made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Destination</span></p>
<p class=rvps1><span class=rvts2>The new path to copy the file or directory to.&nbsp; If the path is relative, it will be made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would copy the file foo.cfg to bar.cfg in the &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Source:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foo.cfg</span></p>
<p class=rvps1><span class=rvts4>Destination: bar.cfg</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CopyObject.html.
























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>CopyObject</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="CopyObject">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>CopyObject</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ConfigAPI.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ErrorMessage.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::CopyObject</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Make a copy of an existing object in the current environment.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Name of the new object</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-object &lt;object ID or alias&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The Object ID or Alias of the object to be copied.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-newobject &lt;object name&gt;</span></p>
<p class=rvps1><span class=rvts2>The name to give to the new object.&nbsp; If this option is not specified, the new object will be created with a unique ID.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CreateANewInstallFast.html.
































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Create a New Install Fast</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Create a New Install Fast">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
}
span.rvts6
{
 font-family: 'Verdana';
 font-weight: bold;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 text-indent: -24px;
 margin: 0px 0px 0px 24px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Create a New Install Fast</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="VirtualTextExists.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CreateANewInstallStep-by-Step.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts6>Overview</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>This tutorial will walk you through the quick and dirty way to get started using InstallJammer with a new install in no time flat. When you're finished with this tutorial, you will have a new install project for your application that is built for the platform you're running the install builder from.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>Follow the steps below, and you'll be off and running!</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts6>Creating Your First Install</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<ol style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li value=1 class=rvps1><span class=rvts5>Open the New Project Wizard.</span></li>
<li value=2 class=rvps1><span class=rvts5>Type in your Project Name.&nbsp; InstallJammer will fill in the Project Directory based on your Project Name and preferences.&nbsp; Click Next.</span></li>
<li value=3 class=rvps1><span class=rvts5>Fill in your Application Name, Short Application Name, Version and Company.&nbsp; Click Next.</span></li>
<li value=4 class=rvps1><span class=rvts5>Fill in your Install Version and Application Executable fields so that InstallJammer knows how to execute your application after installing.&nbsp; Click Next.</span></li>
<li value=5 class=rvps1><span class=rvts5>Type in the directory where your application is stored on your system.&nbsp; This should be the root directory of your application.&nbsp; Click Finish.</span></li>
<li value=6 class=rvps1><span class=rvts6>Done!</span></li>
</ol>
<p class=rvps2><span class=rvts5><br></span></p>
<p class=rvps2><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>You have just built your install project. Now that you have the project built, click the Build Install button on the toolbar or from the Build menu, and InstallJammer will build an installer for your application.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>If you entered your Application Directory properly, you should have your entire application now packaged up in a convenient installer for your current platform!</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>Click Test Install from the toolbar or from the Build menu and test your new installer!</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>If you had any trouble, or any questions, please read through </span><a class=rvts4 href="CreateANewInstallStep-by-Step.html">Create a New Install Step-by-Step</a><span class=rvts3>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CreateANewInstallStep-by-Step.html.


































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Create a New Install Step-by-Step</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Create a New Install Step-by-Step">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 0px 0px 0px 48px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Create a New Install Step-by-Step</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CreateANewInstallFast.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="WhatIsTclTk.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>Overview</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This tutorial will walk you, step-by-step, through creating your first installer using the InstallJammer Install Builder. The process is very easy and should take you no longer than a few minutes. You'll have your first installer up and running in no time!</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Creating Your First Install</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>When InstallJammer first loads, you are presented with the Start Page that shows you a list of current installers you have built. Your first time out, this page will have no projects. So, let's create one!</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>New installs are created in InstallJammer using the Install Project Wizard. You can open up the wizard by either clicking the "New Install" button on the main toolbar or by opening up the File menu and clicking "New." By clicking either of these options, you should now be presented with the Install Project Wizard. InstallJammer uses the wizard to guide you through the rest of the new install process.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Step 1 - Project Information</span></p>
<p class=rvps1><img border="0" src="Images/image132032558.jpg" width="481" height="382"></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Step 1 of the wizard asks you for some basic project information. This information is all internal to InstallJammer and tells it where you want to save your project and what you want to call the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Project Name</span></p>
<p class=rvps1><span class=rvts2>This is what you want to call your project. This does not have to be the name of the application you are installing, but it would make sense.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Project Directory</span></p>
<p class=rvps1><span class=rvts2>This is the directory where you want to store this project. A new directory will be created to store your install. In InstallJammer, each project is stored in its own directory so that everything can be contained. </span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Step 2 - Application Strings</span></p>
<p class=rvps1><img border="0" src="Images/screen2.png" width="481" height="382"></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Step 2 of the wizard asks you some information about the product or program that you will be installing.</span></p>
<p class=rvps2><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Application Name</span></p>
<p class=rvps1><span class=rvts2>This is the name of your application or product.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Short Application Name</span></p>
<p class=rvps1><span class=rvts2>This is a shortened name for your application.&nbsp; This name is used on most UNIX systems as a directory, so it is usually all lowercase with no spaces.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Version</span></p>
<p class=rvps1><span class=rvts2>This is the version of your product. This value is not used by InstallJammer for anything, it is there as a representation of your software to the person installing it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Company</span></p>
<p class=rvps1><span class=rvts2>This is the name of your company or organization. </span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Step 3 - Application Information&nbsp; </span></p>
<p class=rvps1><img border="0" src="Images/screen3.png" width="481" height="382"></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>Step 3 of the wizard asks for a few more pieces of information about your application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Install Version</span></p>
<p class=rvps1><span class=rvts2>This version is used internally by InstallJammer as a way to track this version of your software against future versions. If you distribute new versions of your software with the version incremented in this field, InstallJammer can (based on your options) install only files that are of the newer version. More on this later.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Windows Application Executable</span></p>
<p class=rvps1><span class=rvts2>This is the name of the main executable for your application on Windows.&nbsp; This is the entry point into your program, and InstallJammer uses it to make shortcuts and launch your application from within the installer if needed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>UNIX Application Executable</span></p>
<p class=rvps1><span class=rvts2>This is the name of the main executable or script for your application in a UNIX environment.&nbsp; This is the entry point into your program, and InstallJammer uses it to make shortcuts and launch your application from within the installer if needed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Step 4 - Application Location</span></p>
<p class=rvps1><img border="0" src="Images/step4.png" width="481" height="382"></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Step 4 is a very simple step that asks for the directory that your application is in. By adding your directory here, your application will start with the entire contents of this directory and all of its subdirectories in the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>You do not have to specify a directory now. You can wait until you get started building the rest of your install and add whatever files and directories you want later.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Step 5 - Theme Selection</span></p>
<p class=rvps1><img border="0" src="Images/step5.png" width="481" height="382"></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Step 5 gives you a list of install themes to choose from.&nbsp; The default theme is the Modern Wizard theme.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Step 6 - Platform Selection</span></p>
<p class=rvps1><img border="0" src="Images/step6.png" width="481" height="382"></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Step 6 presents you with a list of platforms supported by your installation of InstallJammer and asks you to pick which ones you plan to install on. You need only pick a single platform for your installer if your software is not multiplatform.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>By default, only the platform you are building on is selected. Not selecting a platform here does not remove the platform from your installer, it only disables it. This is so that if you decide to add more platforms in the future, you can easily switch them on as needed without having to rebuild your install project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Step 7 - Additional Features</span></p>
<p class=rvps1><img border="0" src="Images/screen7.png" width="481" height="382"></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Step 7 lets you select some additional features you might like to add to your installer. Most of the features are switched on by default, as they are common to most installers used today.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Allow users to select custom components in your install</span></p>
<p class=rvps1><span class=rvts2>If this feature is checked, InstallJammer will add two panes to your installer that allow a user to select a Custom install option and then select the custom components they wish to install from your product.&nbsp; This is only important if you have many components in your install and you want the user to be able to choose which parts they install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Include an uninstaller</span></p>
<p class=rvps1><span class=rvts2>If this feature is checked, InstallJammer will add an action to your install actions to create an uninstaller when your application is installed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add the uninstaller to the Windows Add/Remove Programs register</span></p>
<p class=rvps1><span class=rvts2>If this feature is checked, InstallJammer will add an action to your install actions to create a registry entry in Windows' "Add/Remove Programs" registry. This means your customers will be able to uninstall your program from the main Windows Control Panel.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add a Windows Program shortcut action for the uninstaller</span></p>
<p class=rvps1><span class=rvts2>If this feature is checked, InstallJammer will add an action to your installer to create a Windows shortcut in your application's Program Folder that points to the uninstaller for your application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add a Windows Program shortcut action for this application</span></p>
<p class=rvps1><span class=rvts2>If this feature is checked, InstallJammer will add an action to your installer to create a Windows shortcut in your application's Program Folder that points to your application. The Program Folder will automatically be created for your application if it does not already exist.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add a View Readme checkbutton</span></p>
<p class=rvps1><span class=rvts2>If this feature is checked, InstallJammer will add a View Readme checkbutton to the Setup Complete pane of your installer to allow the user to view your README file before exiting the installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add a Launch Application checkbutton</span></p>
<p class=rvps1><span class=rvts2>If this feature is checked, InstallJammer will add a checkbutton to the Setup Complete pane of your installer to allow the user to launch your application before exiting the installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add a Create Desktop Shortcut checkbutton</span></p>
<p class=rvps1><span class=rvts2>If this feature is checked, InstallJammer will add a Create Desktop Shortcut checkbutton to the Setup Complete pane of your installer to allow the user to create a shortcut to your application on their desktop before exiting the installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add a Create Quick Launch checkbutton</span></p>
<p class=rvps1><span class=rvts2>If this feature is checked, InstallJammer will add a Create Quick Launch Shortcut checkbutton to the Setup Complete pane of your installer to allow the user to create a shortcut to your application in their quick launch toolbar before exiting the installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Final Step - Create Install</span></p>
<p class=rvps1><img border="0" src="Images/image1052404295.jpg" width="481" height="382"></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Now that you have gone through all the steps, you're ready to create your install! Click the finish button, and InstallJammer will create your install and open it to get you started.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Building Your Install</span></p>
<p class=rvps1><span class=rvts2>Now you're ready to build your installer! Click the Build Install button on the toolbar or under the Build menu, and InstallJammer will build an installer for your application. If you entered all of your data correctly, you should end up with an installer that is ready to go!</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Testing Your Installer</span></p>
<p class=rvps1><span class=rvts2>If your installer built successfully, you're ready to give it a test. Click the Test Install button on the toolbar or under the Build menu. Run through the installer, and your program should install in a default location. Make sure you don't change the destination directory when testing your installer. If you do, InstallJammer can't find your installed application to test the uninstaller.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Testing Your Uninstaller</span></p>
<p class=rvps1><span class=rvts2>Once you have your application installed, it's time to test your uninstaller. Click the Test Uninstall button on the toolbar or under the Build menu. InstallJammer will execute the uninstaller that was created when your application was installed. Run through the uninstaller to delete the test run you just installed.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CreateFileLink.html.


























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Create File Link</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Create File Link">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Create File Link</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CopyFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CreateFolder.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action creates a link in the file system to another file.&nbsp; The link can be a symbolic or a hard link.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Link Name</span></p>
<p class=rvps1><span class=rvts2>The file name of the link to create on the target system.&nbsp; This file will point to another file in the file system.&nbsp; If the path is relative, it will be made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Link Target</span></p>
<p class=rvps1><span class=rvts2>The target file of the link to create.&nbsp; The new file link will point to this file.&nbsp; If the path is relative, it will be made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Link Type</span></p>
<p class=rvps1><span class=rvts2>The type of link to create: hard or symbolic.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values create a symbolic link from our program executable into /usr/local/bin.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Link Name:&nbsp;&nbsp; /usr/local/bin/myprogram</span></p>
<p class=rvps1><span class=rvts4>Link Target: &lt;%InstallDir%&gt;/myprogram</span></p>
<p class=rvps1><span class=rvts4>Link Type:&nbsp;&nbsp; symbolic</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CreateFolder.html.










































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Create Folder</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Create Folder">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Create Folder</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CreateFileLink.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="DeleteFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to create a new folder or directory on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Folder Name</span></p>
<p class=rvps1><span class=rvts2>The name of the folder or directory to create.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CreateInstallPanes.html.


































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Create Install Panes</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Create Install Panes">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Create Install Panes</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AppendTextToWidget.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="DestroyWidget.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will create all of the install panes for the installer.&nbsp; This is usually done at the front of the install to create all of the panes at once so that they display more quickly as the user moves through them.&nbsp; If the panes are not created up front, they will be created as each one is displayed for the first time.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If this action is placed on a pane with a progress bar, it will increment the progress bar as each pane is created.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/CreateWindowsService.html.
























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Create Windows Service</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Create Windows Service">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
}
span.rvts6
{
 font-family: 'Verdana';
 font-weight: bold;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 7px 0px 7px 0px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Create Windows Service</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ContinueWindowsService.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="DeleteWindowsService.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will continue a Windows service that is in a paused state.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties</span><span class=rvts2>&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Account</span></p>
<p class=rvps1><span class=rvts2>Specifies an account name to be the user account under which the service should run.&nbsp; The account name takes the form domain\username. If the account is a local account, the account name may be specified as .\username or username. If this option is not specified, the service will run under the LocalSystem account. When Service Type is Kernel Driver or File System Driver, the account name should be the name of the driver object that the system uses to load the driver.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Command</span></p>
<p class=rvps1><span class=rvts2>This is the system command to be executed to start the service.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Database</span></p>
<p class=rvps2><span class=rvts2>Specifies the service control database to be operated on. By default, this is the active service control database on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Dependencies</span></p>
<p class=rvps2><span class=rvts2>Specifies the services and service load order groups that are required by this service and that must start before this service. This property contains a list of service names and load order groups. A load order group name must be prefixed with a + character to indicate that it is a group name and not a service.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Description</span></p>
<p class=rvps1><span class=rvts2>Specifies the long description for the service when viewed within the services console.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Display Name</span></p>
<p class=rvps2><span class=rvts2>Specifies the user visible name for the service. This is the name that is shown in the net start command and the SCM control panel applet.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Error Control</span></p>
<p class=rvps2><span class=rvts2>This option specifies how errors during service start are to be handled.</span></p>
<div class=rvps2><table border=1 cellpadding=1 cellspacing=2 style="border-color: #000000; border-style: solid;">
<tr valign=top>
<td width=71 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Critical</span></p>
</td>
<td width=691 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>An error message will be logged to the Windows event log if possible. If the last known good configuration is active, the system startup is aborted. Otherwise, the system is restarted with the last known good configuration.</span></p>
</td>
</tr>
<tr valign=top>
<td width=71 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Ignore</span></p>
</td>
<td width=691 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>An error message will be logged to the Windows event log. The system startup will continue.</span></p>
</td>
</tr>
<tr valign=top>
<td width=71 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Normal</span></p>
</td>
<td width=691 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>An error message will be logged to the Windows event log and a popup displayed to the user. The system startup will continue. This is the default.</span></p>
</td>
</tr>
<tr valign=top>
<td width=71 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Severe</span></p>
</td>
<td width=691 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>An error message will be logged to the Windows event log. The system startup will continue only if the last known good configuration is active. Otherwise, the system is restarted with the last known good configuration.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps2><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Interactive</span></p>
<p class=rvps2><span class=rvts5>This option specifies whether the service should be allowed to interact with the desktop. This is only valid when Service Type is specified to be Own Process or Shared Process. The Account option must not be used with this option since interactive services must run under the </span><span class=rvts6>LocalSystem</span><span class=rvts5> account. </span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Load Order Group</span></p>
<p class=rvps2><span class=rvts5>Specifies a group name to be the service load order group to which the service belongs. If the option is not specified, the service is assumed to not belong to any load order group.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Password</span></p>
<p class=rvps2><span class=rvts5>Specifies the password corresponding to the user account specified in the Account option. This option is ignored if the Account option is not specified.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Service Name</span></p>
<p class=rvps1><span class=rvts2>The name of the service to perform the action on.&nbsp; This can be the internal or the display name of the service.&nbsp; If the display name is given, it will automatically be translated to the internal service name for the action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Service Type</span></p>
<p class=rvps1><span class=rvts2>This property specifies the type of service to create.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=1 cellpadding=1 cellspacing=2 style="border-color: #000000; border-style: solid;">
<tr valign=top>
<td width=134 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Own Process</span></p>
</td>
<td width=628 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>Service that runs in its own process. This corresponds to the </span><span class=rvts3>SERVICE_WIN32_OWN_PROCESS</span><span class=rvts2> in the Windows SDK documentation. This is the default if the option is not specified.</span></p>
</td>
</tr>
<tr valign=top>
<td width=134 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Shared Process</span></p>
</td>
<td width=628 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>Service that runs inside a process shared with other services. This corresponds to the </span><span class=rvts3>SERVICE_WIN32_SHARED_PROCESS</span><span class=rvts2> in the Windows SDK documentation.</span></p>
</td>
</tr>
<tr valign=top>
<td width=134 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>File System Driver</span></p>
</td>
<td width=628 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>File system driver. This corresponds to the </span><span class=rvts3>SERVICE_FILE_SYSTEM_DRIVER</span><span class=rvts2> in the Windows SDK documentation.</span></p>
</td>
</tr>
<tr valign=top>
<td width=134 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Kernel Driver</span></p>
</td>
<td width=628 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>Kernel driver. This corresponds to the </span><span class=rvts3>SERVICE_KERNEL_DRIVER</span><span class=rvts2> in the Windows SDK documentation.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Start Type</span></p>
<p class=rvps1><span class=rvts2>This property specifies how the service is to be started.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=1 cellpadding=1 cellspacing=2 style="border-color: #000000; border-style: solid;">
<tr valign=top>
<td width=106 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Auto Start</span></p>
</td>
<td width=656 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>The service should be automatically started by the service control manager during system startup. This is the default if the option is not specified.</span></p>
</td>
</tr>
<tr valign=top>
<td width=106 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Boot Start</span></p>
</td>
<td width=656 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>The service should be automatically started by the system loader during system boot. This is only valid when Service Type is specified to be Kernel Driver or File System Driver.</span></p>
</td>
</tr>
<tr valign=top>
<td width=106 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Demand Start</span></p>
</td>
<td width=656 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>The service should be started by the system upon receiving an explicit program request.</span></p>
</td>
</tr>
<tr valign=top>
<td width=106 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>Disabled</span></p>
</td>
<td width=656 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>The service is disabled and cannot be started even on program request.</span></p>
</td>
</tr>
<tr valign=top>
<td width=106 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts3>System Start</span></p>
</td>
<td width=656 style="border-color: #000000; border-style: solid;">
<p class=rvps1><span class=rvts2>The service is a driver that is started by the operating system </span><span class=rvts3>IoInitSystem</span><span class=rvts2> function during system initialization. This is only valid when Service Type is specified to be Kernal Driver or File System Driver.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>System</span></p>
<p class=rvps2><span class=rvts2>Specifies the name of the system on which the command should be invoked. By default, this is the local system.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/Credits.html.


















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Credits</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Credits">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-size: 12pt;
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Credits</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="License.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ReleaseNotes.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts4>InstallJammer Multiplatform Installer</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Written by Damon Courtney</span></p>
<p class=rvps1><span class=rvts2>&lt;</span><a class=rvts5 href="mailto:damon@installjammer.com">damon@installjammer.com</a><span class=rvts2>&gt;</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><a class=rvts6 href="http://www.installjammer.com/">http://www.installjammer.com/</a></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Credits</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>InstallJammer would not be possible without the additional work of many others and their projects.&nbsp; This list is by no means complete and doesn't include any of the help received from the users of InstallJammer or the wonderful support of the Tcl community.&nbsp; This is simply a list of projects that have helped to build InstallJammer into what it is.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts3>BWidgets by the BWidgets Team</span></li>
<li class=rvps1><span class=rvts3>Tktable by Jeff Hobbs</span></li>
<li class=rvps1><span class=rvts3>TWAPI by Ashok P. Nadkarni</span></li>
<li class=rvps1><span class=rvts3>TkDND by Georgios Petasis</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/DebuggingAnInstall.html.


















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Debugging an Install</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Debugging an Install">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts3
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Debugging an Install</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="VirtualDirectoryDefinitions.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="WhatIsTheBuilderAPI.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>InstallJammer provides several different ways and helpful tools to help debug installs.&nbsp; Most installs are fairly simple and don't really require complex debugging, but some installs can get very elaborate and require the ability to peek into what InstallJammer is really doing in the background.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Commands for debugging</span></p>
<p class=rvps1><span class=rvts3>InstallJammer provides two commands to assist with debugging: </span><span class=rvts4>debug</span><span class=rvts3> and </span><span class=rvts4>debugging</span><span class=rvts3>.&nbsp; The debug command will output a debug message and can be used in scripts or in the console to output debugging information.&nbsp; The debugging command is the command that controls what debugging is taking place during installation.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>The following is the usage for the debugging command:</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>debugging level &lt;0, 1, 2 or 3&gt;</span></p>
<p class=rvps1><span class=rvts3>This command sets the level of debugging output to show.&nbsp; 0 means no output, and 3 means very verbose output.&nbsp; The default level when not specified is 1.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>debugging &lt;on | off&gt;</span></p>
<p class=rvps1><span class=rvts3>This command will simply turn debugging on or off.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>debugging &lt;file | console&gt; &lt;on | off&gt; ?filename?</span></p>
<p class=rvps1><span class=rvts3>This command will turn debugging on or off specifically for outputing debug information to a file or to the console.&nbsp; If a filename is given, file output will be directed to that file.&nbsp; If no filename is given, and debug output to a file is turned on, the file &lt;%Temp%&gt;/debug.log will be used.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>In any case, when you use the debugging command, it will tell you exactly what and how it is logging.&nbsp; Calling the debugging command with no arguments will tell you the current state of debugging in the installer.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts2>Debug output to the console is controlled by the ::debug variable.</span></p>
<p class=rvps1><span class=rvts2>Debug output to a file is controlled by the ::info(Debugging) variable.</span></p>
<p class=rvps1><span class=rvts2>The ::debugfp variable is the open file pointer to the debug log file if it is open.&nbsp; The variable will be an empty string if file logging is turned off.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/DeleteEnvironmentVariable.html.
























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Delete Environment Variable</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Delete Environment Variable">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Delete Environment Variable</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddEnvironmentVariable.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="RebootOrShutdownSystem.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to delete an environment variable from the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>Windows</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Level</span></p>
<p class=rvps1><span class=rvts2>This specifies whether the variable should be deleted for every user on the system or just the current user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Variable</span></p>
<p class=rvps1><span class=rvts2>This property specifies the environment variable to be deleted from the target system.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/DeleteFile.html.










































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Delete File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Delete File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Courier';
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Delete File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CreateFolder.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ReadFileIntoVirtualText.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will delete all of the files specified from the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Files</span></p>
<p class=rvps1><span class=rvts2>A list of files or patterns separated by a ;.&nbsp; Any pattern or file that is a relative path is automatically made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would delete a /tmp/mytemp directory and all of the .bak1 files in the &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Files: /tmp/mytemp;*.bak1</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/DeleteWindowsService.html.






























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Delete Windows Service</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Delete Windows Service">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 7px 0px 7px 0px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Delete Windows Service</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CreateWindowsService.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PauseWindowsService.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will delete a Windows service from the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Database</span></p>
<p class=rvps2><span class=rvts2>Specifies the service control database to be operated on. By default, this is the active service control database on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Service Name</span></p>
<p class=rvps1><span class=rvts2>The name of the service to perform the action on.&nbsp; This can be the internal or the display name of the service.&nbsp; If the display name is given, it will automatically be translated to the internal service name for the action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>System</span></p>
<p class=rvps2><span class=rvts2>Specifies the name of the system on which the command should be invoked. By default, this is the local system.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/DestroyWidget.html.










































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Destroy Widget</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Destroy Widget">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Destroy Widget</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CreateInstallPanes.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FocusOnWidget.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will permanently destroy a widget.&nbsp; A widget can either be a single widget on a pane created with the </span><a class=rvts4 href="AddWidget.html">Add Widget</a><span class=rvts2> action, or it can specify a message panel or another pane.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Widget ID</span></p>
<p class=rvps1><span class=rvts2>A list of Widget IDs or Aliases separated by ;.&nbsp; A widget ID can also be specified as &lt;PANE&gt;.&lt;WIDGET&gt; where &lt;PANE&gt; is the ID or Alias of a specific pane and &lt;WIDGET&gt; is the ID or Alias of a widget on that pane.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/DestroyWidget1.html.


















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>DestroyWidget</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="DestroyWidget">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>DestroyWidget</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ErrorMessage.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="Exit1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::DestroyWidget</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Completely destroys a widget or list of widgets.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-widgets</span></p>
<p class=rvps1><span class=rvts2>A list of widget IDs or aliases.&nbsp; Each widget can be specified by its ID, an alias or in the form of &lt;PANE&gt;.&lt;WIDGET&gt; where &lt;PANE&gt; is the ID or Alias of a pane and &lt;WIDGET&gt; is the ID or Alias of a widget on that pane.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/DisableWow64Redirection.html.










































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Disable Wow64 Redirection</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Disable Wow64 Redirection">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Disable Wow64 Redirection</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="UninstallSelectedFiles.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="RevertWow64Redirection.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>On 64 bit Windows Vista (and beyond?) systems, installers and setup programs have certain system directories automatically redirected to a 32 bit directory hierarchy.&nbsp; This action disables that redirection so that libraries can be properly installed in the 64 bit directories.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Disabling the redirection will continue for the rest of the installation or until a </span><a class=rvts4 href="RevertWow64Redirection.html">Revert Wow64 Redirection</a><span class=rvts2> action is executed, but the redirection only applies to the current process, so it will not continue once your installer exits.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>Windows</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/DiskBuilder.html.


























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Disk Builder</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Disk Builder">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Disk Builder</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="VirtualText.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="TestRun.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>The disk builder is where the actual installation binaries are built. Once you have completed all the steps to creating your install, you must build it in order to use it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Building an install</span></p>
<p class=rvps1><span class=rvts2>Pressing the build button will start the build process. Only the platforms selected in the Platforms to build section will be built. This allows you to quickly rebuild a single platform instead of always having to build all of the binaries.&nbsp; Platforms that are not checked, or platforms that are not active will not be built.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Once the build process starts, you can continue working on the install, as the build process takes place in the background. This is convenient if your build is a long one, and you wish to keep making changes to your install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Quick Build</span></p>
<p class=rvps1><span class=rvts2>A quick build means InstallJammer will rebuild all of the files for your installer, but it won't repackage any of your application files.&nbsp; This is a fast way to rebuild changes you've made to the installer when you haven't actually changed any of the files you are installing.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Build for final release</span></p>
<p class=rvps1><span class=rvts2>This option tells InstallJammer that you are building your installs for final release.&nbsp; With this option checked, InstallJammer will rebuild the full install, including your application files, even if you select a quick build and disable debugging options in the resulting installer.&nbsp; This produces an installer that is ready for distribution to customers.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/EnvironmentVariableExists.html.








































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>EnvironmentVariableExists</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Environment Variable Exists">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>EnvironmentVariableExists</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GetWidgetPath.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FindObjects.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::EnvironmentVariableExists</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Check to see if a given environment variable exists or not in the current system environment.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts4>This API call just looks into Tcl's ::env() array to see if the variable exists or not.&nbsp; The ::env() array is built by Tcl based on the user's environment.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>True or false.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-variable &lt;varName&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The variable to check for existence.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/EnvironmentVariableTestCondition.html.




















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Env Variable Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Environment Variable Test Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Env Variable Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="StringMatchCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PackageTestCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if an environment variable exists or not.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=142>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; exists</span></p>
</td>
<td width=620>
<p class=rvps1><span class=rvts2>True if the virtual text exists.</span></p>
</td>
</tr>
<tr valign=top>
<td width=142>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not exist</span></p>
</td>
<td width=620>
<p class=rvps1><span class=rvts2>True if the virtual text does not exist.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Variable</span></p>
<p class=rvps1><span class=rvts2>The name of the environment variable to check.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ErrorMessage.html.














































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>ErrorMessage</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="ErrorMessage">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>ErrorMessage</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CopyObject.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="DestroyWidget1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::ErrorMessage</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Display an error message to the user using standard tools.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty String</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-message &lt;error message&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>This is the body of the message to display to the user in the dialog box or in the console.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-title &lt;dialog title&gt;</span></p>
<p class=rvps1><span class=rvts2>This is the window title of the dialog box when it pops up.&nbsp; If not specified, it will default to "Install Error."</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ExecuteAction.html.
















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Execute Action</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Execute Action">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Execute Action</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ConsolePause.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ExecuteExternalProgram.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to execute another action or action group.&nbsp; The Execute Action's conditions are checked before executing the action specified, and then the conditions of the target action can be checked based on properties.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Action</span></p>
<p class=rvps1><span class=rvts2>The ID or alias of the action to execute.&nbsp; This can be either another action in the installer or an action group.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Evaluate Conditions</span></p>
<p class=rvps1><span class=rvts2>If this is true, the conditions on the target action will also be checked before executing the action.&nbsp; If this is false, only the conditions of the Execute Action action will be checked, and any conditions on the target action or action group will be ignored.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ExecuteExternalProgram.html.




















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Execute External Program</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Execute External Program">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Execute External Program</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ExecuteAction.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ExecuteScript.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will execute an external program like a shell script or batch file and return the results in specified virtual text.&nbsp; It can also be used to show progressive output while the external program is running, so that the user can see what the program is doing while it runs.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>You cannot execute in a console or as root if Show Progressive Output is true.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Clear Progressive Widget</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the progressive text widget used during Show Progressive Output will be cleared before the external program is executed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Console Title (UNIX only)</span></p>
<p class=rvps1><span class=rvts2>If this property is not null, it specifies the title to use on the console window if the Execute in Console property is true.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Execute as Root (UNIX only)</span></p>
<p class=rvps1><span class=rvts2>If this property is true, InstallJammer will attempt to execute the given program as root.&nbsp; If the user is already root, the action will execute as normal.&nbsp; If the user is not root, they will be prompted for their root password which will then execute the program as root.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Execute in Console</span></p>
<p class=rvps1><span class=rvts2>If this property is true, InstallJammer will execute the external program in a console window.&nbsp; This is useful for executing scripts that expect some kind of input from the user on the command-line.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts5>InstallJammer will attempt to locate the best possible terminal based on desktop environment.&nbsp; On KDE, this will be Konsole.&nbsp; On Gnome, it will be gnome-terminal.&nbsp; If nothing else can be found, good old xterm will be used.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>If Execute in Console is specified in conjunction with Execute as Root, and the user is not root, the console will first ask the user for their root password in the same console window before executing.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts3>Include Stderr</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the standard error channel of the executing program will be included in the output from the program.&nbsp; This will include the standard error in the result of the execution or in the progressive output if it is being used.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Program Command Line</span></p>
<p class=rvps1><span class=rvts2>This is the command-line of the program to execute.&nbsp; The command line is executed exactly as it is input with all arguments included.&nbsp; Virtual text will automatically be substituted.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>It should be noted that arguments on the command-line are separated by spaces, and each argument is passed separately to the system as arguments to the command being executed.&nbsp; Each argument is parsed individually for virtual text rather than substituting the string as a whole so that each argument is properly appended to a list of arguments to execute.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Progressive Output Widget</span></p>
<p class=rvps1><span class=rvts2>This property specifies a textbox widget that will be updated with the output of a progressive command as it becomes available.&nbsp; The textbox will automatically scroll down to keep up with new input.&nbsp; A widget can be specified by its ID or Alias if it was created with the </span><a class=rvts6 href="AddWidget.html">Add Widget</a><span class=rvts2> action, or it can be the name of a widget on the current pane, or it can be specified as &lt;PANE&gt;.&lt;WIDGET&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Result Virtual Text&nbsp; </span></p>
<p class=rvps1><span class=rvts2>This is a virtual text variable to store the result of external program.&nbsp; This will be any data that is output to standard out while the program is running.&nbsp; If progressive output is being shown, this variable will be the entire result that was output when the program finishes executing.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Show Progressive Output</span></p>
<p class=rvps1><span class=rvts2>If this value is true, the Progressive Output Widget will be updated with new data as it becomes available from the external program.&nbsp; If this value is false, all output from the external program is buffered and stored in Result Virtual Text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Status Virtual Text</span></p>
<p class=rvps1><span class=rvts2>This is a virtual text variable that stores the exit code of the external program.&nbsp; An exit code of 0 usually means that the program succeeded without error.&nbsp; Any other exit code usually means that the program failed in some way.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Wait&nbsp; for Program</span></p>
<p class=rvps1><span class=rvts2>This tells InstallJammer to wait until the external program finishes before continuing on with the install.&nbsp; If this value is false, InstallJammer will execute the external program in the background and continue on.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Watch Progressive Output</span></p>
<p class=rvps1><span class=rvts2>If this property is true, and Show Progressive Output is true, InstallJammer will watch the output from the external program for cues that tell InstallJammer to set virtual text while it is running.&nbsp; The text InstallJammer looks for looks like a line surrounded by : with a single word as the first argument followed by any other arguments.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Example:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>:Status Checking for file...:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This will set the &lt;%Status%&gt; virtual text variable to the value "Checking for file..." and then refresh the screen.&nbsp; This allows an external program to update the status or progres bars while it is running to keep the GUI alive so that the user knows what is going on while it is running.&nbsp; Any line that matches the output that InstallJammer is looking for will not be displayed in the output.&nbsp; It will be swallowed by InstallJammer before the user sees it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Watch Regular Expression</span></p>
<p class=rvps1><span class=rvts2>This property specifies the regular expression to use when watching progressive output.&nbsp; By default, it looks for text in the manner described for Watch Progressive Output, but this property can be changed to look for any other kind of pattern.&nbsp; If the regular expression provides two submatch values, they will be used as the virtual text variable name and the value to set the virtual text to.&nbsp; If there is only one or no submatch, the Watch Virtual Text property will be used to store the value that matches.&nbsp; This property should only be changed if you really know what you're doing and know enough about regular expressions.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Watch Virtual Text</span></p>
<p class=rvps1><span class=rvts2>If the Watch Regular Expression does not include two submatches, this virtual text will be used as the virtual text to set with the result of the regular expression when watching progressive output.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ExecuteScript.html.




















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Execute Script</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Execute Script">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Execute Script</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ExecuteExternalProgram.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AdjustLineFeeds.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to script unique actions in Tcl that allow you to do almost anything with your installer.&nbsp; Since Tcl scripts don't have any constraints within an installer, this action can be used to handle anything that is not already available in another action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>See What is Tcl/Tk? for more information.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Result Virtual Text</span></p>
<p class=rvps1><span class=rvts2>This is a virtual text variable to store the result of the script.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Tcl Script</span></p>
<p class=rvps1><span class=rvts2>This property holds the Tcl script to be executed.&nbsp; All virtual text will be substituted for the script.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ExecuteScriptCondition.html.












































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Execute Script Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Execute Script Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Execute Script Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CommandLineTestCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ObjectIsActiveCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition is a Tcl script that must return true if the condition passes or false if the condition does not pass.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Script</span></p>
<p class=rvps1><span class=rvts2>The Tcl script to evaluate.&nbsp; All virtual text is substituted when evaluating the script.&nbsp; Your script should always end with a return command that returns either true or false.&nbsp; Anything that is returned that looks to be true will be true.&nbsp; Anything that does not look to be true (including an empty string or other text) will be considered false and cause the condition to return false.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following script is an example that returns true if we are running a patch installer or false otherwise:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>if {[string is true &lt;%RunningInstaller%&gt;] &amp;&amp; [string is true &lt;%UpgradeInstall%&gt;]} {</span></p>
<p class=rvps1><span class=rvts4>&nbsp;&nbsp;&nbsp; return 1</span></p>
<p class=rvps1><span class=rvts4>}</span></p>
<p class=rvps1><span class=rvts4>return 0</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2>Note that the script always returns a true or false answer.&nbsp; This is the safest way to ensure that your condition will always return something valid to the installer.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/Exit.html.
















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Exit</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Exit">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Exit</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ContinueInstall.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FetchURL.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will cause the installer to exit.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Exit Code</span></p>
<p class=rvps1><span class=rvts2>If this property is not empty, it specifies an exit code to exit the (un)installer with.&nbsp; By default, an (un)installer will exit with a 0 if it finishes successfully or 1 if the install is canceled.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Exit Type</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer what kind of exit this is.&nbsp; Whether it's a cancel or finish.&nbsp; This mostly affects what action group InstallJammer will execute as it is executing.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/Exit1.html.
























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Exit</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Exit">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Exit</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="DestroyWidget1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FetchURL1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::Exit</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Exit the running program as either a canceled or finished install.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-exitcode &lt;exit code&gt;</span></p>
<p class=rvps1><span class=rvts2>If this option is specified, it will set the exit code of the running (un)installer before it exits.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-exittype &lt;cancel | finish&gt;</span></p>
<p class=rvps1><span class=rvts2>Tell the installer whether to exit as a canceled install or a finished install.&nbsp; This affects whether the Cancel or Finish actions are executed as the installer exits.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FHContent.css.


















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
BODY {font-family: verdana,geneva,arial,sans-serif}
P {font-size: 0.8em}
.it {font-style: italic}
H1 {font-size: 1.2em}
H2 {font-size: 1em}
H3 {font-size: 0.8em}
H4 {font-size: 0.8em; font-style: italic}
UL,OL {font-size: 0.8em}
LI {margin-top: 0.5em}
Added docs/html/FHDisplayToc.js.






















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*Copyright DevHost Ltd. 2007 : v2.026*/
var isIE = navigator.appName.toLowerCase().indexOf("explorer") > -1;
var mdi = (isIE) ? textSizes[1]:textSizes[3];
var sml = (isIE) ? textSizes[2]:textSizes[4];
var oldCurrentNumber = "", oldLastVisitNumber = "";
var toDisplay = new Array();
for (ir=0; ir<tocTab.length; ir++) 
  {toDisplay[ir] = tocTab[ir][0].split(".").length==1;}

function reDisplay(currentNumber,tocChange,noLink,e) {
  if (e)
  {
    ctrlKeyDown = (isIE) ? e.ctrlKey : (e.modifiers==2);
    if (tocChange && ctrlKeyDown) tocChange = 2;
  }
  try
  {toc.document.clear();}
  catch (e)
  {location.href = "index.html";}
  toc.document.write("<!-- saved from url=(0014)about:internet -->\n<html>\n<head>\n<title>ToC</title>\n</head>\n<body bgcolor=\"" + backColor + "\">\n<table border=0 cellspacing=1 cellpadding=0>\n<tr>\n<td colspan=" + (nCols+1) + "><a href=\"javaScript:history.go(0)\" onMouseDown=\"parent.reDisplay('" + tocTab[0][0] + "',0,0)\" style=\"font-family: " + fontTitle + "; font-weight:bold; font-size:" + textSizes[0] + "em; color: " + titleColor + "; text-decoration:none\">" + tocTab[0][1] + "</a></td></tr>\n<tr>");

  for (k=0; k<nCols; k++) 
    {toc.document.write("<td>&nbsp;</td>");}
  toc.document.write("<td width=240>&nbsp;</td></tr>");

  var currentNumArray = currentNumber.split(".");
  var currentLevel = currentNumArray.length-1;

  var currentIndex = null;
  for (i=0; i<tocTab.length; i++) 
  {
    if (tocTab[i][0] == currentNumber) 
      {currentIndex = i; break;}
  }

  if (currentIndex == null)
    {for (i=0; i<tocTab.length; i++) 
      {if (tocTab[i][3] == currentNumber) 
         {
           currentIndex = i;
           currentNumber = tocTab[i][0];
           currentNumArray = currentNumber.split(".");
           currentLevel = currentNumArray.length-1;
           break;
         }
       if (tocTab[i][4] == currentNumber) 
         {
           currentIndex = i;
           currentNumber = tocTab[i][0];
           currentNumArray = currentNumber.split(".");
           currentLevel = currentNumArray.length-1;
           break;
         }
      }
    }

  if (currentIndex == null)
    {currentIndex=0;}//the requested page was not found, so show the home page instead
        
  if (currentIndex < tocTab.length-1) 
    {
      nextLevel = tocTab[currentIndex+1][0].split(".").length-1;
      currentIsExpanded = nextLevel > currentLevel && toDisplay[currentIndex+1];
    } 
  else currentIsExpanded = false;

  theHref = (noLink) ? "" : tocTab[currentIndex][2];
  theTarget = tocTab[currentIndex][3];

  for (i=1; i<tocTab.length; i++) 
    {
      if (tocChange) 
        {
          thisNumber = tocTab[i][0];
          thisNumArray = thisNumber.split(".");
          thisLevel = thisNumArray.length-1;
          isOnPath = true;
          if (thisLevel > 0) 
            {
              for (j=0; j<thisLevel; j++) 
                {isOnPath = (j>currentLevel) ? false : isOnPath && (thisNumArray[j] == currentNumArray[j]);}
            } 
          toDisplay[i] = (tocChange == 1) ? isOnPath : (isOnPath || toDisplay[i]);
          if (thisNumber.indexOf(currentNumber+".")==0 && thisLevel > currentLevel) 
            {                 
              if (currentIsExpanded) toDisplay[i] = false;
              else toDisplay[i] = (thisLevel == currentLevel+1); 
            }
        } 
    } // End of loop over the tocTab


  var scrollY=0, addScroll=tocScroll; 
  for (i=1; i<tocTab.length; i++) 
    {
      if (toDisplay[i]) 
        {
          thisNumber = tocTab[i][0];
          thisNumArray = thisNumber.split(".");
          thisLevel = thisNumArray.length-1;
          isCurrent = (i == currentIndex);
          if (i < tocTab.length-1) 
            {
              nextLevel = tocTab[i+1][0].split(".").length-1;
              img = (thisLevel >= nextLevel) ? "topic.png" : ((toDisplay[i+1]) ? "open.png" : "closed.png");
            } 
          else img = "topic.png";

          if (addScroll) scrollY+=((thisLevel<2)?mdi:sml)*25;
          if (isCurrent) addScroll=false;
          if (noLink)
            thisTextColor = (thisNumber==oldCurrentNumber) ? currentColor:((thisNumber==oldLastVisitNumber) ? lastVisitColor:normalColor);
          else thisTextColor = (thisNumber==currentNumber) ? currentColor:((thisNumber==oldCurrentNumber) ? lastVisitColor:normalColor);

          toc.document.writeln("<tr valign=top>");

          for (k=1; k<=thisLevel; k++) 
            {toc.document.writeln("<td>&nbsp;</td>");}

          toc.document.writeln("<td valign=top><a href=\"javaScript:history.go(0)\" onMouseDown=\"parent.reDisplay('" + thisNumber + "'," + tocBehaviour[0] + "," + tocLinks[0] + ",event)\"><img src=\"Images/" + img + "\" border=0></a></td> <td colspan=" + (nCols-thisLevel) + ">&nbsp;<a href=\"javaScript:history.go(0)\" onMouseDown=\"parent.reDisplay('" + thisNumber + "'," + tocBehaviour[1] + "," + tocLinks[1] + ",event)\" style=\"font-family: " + fontLines + ";" + ((thisLevel<=mLevel)?"font-weight:bold":"") +  "; font-size:" + ((thisLevel<=mLevel)?mdi:sml) + "em; color: " + thisTextColor + "; text-decoration:none\">" + ((showNumbers)?(thisNumber+" "):"") + tocTab[i][1] + "</a></td></tr>");
        }
    }

  if (!noLink) 
    { 
      oldLastVisitNumber = oldCurrentNumber;
      oldCurrentNumber = currentNumber;
    }

  toc.document.writeln("</table>\n");
  toc.document.writeln("\n\r\n\r  <br>\n\r  <hr>\n\r <div style=\'font-family: Verdana; font-size:0.6em; color:#000000\'>\n\r  \n\r  </div>\n</body></html>");
  if (tocScroll) toc.scroll(0,scrollY);
  if (theHref) 
    if (theTarget=="top") top.location.href = theHref;
    else if (theTarget=="parent") parent.location.href = theHref;
    else if (theTarget=="blank") open(theHref,"");
    else content.location.href = theHref;
  toc.document.close();
}
Added docs/html/FHKeywords.html.




>
>
1
2
<!-- saved from url=(0014)about:internet -->
<html><head><title></title><style type="text/css"><!-- body{font-size: 10pt; font-family: "Verdana"; color: #2E2E2E;} --></style></head><body bgcolor="#D1D1D1"><div><br></div><div><a href="10.html" target="content"><font color=#2E2E2E>1.0</font></a></div><div><a href="101.html" target="content"><font color=#2E2E2E>1.0.1</font></a></div><div><a href="102.html" target="content"><font color=#2E2E2E>1.0.2</font></a></div><div><a href="103.html" target="content"><font color=#2E2E2E>1.0.3</font></a></div><div><a href="104.html" target="content"><font color=#2E2E2E>1.0.4</font></a></div><div><a href="10b1.html" target="content"><font color=#2E2E2E>1.0b1</font></a></div><div><a href="10b2.html" target="content"><font color=#2E2E2E>1.0b2</font></a></div><div><a href="10rc1.html" target="content"><font color=#2E2E2E>1.0rc1</font></a></div><div><a href="10rc3.html" target="content"><font color=#2E2E2E>1.0rc3</font></a></div><div><a href="11.html" target="content"><font color=#2E2E2E>1.1</font></a></div><div><a href="11b1.html" target="content"><font color=#2E2E2E>1.1b1</font></a></div><div><a href="11b2.html" target="content"><font color=#2E2E2E>1.1b2</font></a></div><div><a href="12.html" target="content"><font color=#2E2E2E>1.2</font></a></div><div><a href="121.html" target="content"><font color=#2E2E2E>1.2.1</font></a></div><div><a href="1210.html" target="content"><font color=#2E2E2E>1.2.10</font></a></div><div><a href="1210b1.html" target="content"><font color=#2E2E2E>1.2.10b1</font></a></div><div><a href="1211.html" target="content"><font color=#2E2E2E>1.2.11</font></a></div><div><a href="1212.html" target="content"><font color=#2E2E2E>1.2.12</font></a></div><div><a href="1213.html" target="content"><font color=#2E2E2E>1.2.13</font></a></div><div><a href="1214.html" target="content"><font color=#2E2E2E>1.2.14</font></a></div><div><a href="122.html" target="content"><font color=#2E2E2E>1.2.2</font></a></div><div><a href="123.html" target="content"><font color=#2E2E2E>1.2.3</font></a></div><div><a href="124.html" target="content"><font color=#2E2E2E>1.2.4</font></a></div><div><a href="126.html" target="content"><font color=#2E2E2E>1.2.6</font></a></div><div><a href="127.html" target="content"><font color=#2E2E2E>1.2.7</font></a></div><div><a href="128.html" target="content"><font color=#2E2E2E>1.2.8</font></a></div><div><a href="129.html" target="content"><font color=#2E2E2E>1.2.9</font></a></div><div><a href="12b1.html" target="content"><font color=#2E2E2E>1.2b1</font></a></div><div><a href="12b2.html" target="content"><font color=#2E2E2E>1.2b2</font></a></div><div><a href="AddDirectoryToPath.html" target="content"><font color=#2E2E2E>Add Directory to Path</font></a></div><div><a href="AddEnvironmentVariable.html" target="content"><font color=#2E2E2E>Add Environment Variable</font></a></div><div><a href="AddInstallInfo.html" target="content"><font color=#2E2E2E>Add Install Info</font></a></div><div><a href="AddPaneToOrder.html" target="content"><font color=#2E2E2E>Add Pane to Order</font></a></div><div><a href="AddResponseFileInfo.html" target="content"><font color=#2E2E2E>Add Response File Info</font></a></div><div><a href="AddToUninstall.html" target="content"><font color=#2E2E2E>Add to Uninstall</font></a></div><div><a href="AddWidget.html" target="content"><font color=#2E2E2E>Add Widget</font></a></div><div><a href="AddWindowsFileCommand.html" target="content"><font color=#2E2E2E>Add Windows File Command</font></a></div><div><a href="AddWindowsFileExtension.html" target="content"><font color=#2E2E2E>Add Windows File Extension</font></a></div><div><a href="AddWindowsFileType.html" target="content"><font color=#2E2E2E>Add Windows File Type</font></a></div><div><a href="AddWindowsRegistryKey.html" target="content"><font color=#2E2E2E>Add Windows Registry Key</font></a></div><div><a href="AddWindowsUninstallEntry.html" target="content"><font color=#2E2E2E>Add Windows Uninstall Entry</font></a></div><div><a href="AddInstallInfo1.html" target="content"><font color=#2E2E2E>AddInstallInfo</font></a></div><div><a href="AdjustLineFeeds.html" target="content"><font color=#2E2E2E>Adjust Line Feeds</font></a></div><div><a href="AppendTextToWidget.html" target="content"><font color=#2E2E2E>Append Text to Widget</font></a></div><div><a href="ApplicationInformation.html" target="content"><font color=#2E2E2E>Application Information</font></a></div><div><a href="AskYesOrNo.html" target="content"><font color=#2E2E2E>Ask Yes or No</font></a></div><div><a href="BackupFile.html" target="content"><font color=#2E2E2E>Backup File</font></a></div><div><a href="ChangeFileOwnership.html" target="content"><font color=#2E2E2E>Change File Ownership</font></a></div><div><a href="ChangeFilePermissions.html" target="content"><font color=#2E2E2E>Change File Permissions</font></a></div><div><a href="CheckForPreviousInstall.html" target="content"><font color=#2E2E2E>Check for Previous Install</font></a></div><div><a href="CommandLineOptions.html" target="content"><font color=#2E2E2E>Command Line Options</font></a></div><div><a href="CommandLineTestCondition.html" target="content"><font color=#2E2E2E>Command Line Test Condition</font></a></div><div><a href="CommandLineAPI.html" target="content"><font color=#2E2E2E>CommandLineAPI</font></a></div><div><a href="ComponentAPI.html" target="content"><font color=#2E2E2E>ComponentAPI</font></a></div><div><a href="Components.html" target="content"><font color=#2E2E2E>Components</font></a></div><div><a href="ConfigAPI.html" target="content"><font color=#2E2E2E>ConfigAPI</font></a></div><div><a href="ConsoleAskYesOrNo.html" target="content"><font color=#2E2E2E>Console Ask Yes or No</font></a></div><div><a href="ConsoleClearScreen.html" target="content"><font color=#2E2E2E>Console Clear Screen</font></a></div><div><a href="ConsoleGetUserInput.html" target="content"><font color=#2E2E2E>Console Get User Input</font></a></div><div><a href="ConsoleMessage.html" target="content"><font color=#2E2E2E>Console Message</font></a></div><div><a href="ConsolePause.html" target="content"><font color=#2E2E2E>Console Pause</font></a></div><div><a href="ContinueInstall.html" target="content"><font color=#2E2E2E>Continue Install</font></a></div><div><a href="ContinueWindowsService.html" target="content"><font color=#2E2E2E>Continue Windows Service</font></a></div><div><a href="CopyFile.html" target="content"><font color=#2E2E2E>Copy File</font></a></div><div><a href="CopyObject.html" target="content"><font color=#2E2E2E>CopyObject</font></a></div><div><a href="CreateANewInstallFast.html" target="content"><font color=#2E2E2E>Create a New Install Fast</font></a></div><div><a href="CreateANewInstallStep-by-Step.html" target="content"><font color=#2E2E2E>Create a New Install Step-by-Step</font></a></div><div><a href="CreateFileLink.html" target="content"><font color=#2E2E2E>Create File Link</font></a></div><div><a href="CreateFolder.html" target="content"><font color=#2E2E2E>Create Folder</font></a></div><div><a href="CreateInstallPanes.html" target="content"><font color=#2E2E2E>Create Install Panes</font></a></div><div><a href="CreateWindowsService.html" target="content"><font color=#2E2E2E>Create Windows Service</font></a></div><div><a href="Credits.html" target="content"><font color=#2E2E2E>Credits</font></a></div><div><a href="DebuggingAnInstall.html" target="content"><font color=#2E2E2E>Debugging an Install</font></a></div><div><a href="DeleteEnvironmentVariable.html" target="content"><font color=#2E2E2E>Delete Environment Variable</font></a></div><div><a href="DeleteFile.html" target="content"><font color=#2E2E2E>Delete File</font></a></div><div><a href="DeleteWindowsService.html" target="content"><font color=#2E2E2E>Delete Windows Service</font></a></div><div><a href="DestroyWidget.html" target="content"><font color=#2E2E2E>Destroy Widget</font></a></div><div><a href="DestroyWidget1.html" target="content"><font color=#2E2E2E>DestroyWidget</font></a></div><div><a href="DisableWow64Redirection.html" target="content"><font color=#2E2E2E>Disable Wow64 Redirection</font></a></div><div><a href="DiskBuilder.html" target="content"><font color=#2E2E2E>Disk Builder</font></a></div><div><a href="EnvironmentVariableTestCondition.html" target="content"><font color=#2E2E2E>Env Variable Test Condition</font></a></div><div><a href="EnvironmentVariableExists.html" target="content"><font color=#2E2E2E>EnvironmentVariableExists</font></a></div><div><a href="ErrorMessage.html" target="content"><font color=#2E2E2E>ErrorMessage</font></a></div><div><a href="ExecuteAction.html" target="content"><font color=#2E2E2E>Execute Action</font></a></div><div><a href="ExecuteExternalProgram.html" target="content"><font color=#2E2E2E>Execute External Program</font></a></div><div><a href="ExecuteScript.html" target="content"><font color=#2E2E2E>Execute Script</font></a></div><div><a href="ExecuteScriptCondition.html" target="content"><font color=#2E2E2E>Execute Script Condition</font></a></div><div><a href="Exit.html" target="content"><font color=#2E2E2E>Exit</font></a></div><div><a href="FetchURL.html" target="content"><font color=#2E2E2E>Fetch URL</font></a></div><div><a href="FileExistsCondition.html" target="content"><font color=#2E2E2E>File Exists Condition</font></a></div><div><a href="FileExtensionExistsCondition.html" target="content"><font color=#2E2E2E>File Extension Test Condition</font></a></div><div><a href="FileNameTestCondition.html" target="content"><font color=#2E2E2E>File Name Test Condition</font></a></div><div><a href="FilePermissionCondition.html" target="content"><font color=#2E2E2E>File Permission Condition</font></a></div><div><a href="FileTypeExistsCondition.html" target="content"><font color=#2E2E2E>File Type Test Condition</font></a></div><div><a href="FilesAndDirectories.html" target="content"><font color=#2E2E2E>Files and Directories</font></a></div><div><a href="FindProcesses.html" target="content"><font color=#2E2E2E>FindProcesses</font></a></div><div><a href="FocusOnWidget.html" target="content"><font color=#2E2E2E>Focus On Widget</font></a></div><div><a href="FrequentlyAskedQuestions.html" target="content"><font color=#2E2E2E>Frequently Asked Questions</font></a></div><div><a href="GenerateUID.html" target="content"><font color=#2E2E2E>Generate UID</font></a></div><div><a href="GetJavaProperty.html" target="content"><font color=#2E2E2E>Get Java Property</font></a></div><div><a href="GetPreviousInstallInfo.html" target="content"><font color=#2E2E2E>Get Previous Install Info</font></a></div><div><a href="GetAction.html" target="content"><font color=#2E2E2E>GetAction</font></a></div><div><a href="GetActionGroup.html" target="content"><font color=#2E2E2E>GetActionGroup</font></a></div><div><a href="GetComponentsForSetupType.html" target="content"><font color=#2E2E2E>GetComponentsForSetupType</font></a></div><div><a href="GetInstallSize.html" target="content"><font color=#2E2E2E>GetInstallSize</font></a></div><div><a href="GetSelectedFiles.html" target="content"><font color=#2E2E2E>GetSelectedFiles</font></a></div><div><a href="GetSystemPackageManager.html" target="content"><font color=#2E2E2E>GetSystemPackageManager</font></a></div><div><a href="GettingStarted.html" target="content"><font color=#2E2E2E>Getting Started</font></a></div><div><a href="GettingToKnowTheInstallBuilder.html" target="content"><font color=#2E2E2E>Getting to Know the Install Builder</font></a></div><div><a href="GetWidgetChildren.html" target="content"><font color=#2E2E2E>GetWidgetChildren</font></a></div><div><a href="GetWidgetPath.html" target="content"><font color=#2E2E2E>GetWidgetPath</font></a></div><div><a href="GroupsAndFiles.html" target="content"><font color=#2E2E2E>Groups and Files</font></a></div><div><a href="ImportWindowsRegistryFile.html" target="content"><font color=#2E2E2E>Import Windows Registry File</font></a></div><div><a href="TheInstallAPI.html" target="content"><font color=#2E2E2E>Install API</font></a></div><div><a href="Command-LineOptions.html" target="content"><font color=#2E2E2E>Install Builder Command Line Options</font></a></div><div><a href="InstallBuilderPreferences.html" target="content"><font color=#2E2E2E>Install Builder Preferences</font></a></div><div><a href="InstallDesktopShortcut.html" target="content"><font color=#2E2E2E>Install Desktop Shortcut</font></a></div><div><a href="InstallLogFile.html" target="content"><font color=#2E2E2E>Install Log File</font></a></div><div><a href="InstallProgramFolderShortcut.html" target="content"><font color=#2E2E2E>Install Program Folder Shortcut</font></a></div><div><a href="InstallSelectedFiles.html" target="content"><font color=#2E2E2E>Install Selected Files</font></a></div><div><a href="InstallUninstaller.html" target="content"><font color=#2E2E2E>Install Uninstaller</font></a></div><div><a href="InstallUNIXProgramFolder.html" target="content"><font color=#2E2E2E>Install UNIX Program Folder</font></a></div><div><a href="InstallUNIXShortcut.html" target="content"><font color=#2E2E2E>Install UNIX Shortcut</font></a></div><div><a href="InstallWindowsShortcut.html" target="content"><font color=#2E2E2E>Install Windows Shortcut</font></a></div><div><a href="InstallWishBinary.html" target="content"><font color=#2E2E2E>Install Wish Binary</font></a></div><div><a href="InstallWrappedScript.html" target="content"><font color=#2E2E2E>Install Wrapped Script</font></a></div><div><a href="LanguageAPI.html" target="content"><font color=#2E2E2E>LanguageAPI</font></a></div><div><a href="LaunchFile.html" target="content"><font color=#2E2E2E>Launch File</font></a></div><div><a href="LaunchWebBrowser.html" target="content"><font color=#2E2E2E>Launch Web Browser</font></a></div><div><a href="License.html" target="content"><font color=#2E2E2E>License</font></a></div><div><a href="LocateJavaRuntime.html" target="content"><font color=#2E2E2E>Locate Java Runtime</font></a></div><div><a href="LogDebugMessage.html" target="content"><font color=#2E2E2E>Log Debug Message</font></a></div><div><a href="MessageBox.html" target="content"><font color=#2E2E2E>Message Box</font></a></div><div><a href="MessagePanel.html" target="content"><font color=#2E2E2E>Message Panel</font></a></div><div><a href="ModifyObject.html" target="content"><font color=#2E2E2E>Modify Object</font></a></div><div><a href="ModifyWidget.html" target="content"><font color=#2E2E2E>Modify Widget</font></a></div><div><a href="ModifyObject1.html" target="content"><font color=#2E2E2E>ModifyObject</font></a></div><div><a href="MoveForward.html" target="content"><font color=#2E2E2E>Move Forward</font></a></div><div><a href="MoveToPane.html" target="content"><font color=#2E2E2E>Move to Pane</font></a></div><div><a href="ObjectIsActiveCondition.html" target="content"><font color=#2E2E2E>Object Test Condition</font></a></div><div><a href="ObjectTypes.html" target="content"><font color=#2E2E2E>Object Types</font></a></div><div><a href="PackageAndArchiveInformation.html" target="content"><font color=#2E2E2E>Package and Archive Information</font></a></div><div><a href="PackageTestCondition.html" target="content"><font color=#2E2E2E>Package Test Condition</font></a></div><div><a href="PanesAndActions.html" target="content"><font color=#2E2E2E>Panes and Actions</font></a></div><div><a href="PauseInstall.html" target="content"><font color=#2E2E2E>Pause Install</font></a></div><div><a href="PauseWindowsService.html" target="content"><font color=#2E2E2E>Pause Windows Service</font></a></div><div><a href="PlatformCondition.html" target="content"><font color=#2E2E2E>Platform Condition</font></a></div><div><a href="PlatformInformation.html" target="content"><font color=#2E2E2E>Platform Information</font></a></div><div><a href="PopulateComponents.html" target="content"><font color=#2E2E2E>Populate Components</font></a></div><div><a href="PopulateSetupTypes.html" target="content"><font color=#2E2E2E>Populate Setup Types</font></a></div><div><a href="PortTestCondition.html" target="content"><font color=#2E2E2E>Port Test Condition</font></a></div><div><a href="PromptForDirectory.html" target="content"><font color=#2E2E2E>PromptForDirectory</font></a></div><div><a href="PromptForFile.html" target="content"><font color=#2E2E2E>PromptForFile</font></a></div><div><a href="PropertyFileAPI.html" target="content"><font color=#2E2E2E>PropertyFileAPI</font></a></div><div><a href="ReadFileIntoVirtualText.html" target="content"><font color=#2E2E2E>Read File Into Virtual Text</font></a></div><div><a href="ReadInstallInfo.html" target="content"><font color=#2E2E2E>ReadInstallInfo</font></a></div><div><a href="RebootOrShutdownSystem.html" target="content"><font color=#2E2E2E>Reboot or Shutdown System</font></a></div><div><a href="RegisterPackage.html" target="content"><font color=#2E2E2E>Register Package</font></a></div><div><a href="RegisterWindowsLibrary.html" target="content"><font color=#2E2E2E>Register Windows Library</font></a></div><div><a href="RegistryEntryExistsCondition.html" target="content"><font color=#2E2E2E>Registry Test Condition</font></a></div><div><a href="ReleaseNotes.html" target="content"><font color=#2E2E2E>Release Notes</font></a></div><div><a href="RemoveDirectoryFromPath.html" target="content"><font color=#2E2E2E>Remove Directory from Path</font></a></div><div><a href="RemovePaneFromOrder.html" target="content"><font color=#2E2E2E>Remove Pane from Order</font></a></div><div><a href="RemoveWindowsRegistryKey.html" target="content"><font color=#2E2E2E>Remove Windows Registry Key</font></a></div><div><a href="RenameFile.html" target="content"><font color=#2E2E2E>Rename File</font></a></div><div><a href="ReplaceTextInFile.html" target="content"><font color=#2E2E2E>Replace Text in File</font></a></div><div><a href="ResponseFileAPI.html" target="content"><font color=#2E2E2E>ResponseFileAPI</font></a></div><div><a href="RevertWow64Redirection.html" target="content"><font color=#2E2E2E>Revert Wow64 Redirection</font></a></div><div><a href="RollbackInstall.html" target="content"><font color=#2E2E2E>RollbackInstall</font></a></div><div><a href="ScriptCondition.html" target="content"><font color=#2E2E2E>Script Condition</font></a></div><div><a href="SetObjectProperty.html" target="content"><font color=#2E2E2E>Set Object Property</font></a></div><div><a href="SetActiveSetupType.html" target="content"><font color=#2E2E2E>SetActiveSetupType</font></a></div><div><a href="SetExitCode.html" target="content"><font color=#2E2E2E>SetExitCode</font></a></div><div><a href="SetFileTypeEOL.html" target="content"><font color=#2E2E2E>SetFileTypeEOL</font></a></div><div><a href="SetObjectProperty1.html" target="content"><font color=#2E2E2E>SetObjectProperty</font></a></div><div><a href="SetPlatformProperty.html" target="content"><font color=#2E2E2E>SetPlatformProperty</font></a></div><div><a href="SetupTypes.html" target="content"><font color=#2E2E2E>Setup Types</font></a></div><div><a href="SetVirtualText1.html" target="content"><font color=#2E2E2E>SetVirtualText</font></a></div><div><a href="ActionStandardProperties.html" target="content"><font color=#2E2E2E>Standard Action Properties</font></a></div><div><a href="ConditionStandardProperties.html" target="content"><font color=#2E2E2E>Standard Condition Properties</font></a></div><div><a href="StandardProperties.html" target="content"><font color=#2E2E2E>Standard Properties</font></a></div><div><a href="StopInstall.html" target="content"><font color=#2E2E2E>Stop Install</font></a></div><div><a href="StopWindowsService.html" target="content"><font color=#2E2E2E>Stop Windows Service</font></a></div><div><a href="StringEqualCondition.html" target="content"><font color=#2E2E2E>String Equal Condition</font></a></div><div><a href="StringIsCondition.html" target="content"><font color=#2E2E2E>String Is Condition</font></a></div><div><a href="StringMatchCondition.html" target="content"><font color=#2E2E2E>String Match Condition</font></a></div><div><a href="SubstVirtualText.html" target="content"><font color=#2E2E2E>SubstVirtualText</font></a></div><div><a href="TestRun.html" target="content"><font color=#2E2E2E>Test Installer</font></a></div><div><a href="TestUninstaller.html" target="content"><font color=#2E2E2E>Test Uninstaller</font></a></div><div><a href="TextWindow.html" target="content"><font color=#2E2E2E>Text Window</font></a></div><div><a href="UninstallLeftoverFiles.html" target="content"><font color=#2E2E2E>Uninstall Leftover Files</font></a></div><div><a href="UninstallSelectedFiles.html" target="content"><font color=#2E2E2E>Uninstall Selected Files</font></a></div><div><a href="UnpackStoredFile.html" target="content"><font color=#2E2E2E>Unpack Stored File</font></a></div><div><a href="UnregisterWindowsLibrary.html" target="content"><font color=#2E2E2E>Unregister Windows Library</font></a></div><div><a href="UnzipFile.html" target="content"><font color=#2E2E2E>Unzip File</font></a></div><div><a href="URLIsValid.html" target="content"><font color=#2E2E2E>URLIsValid</font></a></div><div><a href="VirtualDirectoryDefinitions.html" target="content"><font color=#2E2E2E>Virtual Directory Definitions</font></a></div><div><a href="VirtualText.html" target="content"><font color=#2E2E2E>Virtual Text</font></a></div><div><a href="VirtualTextDefinitions.html" target="content"><font color=#2E2E2E>Virtual Text Definitions</font></a></div><div><a href="VirtualTextTestCondition.html" target="content"><font color=#2E2E2E>Virtual Text Test Condition</font></a></div><div><a href="VirtualTextAPI.html" target="content"><font color=#2E2E2E>VirtualTextAPI</font></a></div><div><a href="VirtualTextExists.html" target="content"><font color=#2E2E2E>VirtualTextExists</font></a></div><div><a href="Wait.html" target="content"><font color=#2E2E2E>Wait</font></a></div><div><a href="Welcome.html" target="content"><font color=#2E2E2E>Welcome</font></a></div><div><a href="WhatAreActionGroups.html" target="content"><font color=#2E2E2E>What are Action Groups?</font></a></div><div><a href="WhatAreActions.html" target="content"><font color=#2E2E2E>What are Actions?</font></a></div><div><a href="WhatAreConditions.html" target="content"><font color=#2E2E2E>What are Conditions?</font></a></div><div><a href="WhatArePanes.html" target="content"><font color=#2E2E2E>What are Panes?</font></a></div><div><a href="WhatIsTclTk.html" target="content"><font color=#2E2E2E>What is Tcl/Tk?</font></a></div><div><a href="WhatIsTheBuilderAPI.html" target="content"><font color=#2E2E2E>What is the Builder API?</font></a></div><div><a href="WhatIsTheInstallAPI.html" target="content"><font color=#2E2E2E>What is the Install API?</font></a></div><div><a href="WhatIsVirtualText.html" target="content"><font color=#2E2E2E>What is Virtual Text?</font></a></div><div><a href="WriteTextToFile.html" target="content"><font color=#2E2E2E>Write Text to File</font></a></div></font></body></html>
Added docs/html/FHNonscroll.js.












































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//© DevHost Ltd, 2005 v1.6
var type = "IE";

IdentifyBrowser();
window.onload=resizeSplitWndw;
window.onresize=resizeSplitWndw;
window.onbeforeprint=set_to_print;
window.onafterprint=reset_form;
window.onerror = errorHandler;

function resizeSplitWndw()
{
  if (type=="MO") 
  {
    document.getElementById('FHScroll').style.top= document.getElementById('FHNonScroll').offsetHeight;
  }
  //-------------------------------------------------
  if (type=="NN") 
  { 
    document.layers.FHScroll.style.top=document.layers.FHNonScroll.offsetHeight;
  }
  if (type=="OP") 
  { 
    document.all.FHScroll.style.top=document.all.FHNonScroll.offsetHeight;
    document.all.FHNonScroll.style.width= document.body.offsetWidth;
  }
  //-------------------------------------------------
  if (type=="IE") 
  {
    var oNonScroll=document.all.item("FHNonscroll");
    var oScroll=document.all.item("FHScroll");
    if (oScroll ==null) return;
    if (oNonScroll != null)
    document.all.FHNonScroll.style.position= "absolute";
    document.all.FHScroll.style.position= "absolute";
    document.all.FHScroll.style.overflow= "auto";
    document.all.FHScroll.style.height= "100%";
    document.all.FHNonScroll.style.width= document.body.offsetWidth;
    document.all.FHScroll.style.width= document.body.offsetWidth-4;
    document.all.FHScroll.style.top= document.all.FHNonScroll.offsetHeight;
    if (document.body.offsetHeight > document.all.FHNonScroll.offsetHeight)
    document.all.FHScroll.style.height= document.body.offsetHeight - document.all.FHNonScroll.offsetHeight;
    else 
    document.all.FHScroll.style.height=0;
  }
}

function errorHandler() {
  //alert("Error Handled"); 
  //When printing pages that contain mixed elements of hidden paragraphs and links, printing will
  //mistakenly raise an exception when parsing the elements, so we suppress it here.
  return true;
}

function set_to_print()
{
  var i;
  document.all.FHScroll.style.overflow="visible";
  document.all.FHScroll.style.width="100%";
  if (window.FHScroll)document.all.FHScroll.style.height = "auto";
  for (i=0; i < document.all.length; i++)
  {
    if (document.all[i].tagName == "BODY") 
    {
      document.all[i].scroll = "auto";
    }
    if (document.all[i].tagName == "A") 
    {
      document.all[i].outerHTML = "<a href=''>" + document.all[i].innerHTML + "</a>";
    }
  }
}

function reset_form()
{
  document.location.reload();
}

function IdentifyBrowser() 
{
  if (navigator.userAgent.indexOf("Opera")!=-1 && document.getElementById) type="OP";//Opera
  else if (document.all) type="IE";													//Internet Explorer e.g. IE4 upwards
  else if (document.layers) type="NN";													//Netscape Communicator 4
  else if (!document.all && document.getElementById) type="MO";
        //Mozila e.g. Netscape 6 upwards
  else type = "IE";
}

function OpenFileRelativeToCHMFolder(stFileName)
{
  var X, Y, sl, a, ra, link;
  ra = /:/;
  a = location.href.search(ra);
  if (a == 2)
    X = 14;
  else
    X = 7;
  sl = "\\";
  Y = location.href.lastIndexOf(sl) + 1;
  link = 'file:///' + location.href.substring(X, Y) + stFileName;
  location.href = link;
}
Added docs/html/FHSearch.html.




































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- saved from url=(0014)about:internet -->
<html>
<head>
<title>Search</title>
<script language="JavaScript1.3" type="text/javascript" src="FHSearchForm.js"></script>
<style type="text/css"><!-- body{font-size: 10pt; font-family: "Verdana"; color: #2E2E2E;} --></style></head>
<body bgcolor="#D1D1D1">

<!-- Find -->
<form name="jse_Form" onsubmit="search_form(jse_Form);return false">
<input type="text" name="d">
<input type="button" value="Go" onclick="search_form(jse_Form)">
</form>

Type in your search text and press Enter
<P>You can surround exact strings with double-quotes and exclude a string by placing a minus before it.</P>
</body>
</html>
Added docs/html/FHSearch.js.








































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
//© Copyright DevHost Ltd, 2005. All Rights Reserved. http://www.Fast-Help.com
var include_num = 1;
var bold = 1;
var boFTS = 1;
var s = new Array();
s[0] = "Welcome^Welcome.html^InstallJammer is a multiplatform GUI installer and builder designed to be completely cross-platform ...^Welcome^InstallJammer,multiplatform,GUI,installer,builder,designed,completely,cross,platform,function,Windows,most,all,versions,UNIX,with,eventual,support,for,Mac,Using,InstallJammer,You,can,read,through,Getting,Started,learn,little,bit,about,how,start,using,InstallJammer,New,Features,Bug,Fixes,you,upgrading,from,previous,version,InstallJammer,read,through,Release,Notes,learn,about,all,changes,since,last,version,Helping,InstallJammer,Development,InstallJammer,continue,develop,with,help,from,people,like,you,Please,report,any,bugs,that,you,find,let,know,features,that,you,would,like,see,InstallJammer,InstallJammer,always,improving,still,has,bugs,work,out,but,can,only,get,better,with,help,from,you,Below,some,links,that,may,help,you,help,InstallJammer,Homepage,Ask,Question,Report,Bug,Request,New,Feature[$XTITLE$]Welcome[$XTITELEND$][$XKEYS$]Welcome[$XKEYSEND$]`;";
s[1] = "License^License.html^InstallJammer is licensed under the GNU General Public License.SPECIAL EXCEPTION FOR INSTALLERS:...^License^InstallJammer,licensed,under,GNU,General,Public,License,SPECIAL,EXCEPTION,FOR,binary,installkit,InstallJammer,code,that,embedded,each,installer,built,using,code,from,InstallJammer,contains,code,that,falls,under,copyright,terms,GPL,still,apply,code,contained,installers,Hereby,Damon,Courtney,grants,you,special,permission,freely,use,distribute,any,installer,built,with,InstallJammer,including,commercial,ones,without,having,make,available,source,code,InstallJammer,any,code,that,contained,within,your,installer,Any,changes,made,InstallJammer,installkit,source,code,must,still,follow,GPL,license,GNU,GENERAL,PUBLIC,LICENSE,Version,June,1991,Copyright,1989,1991,Free,Software,Foundation,Inc,Franklin,Street,Fifth,Floor,Boston,02110,1301,USA,Everyone,permitted,copy,distribute,verbatim,copies,license,document,but,changing,not,allowed,			,Preamble,licenses,for,most,software,designed,take,away,your,freedom,share,change,contrast,GNU,General,Public,License,intended,guarantee,your,freedom,share,change,free,software,make,sure,software,free,for,all,its,users,General,Public,License,applies,most,Free,Software,Foundation's,software,any,other,program,whose,authors,commit,using,Some,other,Free,Software,Foundation,software,covered,GNU,Lesser,General,Public,License,instead,You,can,apply,your,programs,too,When,speak,free,software,referring,freedom,not,price,General,Public,Licenses,designed,make,sure,that,you,have,freedom,distribute,copies,free,software,charge,for,service,you,wish,that,you,receive,source,code,can,get,you,want,that,you,can,change,software,use,pieces,new,free,programs,that,you,know,you,can,these,things,protect,your,rights,need,make,restrictions,that,forbid,anyone,deny,you,these,rights,ask,you,surrender,rights,These,restrictions,translate,certain,responsibilities,for,you,you,distribute,copies,software,you,modify,For,example,you,distribute,copies,such,program,whether,gratis,for,fee,you,must,give,recipients,all,rights,that,you,have,You,must,make,sure,that,they,too,receive,can,get,source,code,you,must,show,these,terms,they,know,rights,protect,your,rights,with,two,copyright,software,offer,you,license,which,gives,you,legal,permission,copy,distribute,modify,software,Also,for,each,author's,protection,ours,want,make,certain,that,everyone,understands,that,warranty,for,free,software,software,modified,someone,else,passed,want,its,recipients,know,that,what,they,have,not,original,that,any,problems,introduced,others,not,reflect,original,authors',reputations,Finally,any,free,program,threatened,constantly,software,patents,wish,avoid,danger,that,redistributors,free,program,individually,obtain,patent,licenses,effect,making,program,proprietary,prevent,have,made,clear,that,any,patent,must,licensed,for,everyone's,free,use,not,licensed,all,precise,terms,conditions,for,copying,distribution,modification,follow,GNU,GENERAL,PUBLIC,LICENSE,TERMS,CONDITIONS,FOR,COPYING,DISTRIBUTION,MODIFICATION,License,applies,any,program,other,work,which,contains,notice,placed,copyright,holder,saying,may,distributed,under,terms,General,Public,License,Program,below,refers,any,such,program,work,work,based,Program,means,either,Program,any,derivative,work,under,copyright,that,say,work,containing,Program,portion,either,verbatim,with,modifications,translated,into,another,language,Hereinafter,translation,included,without,limitation,term,modification,Each,licensee,addressed,you,Activities,other,than,copying,distribution,modification,not,covered,License,they,outside,its,scope,act,running,Program,not,restricted,output,from,Program,covered,only,its,contents,constitute,work,based,Program,independent,having,been,made,running,Program,Whether,that,true,depends,what,Program,does,You,may,copy,distribute,verbatim,copies,Program's,source,code,you,receive,any,medium,provided,that,you,conspicuously,appropriately,publish,each,copy,appropriate,copyright,notice,disclaimer,warranty,keep,intact,all,notices,that,refer,License,absence,any,warranty,give,any,other,recipients,Program,copy,License,along,with,Program,You,may,charge,fee,for,physical,act,transferring,copy,you,may,your,option,offer,warranty,protection,exchange,for,fee,You,may,modify,your,copy,copies,Program,any,portion,thus,forming,work,based,Program,copy,distribute,such,modifications,work,under,terms,Section,above,provided,that,you,also,meet,all,these,You,must,cause,modified,files,carry,prominent,notices,stating,that,you,changed,files,date,any,change,You,must,cause,any,work,that,you,distribute,publish,that,whole,part,contains,derived,from,Program,any,part,thereof,licensed,whole,charge,all,third,parties,under,terms,License,modified,program,normally,reads,commands,interactively,when,run,you,must,cause,when,started,running,for,such,interactive,use,most,ordinary,way,print,display,announcement,including,appropriate,copyright,notice,notice,that,warranty,else,saying,that,you,provide,warranty,that,users,may,redistribute,program,under,these,conditions,telling,user,how,view,copy,License,Program,itself,interactive,but,does,not,normally,print,such,announcement,your,work,based,Program,not,required,print,announcement,These,requirements,apply,modified,work,whole,identifiable,sections,that,work,not,derived,from,Program,can,reasonably,considered,independent,separate,works,themselves,then,License,its,terms,not,apply,those,sections,when,you,distribute,separate,works,But,when,you,distribute,same,sections,part,whole,which,work,based,Program,distribution,whole,must,terms,License,whose,permissions,for,other,licensees,extend,entire,whole,thus,each,every,part,regardless,who,wrote,Thus,not,intent,section,claim,rights,contest,your,rights,work,written,entirely,you,rather,intent,exercise,right,control,distribution,derivative,collective,works,based,Program,addition,mere,aggregation,another,work,not,based,Program,with,Program,with,work,based,Program,volume,storage,distribution,medium,does,not,bring,other,work,under,scope,License,You,may,copy,distribute,Program,work,based,under,Section,object,code,executable,form,under,terms,Sections,above,provided,that,you,also,one,Accompany,with,complete,corresponding,machine,readable,source,code,which,must,distributed,under,terms,Sections,above,medium,customarily,used,for,software,interchange,Accompany,with,written,offer,valid,for,least,three,years,give,any,third,party,for,charge,more,than,your,cost,physically,performing,source,distribution,complete,machine,readable,copy,corresponding,source,code,distributed,under,terms,Sections,above,medium,customarily,used,for,software,interchange,Accompany,with,information,you,received,offer,distribute,corresponding,source,code,alternative,allowed,only,for,noncommercial,distribution,only,you,received,program,object,code,executable,form,with,such,offer,accord,with,Subsection,above,source,code,for,work,means,preferred,form,work,for,making,modifications,For,executable,work,complete,source,code,means,all,source,code,for,all,modules,contains,plus,any,associated,interface,definition,files,plus,scripts,used,control,compilation,installation,executable,However,special,exception,source,code,distributed,need,not,include,anything,that,normally,distributed,either,source,binary,form,with,major,components,compiler,kernel,operating,system,which,executable,runs,unless,that,component,itself,accompanies,executable,distribution,executable,object,code,made,offering,access,copy,from,designated,place,then,offering,equivalent,access,copy,source,code,from,same,place,counts,distribution,source,code,even,though,third,parties,not,compelled,copy,source,along,with,object,code,You,may,not,copy,modify,sublicense,distribute,Program,except,expressly,provided,under,License,Any,attempt,otherwise,copy,modify,sublicense,distribute,Program,void,automatically,terminate,your,rights,under,License,However,parties,who,have,received,copies,rights,from,you,under,License,not,have,licenses,terminated,long,such,parties,remain,full,compliance,You,not,required,accept,License,since,you,have,not,signed,However,nothing,else,grants,you,permission,modify,distribute,Program,its,derivative,works,These,actions,prohibited,law,you,not,accept,License,Therefore,modifying,distributing,Program,any,work,based,Program,you,indicate,your,acceptance,License,all,its,terms,conditions,for,copying,distributing,modifying,Program,works,based,Each,time,you,redistribute,Program,any,work,based,Program,recipient,automatically,receives,license,from,original,licensor,copy,distribute,modify,Program,subject,these,terms,conditions,You,may,not,impose,any,further,restrictions,recipients',exercise,rights,granted,herein,You,not,responsible,for,enforcing,compliance,third,parties,License,consequence,court,judgment,allegation,patent,infringement,for,any,other,reason,not,limited,patent,issues,conditions,imposed,you,whether,court,order,agreement,otherwise,that,contradict,conditions,License,they,not,excuse,you,from,conditions,License,you,cannot,distribute,satisfy,simultaneously,your,obligations,under,License,any,other,pertinent,obligations,then,consequence,you,may,not,distribute,Program,all,For,example,patent,license,would,not,permit,royalty,free,redistribution,Program,all,those,who,receive,copies,directly,indirectly,through,you,then,only,way,you,could,satisfy,both,License,would,refrain,entirely,from,distribution,Program,any,portion,section,held,invalid,unenforceable,under,any,particular,circumstance,balance,section,intended,apply,section,whole,intended,apply,other,circumstances,not,purpose,section,induce,you,infringe,any,patents,other,property,right,claims,contest,validity,any,such,claims,section,has,sole,purpose,protecting,integrity,free,software,distribution,system,which,implemented,public,license,practices,Many,people,have,made,generous,contributions,wide,range,software,distributed,through,that,system,reliance,consistent,application,that,system,decide,she,willing,distribute,software,through,any,other,system,licensee,cannot,impose,that,choice,section,intended,make,thoroughly,clear,what,believed,consequence,rest,License,distribution,use,Program,restricted,certain,countries,either,patents,copyrighted,interfaces,original,copyright,holder,who,places,Program,under,License,may,add,explicit,geographical,distribution,limitation,excluding,those,countries,that,distribution,permitted,only,among,countries,not,thus,excluded,such,case,License,incorporates,limitation,written,body,License,Free,Software,Foundation,may,publish,revised,new,versions,General,Public,License,from,time,time,Such,new,versions,similar,spirit,present,version,but,may,differ,detail,address,new,problems,concerns,Each,version,given,distinguishing,version,number,Program,specifies,version,number,License,which,applies,any,later,version,you,have,option,following,terms,conditions,either,that,version,any,later,version,published,Free,Software,Foundation,Program,does,not,specify,version,number,License,you,may,choose,any,version,ever,published,Free,Software,Foundation,you,wish,incorporate,parts,Program,into,other,free,programs,whose,distribution,conditions,different,write,author,ask,for,permission,For,software,which,copyrighted,Free,Software,Foundation,write,Free,Software,Foundation,sometimes,make,exceptions,for,decision,guided,two,goals,preserving,free,status,all,derivatives,free,software,promoting,sharing,reuse,software,generally,			,WARRANTY,BECAUSE,PROGRAM,LICENSED,FREE,CHARGE,WARRANTY,FOR,PROGRAM,EXTENT,PERMITTED,APPLICABLE,LAW,EXCEPT,WHEN,OTHERWISE,STATED,WRITING,COPYRIGHT,HOLDERS,OTHER,PARTIES,PROVIDE,PROGRAM,WITHOUT,WARRANTY,ANY,KIND,EITHER,EXPRESSED,IMPLIED,INCLUDING,BUT,NOT,LIMITED,IMPLIED,WARRANTIES,MERCHANTABILITY,FITNESS,FOR,PARTICULAR,PURPOSE,ENTIRE,RISK,QUALITY,PERFORMANCE,PROGRAM,WITH,YOU,SHOULD,PROGRAM,PROVE,DEFECTIVE,YOU,ASSUME,COST,ALL,NECESSARY,SERVICING,REPAIR,CORRECTION,EVENT,UNLESS,REQUIRED,APPLICABLE,LAW,AGREED,WRITING,ANY,COPYRIGHT,HOLDER,ANY,OTHER,PARTY,WHO,MAY,MODIFY,REDISTRIBUTE,PROGRAM,PERMITTED,ABOVE,LIABLE,YOU,FOR,DAMAGES,INCLUDING,ANY,GENERAL,SPECIAL,INCIDENTAL,CONSEQUENTIAL,DAMAGES,ARISING,OUT,USE,INABILITY,USE,PROGRAM,INCLUDING,BUT,NOT,LIMITED,LOSS,DATA,DATA,BEING,RENDERED,INACCURATE,LOSSES,SUSTAINED,YOU,THIRD,PARTIES,FAILURE,PROGRAM,OPERATE,WITH,ANY,OTHER,PROGRAMS,EVEN,SUCH,HOLDER,OTHER,PARTY,HAS,BEEN,ADVISED,POSSIBILITY,SUCH,DAMAGES,END,TERMS,CONDITIONS[$XTITLE$]License[$XTITELEND$][$XKEYS$]License[$XKEYSEND$]`;";
s[2] = "Credits^Credits.html^InstallJammer Multiplatform InstallerWritten by Damon Courtney<damon@installjammer.com>htt...^Credits^InstallJammer,Multiplatform,Installer,Written,Damon,Courtney,<damon@installjammer,com>,installjammer,Credits,InstallJammer,would,not,possible,without,additional,work,many,others,projects,list,means,complete,doesn't,include,any,help,received,from,users,InstallJammer,wonderful,support,Tcl,community,simply,list,projects,that,have,helped,build,InstallJammer,into,what,BWidgets,BWidgets,Team,Tktable,Jeff,Hobbs,TWAPI,Ashok,Nadkarni,TkDND,Georgios,Petasis[$XTITLE$]Credits[$XTITELEND$][$XKEYS$]Credits[$XKEYSEND$]`;";
s[3] = "Release Notes^ReleaseNotes.html^1.2.15 (October 29th, 2010)This release contains minor bug fixes and enhancements.Minor Bu...^Release Notes^October,29th,2010,release,contains,minor,bug,fixes,enhancements,Minor,Bug,Fixes,Fixed,several,issues,uninstall,cleanup,process,Fixed,bug,where,saving,some,projects,could,cause,error,when,reloading,project,file,due,unmatched,braces,project,file,Fixed,bug,Add,Widget,action,where,browse,entry,did,not,properly,fire,event,Fixed,bug,where,nested,action,groups,would,cause,error,when,executing,Fixed,bug,where,Copy,Value,from,right,click,menu,would,copy,blank,value,clear,buffer,Fixed,movement,keys,for,text,widgets,readonly,state,that,they,scroll,properly,Fixed,bug,Uninstall,Selected,Files,action,where,trying,uninstall,file,that,doesn't,exist,would,cause,error,Fixed,bug,building,separate,archives,that,would,cause,fail,some,platforms,Fixed,bug,where,exit,dialog,Linux,was,not,modal,enough,dialog,not,completely,modal,sense,that,people,used,Windows,but,user,shouldn't,able,click,second,time,cause,error,Fixed,bug,where,GetSelectedFiles,API,was,appending,extra,directory,tail,onto,each,directory,object,returned,Fixed,bug,where,non,ASCII,filenames,were,not,supported,installer,could,produce,incompatibility,with,anyone,using,custom,UTF,message,catalog,Fixed,bug,launching,file,explorer,UNIX,with,selected,group,Fixed,bug,dragging,dropping,files,UNIX,with,selected,group,Fixed,bug,with,file,URLs,dropped,from,Nautilus,not,being,decoded,builder,doesn't,recognize,files,with,spaces,because,they,show,%20,Fixed,bug,builder,where,text,would,show,blank,system,language,was,not,language,supported,InstallJammer,Fixed,but,chmod,installkit,startup,UNIX,that,could,cause,error,root,user,owned,installation,Make,sure,install,information,updated,before,redraw,setup,type,description,fixes,bug,where,setup,type,description,that,includes,space,required,would,not,show,properly,because,space,had,not,been,updated,before,text,was,changed,Fixed,hard,coded,error,title,string,condition,failure,popups,Made,default,TempRoot,instead,Removed,hard,coded,directory,not,empty,message,string,Fixed,bug,that,allowed,illegal,characters,installer,executable,name,Remove,symbolic,color,names,from,source,use,hex,RGB,values,instead,Fixed,bug,where,kdesu,longer,worked,under,KDE4,Fixed,bug,where,title,longer,supported,for,konsole,Execute,External,Program,action,Minor,Enhancements,Changed,build,quick,build,keyboard,shortcuts,Control,now,quick,build,Control,Shift,full,build,Changed,menus,reflect,change,Added,Description,field,Windows,Shortcut,action,sets,Comments,field,tooltip,shortcut,created,Windows,Hitting,space,while,viewing,component,tree,during,installation,now,toggle,current,component,Added,new,Show,Hidden,Directories,checkbutton,choose,file,dialog,UNIX,platforms,Added,new,separator,option,PropertyFileAPI,Move,Pane,action,attempts,move,current,pane,it's,already,pane,reload,rerun,its,actions,instead,just,doing,nothing,Made,default,state,text,widgets,readonly,Added,Windows7,<%WindowsPlatform%>,virtual,text,Added,new,Display,Name,property,file,groups,Added,new,GetDisplayName,API,call,Modifying,title,object,now,sets,Alias,that,title,alias,currently,empty,equal,current,title,Added,new,DecodeURL,API,call,Notes[$XTITELEND$][$XKEYS$]Release,Notes[$XKEYSEND$]`;";
s[4] = "1.2.14^1214.html^1.2.14 (September 18th, 2009)This release contains minor bug fixes and enhancements.Minor ...^1.2.14^September,18th,2009,release,contains,minor,bug,fixes,enhancements,Minor,Bug,Fixes,Fixed,bug,where,uninstaller,Windows,would,sometimes,fail,delete,uninstall,exe,which,would,cause,empty,directory,error,Fixed,bug,where,uninstaller,would,pop,error,message,after,finishing,machine,had,host,scripting,disabled,Fixed,bug,where,desktop,icons,were,not,being,created,Linux,x86_64,platform,Fixed,bug,where,desktop,icons,created,when,installing,root,could,not,read,normal,user,Fixed,bug,where,desktop,icons,need,created,with,executable,bit,set,for,some,platforms,window,managers,Fixed,bug,where,clicking,delete,button,virtual,text,tab,would,not,delete,virtual,text,currently,being,edited,Fixed,bug,where,Default,System,Language,property,was,not,being,saved,installer,value,was,ignored,Fixed,display,Polish,language,strings,installer,uninstaller,Fixed,bug,Create,File,Link,action,where,order,link,its,target,were,accidentally,reversed,non,Windows,platforms,Fixed,bug,where,toggling,components,certain,cases,could,cause,error,Fixed,bug,where,attempting,focus,browse,entry,widget,would,focus,nothing,when,should,focus,browse,button,Fixed,bug,where,last,pane,wizard,was,conditional,wizard,could,end,displaying,blank,pane,end,instead,exiting,when,wizard,moved,forward,Fixed,bug,where,editing,long,description,command,line,option,would,fail,error,Fixed,bug,where,writing,out,script,properties,project,files,could,make,end,very,difficult,read,changes,way,object,properties,written,for,anyone,manipulating,project,files,hand,Fixed,bug,where,encrypted,installers,would,not,install,files,correctly,non,Windows,platforms,Fixed,bug,where,Add,Directory,Path,non,Windows,systems,could,mangle,PATH,environment,variable,after,executing,Removed,more,hard,coded,English,strings,from,uninstaller,They,still,require,translation,for,other,languages,but,they're,longer,hard,coded,into,code,Fixed,selection,bug,choose,directory,dialog,Fixed,bug,where,selection,entry,choose,directory,dialog,would,incorrectly,highlight,directory,Fixed,bug,where,builder,would,not,run,propertly,x86_64,Linux,machines,Fixed,bug,where,specifying,password,did,not,encrypt,separate,archives,when,Build,Separate,Archives,mode,Fixed,bug,where,Install,UNIX,Shortcut,action,did,not,offer,Command,Line,Arguments,property,even,though,was,supposed,other,actions,Fix,bug,Execute,External,Program,action,where,terminals,taken,from,TERM,environment,variable,could,fail,because,hard,coded,title,option,Fixed,bug,where,building,Windows,installers,non,Windows,platforms,could,result,symlinks,being,packaged,incorrectly,links,not,followed,files,Fixed,bug,where,version,non,Windows,platforms,would,error,out,Fixed,bug,where,can,create,operator,File,Test,condition,was,reporting,incorrectly,non,Windows,platforms,Fixed,bug,that,removed,hidden,value,for,Window,State,property,Install,Windows,Shortcut,action,Minor,Enhancements,Added,Control,click,virtual,text,table,select,row,for,deletion,without,editing,contents,Added,Shift,click,virtual,text,table,select,multiple,rows,within,table,for,deletion,Added,Czech,translations,thanks,Kamil,Changed,title,default,silent,actions,main,install,action,Copy,Files,pane,better,represent,what,going,when,reading,tree,Added,new,<%InstallStartupDir%>,<%UninstallStartupDir%>,virtual,text,variables,that,contain,directory,installer,was,launched,from,Changed,wording,Yes,buttons,license,pane,They,were,holdover,from,Classic,Wizard,text,doesn't,make,sense,context,new,pane,Added,new,WizardAPI,API,call,Added,new,Description,property,Create,Windows,Service,action,that,allow,action,specify,description,service,being,created,Added,titles,default,console,actions,give,better,idea,what's,going,when,looking,tree,Added,new,SetInstallPassword,API,Made,possible,copy,paste,objects,between,two,different,instances,InstallJammer,Added,new,PropertyFileAPI,API,call,handle,reading,properties,files,Added,new,<%Tolower,string%>,<%Toupper,string%>,virtual,text,Removed,Install,Error,Exit,Setup,hard,coded,English,strings,added,new,virtual,text,English,message,catalog,replace,14[$XTITELEND$][$XKEYS$]1,14[$XKEYSEND$]`;";
s[5] = "1.2.13^1213.html^1.2.13b2 (May 3rd, 2009)This release contains minor bug fixes and enhancements.Minor Bug F...^1.2.13^13b2,May,3rd,2009,release,contains,minor,bug,fixes,enhancements,Minor,Bug,Fixes,Fixed,bug,where,Select,Destination,pane,would,not,properly,substitute,destination,label,when,updating,pane,Installing,UNIX,shortcuts,root,not,install,for,all,users,not,for,root,user,does,not,count,for,desktop,icons,only,for,program,folders,shortcuts,Removed,code,restart,gnome,panel,Gnome,desktops,seems,like,panel,automatically,pick,changes,its,own,now,Fixed,bug,where,default,system,language,was,not,getting,picked,properly,some,Windows,systems,Fixed,bug,with,choose,directory,dialog,Vista,where,was,still,looking,for,Documents,even,though,Vista,just,calls,Documents,Fixed,bug,where,trying,launch,explorer,directory,Vista,would,just,open,explorer,Computer,screen,Fixed,bug,where,tar,zip,archives,did,not,auto,refresh,files,when,Refresh,File,List,Before,Building,preference,was,turned,Fixed,bug,Create,File,Link,action,where,would,fail,UNIX,systems,link,target,did,not,already,exist,remain,requirement,for,Windows,platforms,however,Fixed,bug,Execute,External,Program,action,where,Progressive,Output,Widget,could,not,found,when,action,was,nested,action,group,Cleaned,all,message,catalogs,remove,double,spaces,when,displaying,text,some,panes,These,extra,spaces,were,part,actual,message,catalog,not,bug,installers,Fixed,bug,where,some,actions,like,WriteTextToFile,that,log,files,would,error,out,when,running,inside,uninstaller,Fixed,bug,where,editing,some,text,fields,would,not,cause,project,become,modified,Fixed,bug,where,setting,Windows,file,attributes,non,Windows,platform,would,then,cause,error,during,installation,Fixed,bug,Platform,Condition,where,not,all,platforms,were,available,Fixed,bug,Execute,External,Program,action,where,watching,for,output,Status,virtual,text,could,cause,infinite,loop,error,Fixed,bug,where,Uninstall,Leftover,Files,was,failing,console,installs,Fixed,bug,where,actions,after,Move,Forward,Move,Pane,action,would,still,executed,when,they,should,skipped,Fixed,bug,where,icons,menus,were,not,being,properly,removed,during,uninstall,Linux,platform,Fixed,bug,that,broke,solid,compression,builds,all,platforms,Fixed,bug,where,using,install,password,would,fail,due,missing,function,Fixed,bug,when,running,multiple,installers,closing,child,installer,would,delete,temporary,directory,out,from,under,parent,Fixed,bug,Locate,Java,Runtime,action,where,would,attempt,prompt,user,with,dialog,console,install,For,now,prompt,for,user,console,install,simply,ignored,Fixed,bug,where,Modify,Widget,action,could,end,clearing,text,widget,even,text,was,specified,Fixed,bug,where,file,group's,size,was,not,accurate,when,following,Fixed,bug,where,tar,zip,archives,with,files,would,error,with,big,ugly,error,message,It's,little,more,graceful,now,Fixed,bug,where,upgrade,installers,were,not,being,included,part,original,install,during,uninstall,because,mismatch,registry,info,Fixed,several,bugs,related,installers,running,under,WINE,Installers,uninstallers,should,now,run,successfully,under,WINE,Fixed,bug,Reboot,Shutdown,System,action,for,UNIX,systems,where,time,was,specified,Fixed,bug,uninstall,All,platforms,now,perform,same,uninstall,that,was,previously,reserved,for,Windows,Which,say,that,uninstaller,copied,off,temporary,location,before,executing,that,original,uninstaller,can,deleted,place,Fixed,bug,that,would,affect,launching,installers,that,launch,other,installers,where,child,installer,would,delete,temporary,directory,out,from,under,parent,leaving,parent,error,out,Fixed,bug,where,creating,desktop,shortcuts,Linux,Gnome,desktops,would,fail,desktop,directory,was,not,called,Desktop,non,English,systems,Fixed,bug,where,uninstall,Windows,would,leave,hanging,process,after,exiting,would,cause,problems,when,uninstaller,was,called,from,some,other,program,Fixed,bug,message,dialogs,where,button,window,would,nothing,Fixed,bug,message,dialogs,where,initial,focus,button,was,not,correct,Fixed,bug,where,editing,virtual,text,string,from,editor,would,not,save,when,editor,closed,Fixed,bug,where,Launch,Web,Browser,action,would,not,work,properly,some,versions,Windows,Fixed,bug,where,passing,uninstaller,would,cause,error,Fixed,bug,where,UNIX,permissions,were,being,flipped,builder,Minor,Enhancements,Added,new,VirtualTextAPI,API,call,Added,new,LanguageAPI,API,call,Added,new,Require,Administrator,option,Windows,platform,Added,new,Use,Uncompressed,Binaries,option,Windows,platform,Added,new,RequireAdministratorText,virtual,text,English,message,catalog,message,appear,when,user,doesn't,have,required,administrator,privileges,Added,new,Installkit,property,Install,Wrapped,Script,action,Added,new,ConfigAPI,API,call,configure,internal,settings,Fixed,bug,where,system,language,might,not,get,used,even,when,message,catalog,compiled,into,installer,Added,new,Default,System,Language,install,feature,specify,that,default,language,installing,system,should,used,exists,within,installer's,message,catalog,Otherwise,Default,Language,used,Added,new,permissions,File,Permission,Condition,Added,new,<%ErrorFiles%>,<%ErrorDirs%>,virtual,text,that,set,during,uninstallation,when,fails,remove,files,directories,most,properties,widgets,can,now,specified,<pane>,<widget>,specify,exactly,which,pane,widget,meant,Added,new,Install,UNIX,Program,Folder,action,allow,creating,program,folders,with,more,options,like,icons,Added,new,matches,does,not,match,operators,Platform,Condition,Added,ability,enable,response,files,for,installers,Response,files,let,user,save,responses,from,install,replay,another,install,later,Added,new,Enable,Response,Files,install,feature,true,default,projects,using,version,higher,Added,new,Add,Response,File,Info,action,enable,adding,virtual,text,response,file,when,they,enabled,Made,SelectedComponents,virtual,text,writable,Whenever,virtual,text,changed,overwrite,current,set,selected,components,Added,new,ComponentAPI,API,call,Added,new,CommandLineAPI,API,call,Added,new,ResponseFileAPI,API,call,Added,new,Disable,Revert,Wow64,Redirection,action,disable,Windows,bit,filesystem,redirection,Locate,Java,Runtime,action,now,includes,full,version,number,<%JavaAvailableVersions%>,virtual,text,Added,new,<%JavaVersionMinor%>,that,set,Locate,Java,Runtime,action,Locate,Java,Runtime,action,now,substitutes,virtual,text,properly,search,path,Also,added,some,debugging,see,where,action,looking,for,Java,system,Locate,Java,Runtime,action,now,handles,Java,versions,properly,you,can,use,version,like,0_10,minimum,maximum,Previously,version,after,was,invalid,Added,new,Vendor,UNIX,shortcut,actions,allow,for,shortcuts,grouped,together,under,particular,vendor,makes,easy,for,multiple,installers,create,shortcuts,same,program,folders,Focus,Widget,action,should,now,work,for,built,widgets,well,not,just,ones,added,with,Add,Widget,action,Added,new,Save,Files,property,file,groups,directories,allow,for,finer,grained,access,Save,Only,Toplevel,Directories,project,preference,Added,new,Application,property,Get,Previous,Install,Info,action,Added,new,ReadInstallInfo,API,Added,new,AddInstallInfo,API,Added,new,PreviousInstallIDs,virtual,text,that,set,after,reading,previous,install,info,Added,new,build,log,file,command,line,option,install,builder,Doing,full,build,not,quick,now,automatically,jumps,build,screen,before,build,begins,show,log,Modify,Widget,action,should,now,properly,handle,textboxes,when,modifying,text,property,Added,new,DestroyWidget,API,call,Destroy,Widget,action,can,now,take,list,widgets,separated,InstallDirSuffix,can,now,contain,more,than,single,directory,whole,string,joined,with,InstallDir,anytime,changed,Added,new,Selectable,property,Components,that,false,turn,component,component,tree,into,header,with,check,radio,button,Added,NONE,option,for,buttons,pane,Made,text,language,selection,dialog,part,English,message,catalog,instead,hard,coded,value,13[$XTITELEND$][$XKEYS$]1,13[$XKEYSEND$]`;";
s[6] = "1.2.12^1212.html^1.2.12 (December 2nd, 2008)This is a minor bug fix release.Minor Bug FixesFixed a bug in...^1.2.12^December,2nd,2008,minor,bug,fix,release,Minor,Bug,Fixes,Fixed,bug,URLIsValid,API,Fixed,bug,Windows,installkits,that,was,causing,installers,signed,with,digital,signature,fail,12[$XTITELEND$][$XKEYS$]1,12[$XKEYSEND$]`;";
s[7] = "1.2.11^1211.html^1.2.11 (December 1st, 2008)This release contains minor bug fixes and enhancements.Minor Bu...^1.2.11^December,1st,2008,release,contains,minor,bug,fixes,enhancements,Minor,Bug,Fixes,Fix,bug,uninstaller,that,can,occur,Windows,systems,where,vbs,file,extension,messed,registry,Fixed,bug,Uninstall,Selected,Files,action,that,would,sometimes,occur,when,using,Remove,from,Uninstall,action,Fixed,bug,that,would,only,occur,some,Windows,system,where,permission,denied,error,would,appear,startup,Fixed,bug,where,<%Platform%>,was,not,expanded,name,archive,files,Fixed,bug,where,passing,argument,installer,Windows,would,show,message,box,with,title,Valid,Argument,Fixed,bug,where,double,clicking,check,box,option,tree,would,cause,check,button,toggle,twice,but,command,wouldn't,fire,leaves,some,components,wrong,state,Fixed,bug,where,going,back,forth,between,custom,setup,component,screen,could,leave,components,unknown,state,Minor,Enhancements,Add,Directory,Path,Add,Environment,Variable,now,also,make,same,change,running,installer's,environment,11[$XTITELEND$][$XKEYS$]1,11[$XKEYSEND$]`;";
s[8] = "1.2.10^1210.html^1.2.10 (November 13th, 2008)This release contains minor bug fixes and enhancements.Minor B...^1.2.10^November,13th,2008,release,contains,minor,bug,fixes,enhancements,Minor,Bug,Fixes,Fixed,bug,InstallDrive,virtual,text,defaulting,drive,where,PROGRAM_FILES,located,Fixed,bug,GetWidgetPath,API,where,would,get,path,enclosing,frame,instead,real,widget,widget,was,added,with,label,Fixed,bug,where,required,components,could,unchecked,parent,parent,was,unchecked,Fixed,bug,where,Add,Widget,action,could,executed,from,action,group,with,pane,its,parent,would,cause,bad,window,error,Fixed,bug,Uninstall,Leftover,Files,action,Fixed,bug,where,specifying,Categories,Additional,Arguments,Install,UNIX,Shortcut,action,would,cause,error,instead,working,like,should,Fixed,bug,where,was,impossible,post,message,box,silent,install,Fixed,bug,Launch,Web,Browser,action,where,URL,would,truncate,URL,was,due,Windows',command,line,parsing,rules,new,method,create,URL,shortcut,temp,directory,then,invoke,that,shortcut,launch,browser,Fixed,bug,where,error,messages,command,line,build,were,not,output,stderr,they,should,Fixed,several,bugs,build,zip,tar,files,Fixed,bug,where,silent,install,would,still,show,progress,bar,Fixed,bug,Install,Windows,Shortcut,action,that,would,prevent,from,creating,URL,shortcut,Fixed,bug,Encode,URL,API,entire,URL,was,being,encoded,which,would,percent,encode,hostname,well,query,which,wrong,thing,Fixed,bug,new,split,archives,code,that,was,causing,split,archives,not,work,non,Windows,platforms,Fix,bug,where,larger,installs,would,fail,even,bit,systems,Fixed,bug,where,variables,defined,command,line,were,being,defined,after,control,script,control,script,should,have,access,correct,values,Fixed,bug,where,setting,platform,variables,from,command,line,would,not,set,properly,Passing,DExecutable,for,example,works,now,Fixed,bug,where,default,actions,modify,button,states,License,Copy,Files,panes,were,happening,after,pane,had,been,displayed,which,would,give,user,time,quickly,zip,before,buttons,were,changed,change,only,affects,new,projects,Older,projects,have,modified,fix,bug,Fixed,bug,where,file,installation,would,sometimes,not,reach,100%,Fixed,bug,where,error,during,command,line,build,would,not,exit,with,error,code,Fixed,bug,where,symlink'd,files,were,being,included,installer,instead,link,file,being,created,target,machine,Fixed,bug,where,Move,Pane,could,not,select,pane,from,uninstall,Fixed,bug,where,Move,Forward,Move,Pane,actions,would,still,execute,any,remaining,actions,current,pane,after,moving,forward,Moving,now,means,that,any,actions,after,move,not,executed,Fixed,bug,where,installer,that,specifically,did,not,allow,language,selection,could,still,get,English,system,language,was,such,should,addressed,further,another,version,Fixed,bug,where,Locate,Java,Runtime,action,was,not,accurately,picking,paths,from,Windows,registry,Fixed,bug,where,Add,Directory,Path,would,fail,for,cshrc,when,variable,didn't,already,exist,Fixed,bug,where,language,chosen,for,installer,was,not,being,propagated,uninstaller,correctly,Fixed,bug,where,editing,text,properties,for,languages,with,space,name,like,Brazilian,Portuguese,failed,save,edited,text,correctly,Fixed,bug,that,would,sometimes,cause,error,builder,after,deleting,object,then,coming,back,that,tab,Fixed,bug,Install,Program,Folder,Shortcut,action,where,specifying,subfolder,folder,name,would,ignored,icon,would,just,installed,root,program,folder,Fixed,bug,where,error,during,file,installation,would,show,error,popup,then,just,freeze,with,way,cancel,installer,error,now,returned,stack,Install,Selected,Files,action,where,can,handled,also,adds,new,<%InstallErrors%>,virtual,text,that,contains,error,message,from,unpack,process,Fixed,bug,Add,Environment,Variable,action,Windows,where,path,registry,would,not,get,expanded,for,some,reason,Fixed,bug,where,uninstall,process,would,error,directories,were,being,removed,Fixed,bug,where,building,from,command,line,would,still,include,debug,options,even,when,building,for,release,thanks,John,Bratteli,for,fix,Fixed,bug,where,uninstall,could,exit,with,error,cleanup,when,being,executed,from,another,uninstall,Fixed,bug,where,Windows,exe,information,was,not,being,substituted,for,virtual,text,when,installer,built,Fixed,bug,where,editing,Install,Version,would,cause,roll,back,each,time,Fixed,bug,where,version,variables,derived,from,InstallVersion,were,not,being,set,properly,Passing,version,information,command,line,should,also,work,expected,now,Minor,Enhancements,Added,new,Follow,File,Links,property,file,groups,property,tells,InstallJammer,whether,include,file,links,files,links,when,building,Added,new,RollbackInstall,API,Removed,AIX,FreeBSD,FreeBSD,HPUX,builder,platforms,does,not,mean,these,platforms,longer,supported,means,they,longer,supported,GUI,builder,platforms,They,also,not,support,LZMA,compression,when,building,these,platforms,Added,new,CopyObject,API,call,Added,new,Encoding,property,Replace,Text,File,Write,Text,File,actions,Editable,text,widgets,now,tab,next,widget,when,hitting,Tab,instead,inserting,tab,text,box,Control,Tab,can,used,insert,tab,it's,really,necessary,Added,new,Append,Text,Widget,action,Added,new,SetExitCode,API,Added,new,Exit,Code,property,Exit,action,special,platforms,tar,zip,now,acceptable,platforms,enable,tar,zip,archive,targets,Added,new,Build,Separate,Archives,property,all,platforms,property,allows,installers,built,with,files,being,separate,archives,that,mounted,startup,means,that,installers,longer,one,single,executable,but,makes,possible,avoid,some,size,limitations,bit,platforms,Added,new,progress,bar,for,console,installs,new,Show,Console,Progress,property,was,added,Install,Selected,Files,action,which,enabled,default,Added,new,Clear,Progressive,Widget,property,Execute,External,Program,action,specify,whether,progressive,output,widget,should,cleared,before,program,exits,default,Yes,which,was,previous,behavior,Added,new,Install,Executable,Description,property,Windows,that,used,File,Description,exe,properties,defaults,what,has,always,<%AppName%>,<%Version%>,Setup,10[$XTITELEND$][$XKEYS$]1,10[$XKEYSEND$]`;";
s[9] = "1.2.10b1^1210b1.html^1.2.10b1 (October 16th, 2008)This release contains minor bug fixes and enhancements.Minor ...^1.2.10b1^10b1,October,16th,2008,release,contains,minor,bug,fixes,enhancements,Minor,Bug,Fixes,Fixed,bug,where,default,actions,modify,button,states,License,Copy,Files,panes,were,happening,after,pane,had,been,displayed,which,would,give,user,time,quickly,zip,before,buttons,were,changed,change,only,affects,new,projects,Older,projects,have,modified,fix,bug,Fixed,bug,where,file,installation,would,sometimes,not,reach,100%,Fixed,bug,where,error,during,command,line,build,would,not,exit,with,error,code,Fixed,bug,where,symlink'd,files,were,being,included,installer,instead,link,file,being,created,target,machine,Fixed,bug,where,Move,Pane,could,not,select,pane,from,uninstall,Fixed,bug,where,Move,Forward,Move,Pane,actions,would,still,execute,any,remaining,actions,current,pane,after,moving,forward,Moving,now,means,that,any,actions,after,move,not,executed,Fixed,bug,where,installer,that,specifically,did,not,allow,language,selection,could,still,get,English,system,language,was,such,should,addressed,further,another,version,Fixed,bug,where,Locate,Java,Runtime,action,was,not,accurately,picking,paths,from,Windows,registry,Fixed,bug,where,Add,Directory,Path,would,fail,for,cshrc,when,variable,didn't,already,exist,Fixed,bug,where,language,chosen,for,installer,was,not,being,propagated,uninstaller,correctly,Fixed,bug,where,editing,text,properties,for,languages,with,space,name,like,Brazilian,Portuguese,failed,save,edited,text,correctly,Fixed,bug,that,would,sometimes,cause,error,builder,after,deleting,object,then,coming,back,that,tab,Fixed,bug,Install,Program,Folder,Shortcut,action,where,specifying,subfolder,folder,name,would,ignored,icon,would,just,installed,root,program,folder,Fixed,bug,where,error,during,file,installation,would,show,error,popup,then,just,freeze,with,way,cancel,installer,error,now,returned,stack,Install,Selected,Files,action,where,can,handled,also,adds,new,<%InstallErrors%>,virtual,text,that,contains,error,message,from,unpack,process,Fixed,bug,Add,Environment,Variable,action,Windows,where,path,registry,would,not,get,expanded,for,some,reason,Fixed,bug,where,uninstall,process,would,error,directories,were,being,removed,Fixed,bug,where,building,from,command,line,would,still,include,debug,options,even,when,building,for,release,thanks,John,Bratteli,for,fix,Fixed,bug,where,uninstall,could,exit,with,error,cleanup,when,being,executed,from,another,uninstall,Fixed,bug,where,Windows,exe,information,was,not,being,substituted,for,virtual,text,when,installer,built,Fixed,bug,where,editing,Install,Version,would,cause,roll,back,each,time,Fixed,bug,where,version,variables,derived,from,InstallVersion,were,not,being,set,properly,Passing,version,information,command,line,should,also,work,expected,now,Fixed,bug,introduced,where,install,registry,would,not,get,cleaned,properly,Fixed,bug,where,cleaning,canceled,install,could,cause,errors,freeze,installer,under,certain,conditions,Fixed,bug,where,uninstaller,would,sometimes,report,that,directory,could,not,removed,because,was,not,empty,when,actually,was,fix,now,means,that,directories,not,necessarily,removed,same,order,they,were,installed,Fix,possible,error,case,when,attempting,set,file,permissions,file,that,doesn't,exist,Fixed,bug,where,stopping,install,might,still,try,execute,some,further,code,after,things,had,stopped,Fixed,bug,where,error,action,would,not,get,propagated,show,error,message,Fixed,bug,where,message,box,uninstaller,could,fail,hang,without,error,Fixed,bug,where,uninstall,that,did,not,have,permissions,would,attempt,lot,things,that,just,weren't,possible,uninstall,should,fail,gracefully,now,give,user,proper,error,messages,Minor,Enhancements,Added,new,Build,Separate,Archives,property,all,platforms,property,allows,installers,built,with,files,being,separate,archives,that,mounted,startup,means,that,installers,longer,one,single,executable,but,makes,possible,avoid,some,size,limitations,bit,platforms,Added,new,progress,bar,for,console,installs,new,Show,Console,Progress,property,was,added,Install,Selected,Files,action,which,enabled,default,Added,new,Clear,Progressive,Widget,property,Execute,External,Program,action,specify,whether,progressive,output,widget,should,cleared,before,program,exits,default,Yes,which,was,previous,behavior,Added,new,Install,Executable,Description,property,Windows,that,used,File,Description,exe,properties,defaults,what,has,always,<%AppName%>,<%Version%>,Setup,10b1[$XTITELEND$][$XKEYS$]1,10b1[$XKEYSEND$]`;";
s[10] = "1.2.9^129.html^1.2.9 (August 11th, 2008)This is a minor bug fix release.Minor Bug FixesFixed a bug intr...^1.2.9^August,11th,2008,minor,bug,fix,release,Minor,Bug,Fixes,Fixed,bug,introduced,where,install,registry,would,not,get,cleaned,properly,Fixed,bug,where,cleaning,canceled,install,could,cause,errors,freeze,installer,under,certain,conditions,Fixed,bug,where,uninstaller,would,sometimes,report,that,directory,could,not,removed,because,was,not,empty,when,actually,was,fix,now,means,that,directories,not,necessarily,removed,same,order,they,were,installed,Fix,possible,error,case,when,attempting,set,file,permissions,file,that,doesn't,exist,Fixed,bug,where,stopping,install,might,still,try,execute,some,further,code,after,things,had,stopped,Fixed,bug,where,error,action,would,not,get,propagated,show,error,message,Fixed,bug,where,message,box,uninstaller,could,fail,hang,without,error,Fixed,bug,where,uninstall,that,did,not,have,permissions,would,attempt,lot,things,that,just,weren't,possible,uninstall,should,fail,gracefully,now,give,user,proper,error,messages,Fix,bug,where,Display,Name,property,was,being,ignored,Create,Windows,Service,action,9[$XTITELEND$][$XKEYS$]1,9[$XKEYSEND$]`;";
s[11] = "1.2.8^128.html^1.2.8 (August 3rd, 2008)This is a minor bug fix release.Minor Bug FixesFixed a bug where...^1.2.8^August,3rd,2008,minor,bug,fix,release,Minor,Bug,Fixes,Fixed,bug,where,loading,corrupted,preferences,file,would,cause,crash,corrupted,preferences,file,should,just,deleted,All,calls,external,stty,command,now,wrapped,catch,prevent,failures,doesn't,mean,that,stty,won't,fail,just,means,that,InstallJammer,won't,fail,result,could,mean,that,some,console,actions,not,work,expected,some,systems,but,errors,seem,very,limited,small,number,machines,Fixed,bug,where,operator,for,conditions,was,not,propagated,temporary,objects,created,during,execution,Fix,bug,where,selecting,single,file,multi,select,file,chooser,would,fail,file,selected,had,space,path,Fixed,bug,where,space,command,line,UNIX,shortcut,would,fail,because,filename,wasn't,properly,quoted,Double,quotes,now,added,around,command,with,spaces,before,writing,out,shortcut,file,Fixed,bug,where,duplicate,directories,could,show,file,groups,Fixed,bug,introduced,last,release,Files,Write,Text,File,that,relative,made,relative,install,dir,docs,correctly,say,Fixed,bug,where,empty,pattern,some,file,actions,would,return,install,directory,Fixed,bug,where,editing,virtual,text,can,sometimes,cause,error,Fixed,bug,where,installing,wrapped,script,fails,substitute,virtual,text,Windows,version,information,Fixed,bug,where,Write,Text,File,paths,were,relative,current,directory,instead,installdir,Value,property,was,accidentally,removed,for,several,widget,types,Add,Widget,action,properties,frame,8[$XTITELEND$][$XKEYS$]1,8[$XKEYSEND$]`;";
s[12] = "1.2.7^127.html^1.2.7 (July 7th, 2008)This release contains major bug fixes and enhancements.Major Bug Fix...^1.2.7^July,7th,2008,release,contains,major,bug,fixes,enhancements,Major,Bug,Fixes,Fix,nasty,bug,where,clicking,File,New,create,new,project,does,not,close,any,open,project,instead,overwrite,open,project,blow,away,Minor,Bug,Fixes,Fixed,bug,where,moving,Add,Widget,action,another,pane,wouldn't,actually,change,its,preview,parent,clicking,Preview,Pane,action,would,preview,its,old,pane,Fixed,bug,where,building,uninstaller,some,systems,would,build,uninstall,that,fails,GUI,mode,Fixed,bug,where,uninstall,could,delete,Install,Dir,even,installer,was,not,one,who,created,Fixed,bug,where,Setup,Actions,could,error,checking,conditions,Fixed,bug,where,executing,action,with,alias,could,end,deleting,alias,which,would,cause,subsequent,executions,that,action,alias,fail,Fixed,bug,where,new,project,wizard,dialog,was,not,modal,Fixed,bug,where,configuring,some,install,uninstall,mode,that,did,not,exist,would,cause,error,install,Each,now,use,standard,mode,given,mode,bogus,Fixed,bug,where,building,from,command,line,would,expose,Install,Password,Install,Password,pane,during,installation,Fixed,bug,order,UNIX,file,permissions,checkbuttons,were,correct,order,but,code,was,not,picking,permissions,correct,order,read,execute,bits,were,flipped,Minor,Enhancements,Reworked,Add,Widget,action's,properties,page,separate,type,specific,properties,into,Advanced,Properties,tab,with,standard,widget,properties,under,Widget,Properties,tab,Added,new,File,Types,property,Add,Widget,action,for,browse,entry,widgets,Added,new,combobox,widget,type,Add,Widget,action,Added,new,Separator,property,Add,Directory,Path,action,Added,new,Separator,property,Remove,Directory,from,Path,action,Added,new,Normalize,Paths,property,Add,Directory,Path,action,Set,correct,default,cancel,buttons,for,standard,message,dialogs,Added,new,Preserve,Windows,File,Attributes,project,preference,7[$XTITELEND$][$XKEYS$]1,7[$XKEYSEND$]`;";
s[13] = "1.2.6^126.html^1.2.6 (June 22nd, 2008)This release contains minor bug fixes and enhancements.Minor Bug Fi...^1.2.6^June,22nd,2008,release,contains,minor,bug,fixes,enhancements,Minor,Bug,Fixes,Fix,bug,where,modified,files,don't,get,updated,unpack,process,changes,file,objects,never,get,noticed,when,unpacked,Fixed,bug,classic,wizard,init,that,would,cause,fail,Fixed,missing,quote,Dutch,translations,for,Classic,Wizard,that,would,cause,error,when,creating,new,project,with,theme,Fix,bug,where,using,image,path,can,cause,image,get,lost,runtime,Fixed,nasty,little,bug,where,File,Update,Method,was,not,being,respected,for,files,being,installed,would,cause,things,like,date,checks,fail,overwrite,modified,existing,files,Fixed,bug,where,canceling,during,installation,would,sometimes,cause,process,freeze,until,killed,Fixed,bug,where,canceling,during,installation,could,cause,error,because,unpack,proceeds,tried,update,file,that,wasn't,installed,Committed,correct,version,LZMA,library,Windows,fix,issues,with,building,installers,using,LZMA,compression,Windows,Modernized,choose,directory,dialog,label,showing,directory,gone,entry,now,reflects,entire,folder,path,entire,path,now,checked,for,valid,characters,before,closing,dialog,Fixed,bug,that,caused,integer,overflows,diskspace,calculations,non,Windows,platforms,Fixed,bug,where,errors,could,cause,errors,with,install,title,text,Fixed,bug,where,changing,language,would,not,update,install,title,with,appropriate,title,for,new,language,Several,fixes,dialog,transient,parent,handling,some,new,variables,control,native,dialogs,Fix,bug,bgerror,handler,Fix,bug,that,causes,error,message,when,building,with,files,Removed,dummy,test,for,Readma,panes,that,they,don't,display,wrong,information,language,other,than,English,Fixed,bug,where,various,move,wizard,actions,would,always,move,step,extra,because,wizard,was,not,noticing,that,actions,had,moved,forward,Fixed,bug,where,not,all,languages,would,appear,choices,builder,Fixed,bug,where,opening,condition,editor,could,cause,copy,paste,actions,not,work,anymore,Fixed,typo,<%FileGroup%>,virtual,text,that,caused,error,Fixed,bug,Execute,External,Program,where,using,progressive,output,would,not,accurately,set,exit,status,error,Fixed,bug,SetActiveSetupType,API,where,was,not,repopulating,components,correctly,Fixed,bug,where,Unpack,Stored,File,action,would,create,original,install,directory,for,packed,file,mistake,Fixed,bug,Execute,Script,action,where,returning,value,would,result,error,Fixed,bug,that,would,not,allow,multiple,directories,with,same,name,exist,file,group,Made,builds,more,robust,when,hit,unexpected,errors,errors,should,now,correctly,build,log,builder,should,back,known,state,that,build,can,tried,again,Fixed,bug,where,multiple,channels,were,opened,debug,log,Fixed,bug,shortcut,actions,where,setting,Command,Line,Properties,did,not,propagate,UNIX,platforms,Fixed,bug,where,passing,temp,command,line,would,not,actually,set,Temp,virtual,text,Fixed,bug,where,attempting,paste,object,with,conditions,would,cause,error,Fixed,several,bugs,with,message,boxes,non,Windows,platforms,Fixed,bug,inconsistency,with,SpaceAvailable,virtual,text,non,Windows,platforms,Fixed,bug,where,deleting,objects,from,system,would,not,remove,all,virtual,text,from,project,file,Fixed,bug,where,opening,project,from,right,click,menu,project,list,would,result,error,Fixed,bug,Windows,Fixed,bug,where,using,tk_getOpenFile,would,error,non,Windows,platforms,Fixed,several,bugs,relating,match,any,conditions,Fixed,bug,where,opening,choose,directory,dialog,from,Windows,network,share,would,error,out,Removed,entry,box,choose,directory,dialog,Make,New,Folder,sufficient,for,specifying,folder,name,entry,was,just,confusing,Fixed,several,bugs,between,setting,Aliases,objects,title,component,tree,Fixed,bug,that,caused,Setup,Actions,group,never,actually,execute,Fixed,bug,Windows,Fix,small,bug,for,command,line,builds,Fix,bug,installers,with,non,ASCII,characters,Fixed,bug,where,condition,failure,messages,would,pop,wrong,place,some,systems,Fixed,bug,where,symlink'd,files,UNIX,were,being,truncated,once,installed,Windows,Fixed,bug,where,symlink'd,directory,would,end,creating,recursive,symlink,target,system,during,installation,Fixed,bug,Modify,Widget,action,where,parent,could,not,determined,action,was,attached,checkbutton,something,else,Minor,Enhancements,Added,more,functionality,debugging,command,allow,for,specifying,whether,you,want,debug,console,file,both,Added,new,Validate,Entry,property,Add,Widget,action,allow,entry,widgets,specify,action,that,executed,when,certain,events,happen,Install,Windows,Shortcut,now,use,TWAPI,its,method,creating,shortcut,when,available,fix,problems,many,people,having,installing,shortcuts,Asian,character,sets,Windows,Added,encoding,option,LoadMessageCatalog,API,Added,ability,specify,configuration,options,top,message,catalog,file,form,key,value,pairs,encoding,utf,etc,Added,new,All,language,text,fields,that,set,all,languages,with,same,message,when,used,When,retrieving,text,for,All,language,text,only,retrieved,all,languages,have,same,text,Otherwise,text,blank,Added,link,Help,menu,Support,Forums,Adding,Russian,translations,thanks,Stanislav,Borutsky,order,Before,Pane,Displayed,actions,conditions,has,been,reversed,Previously,actions,would,execute,first,but,opposite,way,every,other,check,works,conditions,now,checked,before,pane,displayed,they,fail,wizard,move,forward,without,ever,executing,actions,Added,new,AddLanguage,API,call,Added,new,PromptForDirectoryNewFolderText,virtual,text,English,message,catalog,default,text,for,Make,New,Folder,button,Choose,Directory,dialog,Translations,added,they,become,available,Added,new,object,option,SetVirtualText,API,allows,for,setting,virtual,text,objects,like,panes,actions,Added,new,LoadMessageCatalog,API,Added,new,powerful,FindObjects,API,for,locating,just,about,anything,system,system,default,language,now,used,default,language,installer,supported,installer,does,not,include,language,for,user's,system,Default,Language,used,its,place,Added,new,Editor,external,program,preference,specify,editor,use,when,editing,multi,line,text,InstallJammer,create,temporary,file,execute,selected,editor,watch,for,changes,file,propagate,back,into,project,enabled,Save,button,for,projects,With,new,Duplicate,Project,option,shouldn't,nearly,confusing,before,Added,check,when,saving,see,project,file,writable,it's,not,InstallJammer,can,attempt,make,file,writable,before,saving,user's,request,Added,new,Watch,Virtual,Text,property,allow,matching,patterns,without,actual,virtual,text,variable,pattern,Regular,expressions,with,less,than,two,sub,match,patterns,use,variable,default,Added,new,Include,TWAPI,property,Install,Wrapped,Script,action,allows,wrapped,scripts,target,system,include,TWAPI,extension,Windows,platforms,script,automatically,modified,with,small,header,load,TWAPI,extension,automatically,Added,ability,specify,images,installer,runtime,Image,properties,can,now,contain,file,build,system,file,target,system,Alias,file,stored,within,installer,Added,new,Command,Line,Actions,group,that,replaces,Setup,Actions,group,terms,location,Command,Line,Actions,group,executes,before,command,line,options,have,been,parsed,Setup,Actions,group,now,executes,after,command,line,options,have,been,parsed,Added,new,Test,Component,property,Panes,Actions,Conditions,property,tells,installer,whether,given,component,should,executed,when,installer,run,test,mode,allows,disabling,things,like,license,panels,other,annoying,things,when,developer,testing,Changed,Test,Component,feature,Include,with,more,options,than,just,Yes,Added,new,test,without,installing,command,line,build,option,pass,test,option,installer,when,testing,Made,legal,pass,directory,command,line,builder,figure,out,which,project,file,directory,use,can,When,project,converted,new,version,now,automatically,saved,backup,made,previous,project,file,Added,new,Wizard,Height,Wizard,Width,properties,Install,Features,section,These,allow,developer,alter,size,wizard,during,installation,Added,new,Default,Directory,Location,Project,Preferences,property,set,specifies,Location,use,for,all,files,directories,that,direct,descendants,file,group,own,Location,not,set,SetVirtualText,API,now,recognizes,update,actions,commands,language,specific,virtual,text,allows,tracking,changes,language,text,SetVirtualText,API's,language,option,now,accepts,language,code,full,language,name,English,etc,title,installer,wizard,now,specified,InstallTitleText,virtual,text,Both,update,automatically,anytime,virtual,text,changes,Windows,command,line,builds,now,done,synchronously,through,new,installjamemr,com,binary,better,allow,scripting,builds,Windows,platform,Added,glob,argument,Windows,only,currently,Installers,now,focus,Next,button,default,when,moving,panes,When,editing,property,clicking,away,from,property,now,auto,save,property,You,longer,have,hit,Return,save,change,may,cause,some,problems,with,errors,properties,Added,new,Require,Response,property,Console,Get,User,Input,action,says,that,user,cannot,provide,empty,response,must,give,something,Added,Package,Databases,property,Register,Package,action,allows,developer,specify,that,they,only,want,support,RPM,DPKG,all,package,managers,All,default,for,backward,compatibility,6[$XTITELEND$][$XKEYS$]1,6[$XKEYSEND$]`;";
s[14] = "1.2.5^125.html^1.2.5 (February 5th, 2008)This release contains minor bug fixes and enhancements.Minor Bug...^^February,5th,2008,release,contains,minor,bug,fixes,enhancements,Minor,Bug,Fixes,Open,Save,project,files,with,utf,encoding,that,non,ASCII,text,automatically,translated,made,correct,with,each,load,save,Fixed,bug,where,copying,pasting,object,would,miss,text,properties,Fixed,bug,Windows,Service,Test,condition,where,condition,would,error,out,service,did,not,exist,Fixed,bug,Modify,Widget,action,that,didn't,handle,framed,widgets,Fixed,bug,Focus,Widget,action,where,didn't,handle,widgets,embedded,frames,Minor,Enhancements,Added,new,Size,property,Components,Added,new,Size,property,File,Groups,Added,new,Display,Name,property,Components,Added,new,Display,Name,property,Setup,Types,Added,new,Encoding,property,Read,File,Into,Virtual,Text,action,Added,new,Register,Windows,Library,action,Added,new,Unregister,Windows,Library,action,5[$XTITELEND$][$XKEYS$]1,5[$XKEYSEND$]`;";
s[15] = "1.2.4^124.html^1.2.4 (January 13rd, 2008)This release contains minor bug fixes and enhancements.Minor Bug...^1.2.4^January,13rd,2008,release,contains,minor,bug,fixes,enhancements,Minor,Bug,Fixes,Fixed,some,minor,bugs,Choose,Directory,dialog,Added,check,for,illegal,characters,directory,name,Fixed,bug,keyboard,navigation,choose,directory,dialog,Fixed,bug,Modify,Widget,where,modifying,existing,text,properties,was,not,modifying,text,properly,Fixed,bug,where,populating,components,with,radiobuttons,where,button,was,checked,would,make,all,checked,Reading,project,files,longer,assumes,UTF,encoding,Fixed,bug,where,WINDOWS,virtual,text,was,being,reported,incorrectly,some,systems,Despite,better,judgment,we'll,trust,environment,variables,Symbolic,links,now,created,using,system,'ln,built,Tcl,'file,link',command,seems,poorly,thought,out,Removed,dummy,license,text,from,all,but,English,translations,that,single,license,display,correctly,all,languages,Fixed,bug,where,buttons,new,project,wizard,would,sometimes,not,appear,correctly,Minor,Enhancements,Read,File,Into,Virtual,Text,now,reads,files,text,instead,binary,default,Added,new,Remove,From,Uninstall,action,Added,new,actions,deal,with,Windows,services,Added,new,Windows,Service,Test,condition,for,testing,Windows,services,Installs,now,built,entirely,temporary,file,only,renamed,final,location,once,build,has,completely,successfully,means,that,broken,builds,not,overwrite,good,installers,that,area,already,build,fails,with,errors,now,reported,having,failed,instead,completed,files,being,packed,now,shown,full,paths,instead,filenames,makes,easier,identify,files,within,build,expense,some,clutter,Building,solid,archives,now,shows,packing,log,messages,Added,new,debugging,command,turn,debugging,off,more,easily,from,console,well,log,debug,information,file,Browsing,for,directory,now,initialize,current,directory,exists,Checking,conditions,can,now,have,boolean,instead,just,always,being,Added,ability,specify,that,conditions,should,matched,with,Match,all,following,Match,any,following,Added,Build,Failure,project,preference,tell,InstallJammer,how,handle,missing,files,when,building,from,GUI,Added,new,ExecuteAction,API,call,Added,Dutch,translations,thanks,Jethro,Borsje,Added,Italian,translations,thanks,LukenShiro,Added,Hungarian,translations,thanks,Nagy,Istvan,4[$XTITELEND$][$XKEYS$]1,4[$XKEYSEND$]`;";
s[16] = "1.2.3^123.html^1.2.3 (October 26th, 2007)This is a minor bug fix release.Minor Bug FixesFixed a typo Ad...^1.2.3^October,26th,2007,minor,bug,fix,release,Minor,Bug,Fixes,Fixed,typo,Add,Windows,Registry,action,Fixed,bug,Alias,handling,code,that,caused,new,projects,fail,with,error,saying,Install,Actions,could,not,found,Fixed,bug,that,causes,multiple,projects,loaded,same,session,build,output,into,wrong,directories,3[$XTITELEND$][$XKEYS$]1,3[$XKEYSEND$]`;";
s[17] = "1.2.2^122.html^1.2.2 (October 25th, 2007)This is a minor bug fix release.Minor Bug FixesFixed a bug o...^1.2.2^October,25th,2007,minor,bug,fix,release,Minor,Bug,Fixes,Fixed,bug,UNIX,platforms,where,creating,directory,that,isn't,writable,would,cause,rest,install,fail,when,tried,write,into,that,directory,Directory,permissions,now,set,after,all,files,have,been,installed,Fixed,typo,Uninstall,Selected,Files,that,would,cause,failure,when,restoring,registry,value,Windows,#1819503],Fixed,typo,that,would,cause,Launch,Web,Browser,actions,fail,#1819487][$XTITLE$]1,2[$XTITELEND$][$XKEYS$]1,2[$XKEYSEND$]`;";
s[18] = "1.2.1^121.html^1.2.1 (October 23rd, 2007)This release contains minor bug fixes and enhancements.A note on...^1.2.1^October,23rd,2007,release,contains,minor,bug,fixes,enhancements,note,command,line,changes,command,line,parsing,was,changed,release,has,caused,bit,pain,for,some,users,would,recommend,reading,help,page,command,line,but,long,short,that,you,building,from,command,line,safest,bet,make,build,last,switch,before,your,project,file,name,Some,new,command,line,options,were,added,release,urge,you,read,documentation,learn,uses,but,note,about,build,being,last,important,It's,not,required,but,you're,going,get,into,lot,less,trouble,you,heed,advice,Minor,Enhancements,Added,official,exception,GPL,license,for,installers,See,License,for,details,Added,new,Rename,Project,option,for,projects,Added,new,Duplicate,Project,option,for,projects,Made,Delete,Project,lot,safer,made,message,dialogs,clearer,what,about,deleted,Removed,Save,option,from,File,menu,only,caused,confusion,Use,Duplicate,Project,instead,Made,New,option,File,menu,create,new,project,with,all,defaults,Added,new,New,Project,Wizard,option,under,File,menu,create,new,project,with,existing,wizard,Added,some,debug,output,uninstall,process,cleanup,Minor,Bug,Fixes,Updated,FreeBSD,binaries,They,were,missed,last,release,Fixed,bug,that,would,cause,command,line,builds,fail,they,discovered,new,file,before,building,Fixed,bug,where,Target,Filename,property,files,was,being,ignored,Fixed,bug,where,project,that,needed,conversion,that,was,built,from,command,line,would,fail,with,error,Fixed,typo,that,caused,Add,Windows,Registry,Key,action,disappear,from,last,release,Fixed,bug,where,Add,Uninstall,action,that,added,directory,forcefully,removed,wasn't,actually,being,forcefully,removed,Fixed,missing,option,bug,Launch,Web,Browser,1[$XTITELEND$][$XKEYS$]1,1[$XKEYSEND$]`;";
s[19] = "1.2^12.html^1.2 (October 21st, 2007)This release contains mostly minor bug fixes and enhancements, but some ...^1.2^October,21st,2007,release,contains,mostly,minor,bug,fixes,enhancements,but,some,enhancements,may,cause,incompatibilties,with,previous,behavior,They,listed,first,Possible,Incompatible,Changes,command,line,parsing,routines,were,rewritten,allows,for,spaces,command,line,interpreted,correctly,being,part,argument,means,that,some,logic,command,line,parser,was,changed,may,cause,problems,for,some,command,lines,Generally,long,last,argument,before,project,file,name,all,should,well,good,practice,anyway,since,denotes,exactly,where,arguments,end,where,file,name,begins,Virtual,text,values,longer,automatically,substituted,for,boolean,values,means,that,you,were,previously,counting,InstallJammer,turn,Yes,into,into,for,you,that,behavior,now,incompatible,You,really,should,using,String,condition,check,for,true,false,because,always,correct,matter,what,your,true,false,value,you,were,relying,behavior,for,your,variables,I'm,sorry,that,has,change,behavior,causes,more,problems,than,solves,lot,more,confusion,because,InstallJammer,doing,something,tricky,that,people,don't,expect,Minor,Enhancements,Added,new,API,call,Added,new,Zip,Archive,platform,for,building,zip,files,from,within,InstallJammer,Added,new,Refresh,File,List,Before,Building,project,preference,that,Yes,default,continue,current,behavior,can,now,turned,off,InstallJammer,not,automatically,search,for,new,deleted,files,directories,when,building,Added,new,Refresh,File,Groups,button,File,Groups,tree,search,directories,each,file,group,for,new,deleted,files,adjust,tree,match,When,searching,for,file,patterns,pattern,itself,now,substituted,for,virtual,text,BEFORE,split,means,that,virtual,text,itself,can,contain,handled,properly,Added,progress,output,for,building,tar,zip,files,Added,new,Off,Value,properties,for,Add,Widget,action,handle,checkbuttons,now,that,boolean,values,not,substituted,Off,Values,remain,value,virtual,text,altered,when,checkbutton,created,but,virtual,text,not,manipulated,after,that,except,checkbutton,itself,Added,new,Restore,Uninstall,property,Add,Windows,Registry,Key,action,Allow,Copy,File,action,specify,multiple,patterns,Source,instead,just,single,file,directory,Added,new,Watch,Regular,Expression,property,Execute,External,Program,specify,regular,expression,pattern,watch,for,instead,just,always,watching,for,single,pattern,Added,new,Echo,Input,property,Console,Get,User,Input,action,Added,new,build,dir,command,line,argument,specify,temporary,build,directory,Added,new,output,dir,command,line,argument,specify,output,directory,for,installers,Added,new,verbose,command,line,argument,show,more,verbose,build,output,Added,new,<%COMMON_QUICK_LAUNCH%>,virtual,directory,Windows,Minor,Bug,Fixes,Fixed,bug,Execute,External,Program,that,caused,progressive,output,for,console,installs,fail,Fixed,bug,where,root,installs,failed,after,change,2b2,Fixed,bug,where,editing,virtual,text,would,sometimes,fail,with,missing,variable,error,Fixed,bug,where,comments,were,not,being,shown,correctly,for,files,directories,Fixed,bug,where,pane,size,settings,for,main,window,were,not,being,remembered,Fixed,bug,where,symlinks,*NIX,systems,were,not,being,recognized,properly,Symlinks,should,now,included,installer,symlink,rebuilt,target,system,such,When,command,line,build,fails,for,missing,files,build,not,properly,fail,option,has,been,selected,previous,install,existed,not,deleted,build,fails,for,missing,file,Fixed,bug,where,newly,created,action,groups,could,not,used,target,drag,drop,actions,Fixed,bug,Env,Variable,Test,condition,where,Variable,property,was,not,being,substituted,for,virtual,text,before,checking,Fixed,bug,Remove,Windows,Registry,Key,action,where,specifying,Value,meant,that,Value,would,never,actually,removed,Fixed,bug,Uninstall,Selected,Files,where,paths,Windows,were,not,being,removed,Make,sure,only,add,directory,once,Add,Directory,Path,Fixed,bug,Install,Program,Folder,Shortcut,where,folder,name,was,being,ignored,Windows,Fixed,bug,Modify,Object,where,active,property,wasn't,properly,reflect,across,all,object,Fixed,bug,Execute,External,Program,where,using,Include,Stderr,would,leave,file,behind,bytes,now,removed,from,output,Execute,External,Program,before,text,checked,for,watch,patterns,Fixed,some,bugs,Execute,External,Program,where,errors,were,not,being,propertly,returned,Fixed,some,bugs,few,file,actions,where,linefeeds,were,being,mangled,Fixed,bug,Locate,Java,Runtime,Windows,where,JDK,directories,were,not,being,searched,Fixed,bug,where,not,including,English,language,installer,meant,that,some,messages,appeared,blank,2[$XTITELEND$][$XKEYS$]1,2[$XKEYSEND$]`;";
s[20] = "1.2b2^12b2.html^1.2b2 (July 23rd, 2007)This release contains bug fixes since the last beta as well as some minor...^1.2b2^2b2,July,23rd,2007,release,contains,bug,fixes,since,last,beta,well,some,minor,enhancements,Minor,Enhancements,File,installation,performance,should,greatly,improved,larger,installs,#1665160],Added,new,Fall,Back,Console,platform,property,that,tells,InstallJammer,fall,back,console,install,GUI,initialization,fails,for,non,Windows,platforms,only,true,default,option,should,disabled,you,not,plan,support,console,mode,#1757285],When,building,installer,InstallJammer,now,look,for,Tcl,packages,project,directory,include,any,found,installer,Platform,specific,packages,should,placed,subdirectory,named,after,platform,Added,new,command,Added,new,command,Added,new,<%ScriptExt%>,virtual,text,that,set,bat,Windows,UNIX,platforms,Added,new,<%InstallRegistryInfo%>,virtual,text,that,set,false,prevent,InstallJammer,from,installing,registry,information,separate,directory,location,registry,information,instead,stored,directly,into,uninstaller,Added,new,<%InstallDirSuffix%>,virtual,text,that,exists,appended,<%InstallDir%>,anytime,changes,does,not,already,equal,suffix,allows,installer,always,have,its,Application,Name,appended,install,directory,user,chooses,different,location,for,example,Added,new,<%InstallDrive%>,virtual,text,Windows,that,equals,drive,letter,whatever,drive,being,installed,etc,Several,actions,were,updated,tell,InstallJammer,that,change,had,been,made,Windows,registry,registry,changed,during,installation,broadcast,issued,running,processes,update,environments,exit,Added,new,command,display,error,messages,Updated,add,support,for,Windows,through,TWAPI,extension,Added,new,API,set,properties,objects,Added,action,command,arguments,that,allow,for,action,Tcl,command,called,anytime,virtual,text,variable,updated,Added,new,API,validate,URL,Changing,Alias,pane,action,action,group,automatically,update,its,title,builder,#1664071],Action,groups,can,now,reordered,builder,#1729054],Action,groups,can,now,check,conditions,before,after,they,execute,Any,conditions,that,occur,before,next,action,cause,action,group,execute,over,again,Added,new,Include,Stderr,property,Execute,External,Program,action,that,include,output,from,standard,error,channel,collected,output,Show,Progressive,Output,Execute,External,Program,action,now,shows,output,Console,mode,Unzip,File,action,can,now,show,percentage,complete,status,update,Added,new,Set,Object,Property,action,set,properties,any,object,Added,new,Add,Uninstall,property,Add,Directory,Path,action,that,automatically,remove,added,paths,uninstall,Updated,Add,Directory,Path,actions,work,UNIX,platforms,Added,new,Add,Environment,Variable,action,that,adds,environment,variables,all,platforms,Added,new,Delete,Environment,Variable,action,for,Windows,platforms,Added,new,Action,property,Add,Widget,action,that,specifies,action,execute,whenever,user,clicks,button,modifies,value,radiobutton,checkbutton,Added,new,button,Type,Add,Widget,action,Added,new,does,not,exist,exists,Object,Test,Condition,that,test,for,existence,objects,Added,new,was,set,from,command,line,Operator,Virtual,Text,Test,Condition,that,allow,checking,for,virtual,text,values,that,were,set,result,options,passed,command,line,Added,new,Command,Line,Test,condition,for,testing,options,passed,command,line,Minor,Bug,Fixes,When,installing,Vista,program,folder,icons,always,installed,for,All,Users,#1744543],Cancel,button,disabled,current,pane,now,disabled,well,When,uninstall,fails,remove,all,files,for,any,reason,uninstaller,remain,system,remove,rest,files,later,Fixed,bug,where,Message,Box,with,buttons,would,also,get,button,mistake,#1735003],Fixed,bug,where,calling,installer,with,path,would,cause,error,with,usage,information,#1729508],Fixed,bug,where,wrapped,text,console,with,just,right,length,would,over,one,character,Target,Filename,property,files,now,substituted,for,virtual,text,during,installation,#1741526],Fixed,bug,where,conditions,failing,console,silent,mode,would,cause,error,#1738957,Bug,#1733622],Fixed,bug,where,pasting,text,would,paste,twice,#1737485,Bug,#1727391],Fixed,bug,where,cancelling,exit,without,saving,could,cause,builder,get,into,unknown,state,where,window,title,would,not,update,Fixed,bug,where,aliases,files,were,not,being,saved,with,installer,files,could,not,referenced,alias,Fixed,bug,calculation,required,install,size,#1729654],Fixed,bug,where,some,messages,were,wrongly,being,output,during,Silent,install,Fixed,bug,where,passing,prefix,while,root,would,not,work,#1731561],Fixed,bug,where,multiple,calls,with,proxy,arguments,would,remember,proxy,between,calls,Fixed,bug,that,made,previewing,panes,UNIX,platforms,impossible,#1729643],Fixed,bug,Console,Get,User,Input,action,where,input,would,not,properly,saved,virtual,text,virtual,text,did,not,exist,before,action,was,called,Fixed,bug,where,Execute,Action,action,would,not,check,conditions,action,group,was,executing,#1737786],Fixed,bug,where,Execute,External,Program,action,would,never,set,status,variable,completion,thereby,causing,installer,hang,#1742712],Fixed,bug,Unzip,File,action,where,multiple,calls,action,could,result,files,being,compounded,#1747116],Fixed,bug,where,Text,Window,action,would,error,non,GUI,modes,action,not,valid,for,non,GUI,modes,Fixed,bug,Add,Windows,Registry,Key,action,where,keys,were,not,being,properly,added,uninstall,#1734957],Fixed,bug,Populate,Components,action,that,was,causing,components,population,Choose,Components,screen,act,very,odd,when,user,moved,back,forth,through,install,#1757505],Fixed,bug,File,Permission,Condition,that,would,cause,installations,root,drive,Windows,hang,infinite,loop,Fixed,bug,where,changing,order,Components,builder,would,not,reflect,installer,#1737930][$XTITLE$]1,2b2[$XTITELEND$][$XKEYS$]1,2b2[$XKEYSEND$]`;";
s[21] = "1.2b1^12b1.html^1.2b1 (May 28th, 2007)This release contains many new enhancements and bug fixes.  The installkit...^1.2b1^2b1,May,28th,2007,release,contains,many,new,enhancements,bug,fixes,installkits,have,been,recompiled,with,new,features,which,biggest,reason,for,minor,revision,bump,instead,just,patch,level,Major,Enhancements,Installkit,binaries,have,been,recompiled,with,new,features,FreeBSD,remains,compiled,but,completed,before,final,release,Added,ability,copy,paste,panes,actions,conditions,through,right,click,Edit,menu,#1664096],Added,new,Install,Password,property,encrypt,installers,with,password,#1557456],Added,support,for,mounting,handling,zip,files,from,within,installer,Added,new,section,specify,which,languages,supported,installer,instead,just,being,all,none,#1661645],Added,new,Unzip,File,action,unzip,standard,zip,files,during,installation,Major,Bug,Fixes,Fixed,bug,where,uninstaller,would,not,remember,settings,from,its,installer,#1676588],Fixed,bug,where,loading,project,with,lot,files,could,take,minutes,load,#1665160],Fixed,bug,where,newly,created,installs,would,inherit,Application,last,install,opened,#1689940],Minor,Enhancements,Quick,builds,should,lot,faster,now,especially,large,projects,with,lot,files,Added,new,FetchURL,API,call,fetch,web,URL,Added,debug,output,API,calls,show,when,they,called,with,what,arguments,Added,debug,output,several,actions,that,didn't,have,any,Added,option,preserve,file,permissions,for,files,non,Windows,platforms,Reordered,check,buttons,UNIX,file,permissions,tabs,reflect,standard,order,Only,languages,included,stored,within,installer,which,decreases,size,little,Automatically,include,TWAPI,extension,Windows,any,code,uses,Added,new,Require,JDK,property,Locate,Java,Runtime,action,require,full,JDK,instead,just,JRE,set,new,virtual,<%JavacExecutable%>,JDK,found,#1690206],Added,new,Foreground,property,Add,Widget,action,specify,text,color,most,widgets,Added,new,label,frame,widget,type,Add,Widget,action,Added,text,widget,type,Add,Widget,action,Added,new,readonly,state,Modify,Widget,action,that,can,applied,entry,text,widgets,Changed,popup,when,testing,modified,project,Now,instead,just,asking,whether,you,want,save,build,you,have,option,quick,build,full,build,Only,show,aliases,actions,when,selecting,from,list,instead,showing,object,IDs,that,don't,mean,anything,user,#1664071],Added,new,Watch,Progressive,Output,property,Execute,External,Program,action,watch,output,program,for,special,cues,InstallJammer,allows,external,programs,change,values,virtual,text,InstallJammer,when,running,for,long,time,they,can,update,messages,progress,bars,etc,Minor,Bug,Fixes,Fixed,bug,where,clicking,twice,grouping,user,interface,tree,like,attempting,rename,would,cause,error,#1665811],Fixed,bug,where,selecting,multiple,panes,then,adding,new,action,would,cause,error,Actions,now,added,last,pane,selected,Fixed,bug,where,substituting,text,for,eval,would,break,virtual,text,had,multiple,words,Fixed,minor,bug,text,edit,window,when,cancelling,edit,Fixed,bug,PromptForFile,API,that,would,cause,error,user,hit,cancel,Fixed,bug,Populate,Components,action,that,would,populate,components,that,were,marked,inactive,Fixed,bug,where,adding,multiple,files,file,group,would,cause,error,#1702000],Some,fixes,were,made,attempt,better,cleanup,stopped,builds,#1664102],Fixed,bug,where,UNIX,file,permissions,were,not,set,properly,based,mask,#1661644],Fixed,bug,Launch,File,action,that,would,cause,backslashes,substituted,Removed,requirement,Install,Windows,Shortcut,action,that,target,file,must,exist,create,shortcut,allow,for,creating,shortcuts,that,point,launching,programs,#1682449],Fixed,Windows,Registry,actions,propertly,substitute,virtual,text,#1685186],Fixed,bug,where,destroyed,window,can,still,parent,window,list,cause,error,#1672859],Ask,Yes,condition,now,includes,Console,Ask,Yes,action,use,that,when,installing,console,mode,#1713635],Fixed,bug,where,checking,for,existence,registry,key,without,value,would,always,return,false,Cleanup,failed,previews,better,Currently,preview,fails,you,can't,preview,that,window,again,because,further,errors,#1546595],Fixed,bug,where,small,blank,window,would,popup,during,silent,installs,uninstalls,Windows,Fixed,bug,Execute,External,Program,action,where,Status,Virtual,Text,was,not,being,accurately,set,with,exit,code,from,external,program,Fixed,bug,where,deleting,condition,while,still,editing,property,could,cause,error,condition,editor,#1708594],Fixed,bug,where,message,boxes,could,popup,non,transient,windows,Added,missing,icons,installers,#1707437],Fixed,several,smaller,bugs,Windows,#1684175],choose,directory,dialog,longer,has,hard,coded,English,strings,still,need,get,translations,for,other,languages,though,#1512658][$XTITLE$]1,2b1[$XTITELEND$][$XKEYS$]1,2b1[$XKEYSEND$]`;";
s[22] = "1.1.2^112.html^1.1.2 (February 21st, 2007)There was a packaging mistake with the 1.1.1 release.  1.1.1 is being...^^February,21st,2007,was,packaging,mistake,with,release,being,repackaged,longer,exists,Minor,Enhancements,Allow,multiple,files,selected,when,adding,files,File,Group,#1657047],Minor,Bug,Fixes,Fixed,bug,where,command,line,builds,Windows,would,fail,complain,about,not,being,able,find,BWidgets,#1653713],Fixed,bug,Set,Virual,Text,action,where,Substitute,Value,property,was,not,being,respected,#1658071],Fixed,bug,UNIX,command,line,builds,where,relative,project,file,could,not,specified,Fixed,bug,command,line,builds,where,solid,archives,were,never,completely,stored,#1653941],Fixed,bug,where,installkit,that,not,writable,would,cause,failure,when,building,#1658482][$XTITLE$]1,2[$XTITELEND$][$XKEYS$]1,2[$XKEYSEND$]`;";
s[23] = "1.1^11.html^1.1 (February 6th, 2007)This is a very big release, so not all of the changes are noted here.  T...^1.1^February,6th,2007,very,big,release,not,all,changes,noted,list,everything,could,remember,These,release,notes,copied,from,1b1,release,notes,show,off,everything,that,new,release,Some,these,changes,noted,final,bug,fixes,from,1b2,release,Major,Enhancements,Changed,underlying,file,format,for,installers,homegrown,format,that,allows,for,more,customization,Installkits,have,all,been,updated,GUI,components,now,dynamically,loaded,that,Console,Silent,installs,can,run,machines,with,libraries,also,resulted,installkits,being,much,smaller,for,most,platforms,Added,new,AIX,FreeBSD,Solaris,sparc,#1459564,#1487035],Added,support,for,building,TAR,files,with,without,GZIP,from,project,Added,LZMA,compression,support,#1487034],Added,support,for,solid,archives,solid,archive,built,one,big,file,before,being,compressed,can,often,result,installers,that,much,smaller,Solid,archives,must,first,extracted,temporary,location,before,they,can,installed,though,Added,support,for,defining,custom,command,line,options,for,installers,Added,support,for,specifying,custom,build,install,location,for,every,file,group,directory,file,project,Added,support,for,relative,file,locations,install,builder,#1525104],Added,support,for,customizing,compression,for,every,file,group,directory,file,project,means,some,file,groups,directories,even,single,files,can,all,compressed,with,different,compression,methods,choice,yours,Added,Console,install,mode,for,installing,via,console,non,Windows,platforms,#1546821],Added,new,Test,Uninstall,section,for,specifying,options,when,testing,uninstaller,Added,support,for,creating,shortcuts,under,Linux,FreeBSD,program,menus,#1487037],Added,support,for,prompting,user,for,root,when,installer,requires,#1487036],Deleted,files,longer,removed,from,project,They,disabled,greyed,out,file,group,tree,can,deleted,continue,part,project,#1525114],Added,new,Upgrade,Application,property,for,projects,that,denotes,that,project,upgrade,install,another,application,Some,actions,for,new,projects,have,been,changed,not,executed,upgrade,install,Added,support,for,registering,application,with,RPM,DPKG,databases,through,Register,Package,action,InstallJammer,documentation,now,includes,PDF,version,user,guide,Major,Bug,Fixes,Fixed,bug,that,was,causing,non,Latin,characters,display,incorrectly,Linux,other,UNIX,platforms,#1522660],Fixed,bug,where,installers,could,not,built,name,installer,path,contained,non,Latin,characters,#1517067],Symbolic,links,that,included,file,group,now,handled,links,installer,same,link,created,pointing,same,file,target,system,during,installation,#1499834],Fixed,bug,where,multiple,installations,application,same,machine,would,removed,when,only,one,uninstallers,was,executed,#1533190],New,Actions,Console,Ask,Yes,Console,Clear,Screen,Console,Get,User,Input,Console,Message,Console,Pause,Fetch,URL,Generate,UID,Launch,File,Add,Install,Info,Get,Previous,Install,Info,Install,Program,Folder,Shortcut,Reboot,Shutdown,System,Register,Package,Import,Windows,Registry,File,Remove,Windows,Registry,Key,#1596457],Focus,Widget,New,Conditions,Execute,Script,Condition,Object,Test,Condition,Virtual,Text,Test,Condition,Env,Variable,Test,Condition,Package,Test,Condition,Port,Test,Condition,File,Extension,Test,Condition,File,Type,Test,Condition,Registry,Test,Condition,Minor,Enhancements,Added,new,Copyright,poperty,for,projects,added,Windows,resource,information,Windows,executable,when,built,Added,new,preference,save,only,toplevel,directories,files,when,saving,project,mostly,for,developers,who,using,InstallJammer,project,template,that,then,built,from,command,line,Added,Default,Install,Mode,property,current,default,Standard,GUI,install,Added,section,for,Package,Information,that,used,when,adding,packages,local,packaging,system,Linux,Added,common,Data,property,all,objects,that,can,used,store,user,specific,data,object,which,can,then,used,other,actions,conditions,Added,Target,Filename,property,for,files,that,allow,installed,files,renamed,target,system,allows,for,total,mapping,files,installer,during,installation,Comment,Data,properties,objects,not,stored,install,they,blank,just,saves,little,space,when,building,Added,new,Show,Setup,Type,property,Setup,Types,specify,that,given,Setup,Type,should,not,offered,choice,during,installation,Actions,Panes,with,conditions,now,shown,with,beside,title,quick,way,see,that,they,affected,some,action,New,objects,added,since,last,time,project,was,opened,added,blue,quick,way,see,what,new,project,Added,new,default,Setup,Actions,action,group,that,execute,before,command,line,options,parsed,can,should,only,used,for,setting,virtual,text,manipulating,platform,specific,command,line,options,before,installer,really,gets,going,Added,new,test,option,for,testing,Console,mode,non,UNIX,platforms,open,console,window,start,install,inside,Added,new,preferences,for,specifying,custom,locations,for,Themes,Actions,Conditions,allow,developers,create,own,custom,components,locations,outside,InstallJammer,directories,Added,button,stop,install,builds,that,progress,Added,new,properties,Add,Widget,action,that,allow,any,non,label,widget,have,label,included,part,widget,itself,makes,easier,add,new,widgets,without,always,having,add,second,widget,for,label,Added,new,browse,entry,widget,Add,Widget,action,entry,with,browse,button,for,selecting,file,directory,target,system,1b2,Added,new,Auto,Update,property,Set,Virtual,Text,action,just,exposes,underlying,function,what,API,can,already,Setting,virtual,text,Auto,Update,means,that,screen,should,automatically,updated,anytime,value,changes,1b2,Building,project,from,command,line,that,has,not,been,converted,new,project,format,result,error,telling,user,they,need,upgrade,project,before,building,#1648310],1b2,Added,Arguments,property,Launch,File,action,pass,arguments,command,line,when,launching,file,1b2,Removed,message,box,check,for,removing,leftover,files,after,main,uninstall,completes,Users,usually,click,box,remove,rest,components,when,they,don't,actually,know,what,they're,doing,It's,better,leave,few,directories,lying,around,than,end,deleting,something,important,1b2,When,converting,from,current,version,project,auto,conversion,routine,attempt,fix,any,broken,License,panes,that,have,been,created,past,versions,1b2,Added,new,Add,Uninstall,property,Write,Text,File,action,1b2,Added,new,Append,Newline,property,Write,Text,File,action,#1651927],1b2,***,POTENTIAL,INCOMPATIBILITY,***,Changed,way,Files,handled,Write,Text,File,action,doesn't,make,sense,for,action,accept,list,patterns,Instead,action,now,accepts,explicit,list,files,not,patterns,write,#1651928],1b2,Added,new,Trim,String,property,Read,File,Into,Virtual,Text,action,that,data,read,from,file,can,trimmed,excess,whitespace,#1650962],1b2,checkbuttons,build,screen,now,match,active,status,platforms,startup,#1647636],1b2,***,POTENTIAL,INCOMPATIBILITY,***,Changed,search,order,virtual,text,substitution,Language,specific,text,now,checked,AFTER,non,specific,Since,most,virtual,text,variables,install,specified,without,language,those,variables,should,take,precedence,over,less,important,language,text,Minor,Bug,Fixes,Fixed,bug,where,using,Choose,Components,pane,non,Custom,setup,type,would,result,blank,component,list,#1614930],Fixed,bug,where,files,were,being,included,platform,where,file,group,had,not,been,included,#1615241],Fixed,bug,where,Choose,Components,pane,would,error,when,populating,component,list,child,component,was,added,where,parent,was,not,#1611703],Fixed,bug,where,License,Agreement,pane,would,not,disable,Yes,button,first,display,which,would,allow,user,skip,license,without,checking,Yes,button,#1593788],Fixed,typo,Create,File,Link,action,#1588953],Fixed,bug,where,File,Group,that,was,deactivated,during,installation,would,still,installed,#1585473],Fixed,bug,where,Condition,that,was,deactivated,during,installation,would,still,checked,#1585469],Fixed,bug,where,entry,widget,added,through,Add,Widget,action,would,lose,its,virtual,text,when,pane,was,displayed,#1585399],1b2,Fixed,bug,where,typing,into,entry,would,sometimes,cause,first,character,typed,turn,into,was,bug,auto,boolean,code,handling,1b2,Fixed,bug,where,License,pane,was,not,disabling,Yes,button,display,user,could,then,proceed,without,every,agreeing,license,#1642817],1b2,Fixed,bug,where,Choose,Directory,dialog,would,default,wrong,directory,would,blank,out,when,user,hit,cancel,#1642718],1b2,Fixed,bug,that,would,cause,InstallJammer,say,that,not,writable,during,installation,when,actually,#1642818],1b2,Moved,debug,log,into,local,InstallJammer,home,directory,for,each,user,instead,local,install,directory,When,running,multi,user,UNIX,system,debug,log,sometimes,cannot,written,1b2,Fixed,bug,where,line,got,moved,down,installjammer,script,causes,not,launch,1b2,Fixed,bug,where,option,command,line,would,error,Windows,1b2,Fixed,bug,command,line,builds,that,would,result,error,1b2,Fixed,bug,where,creating,new,project,can,fail,error,while,trying,save,project,preferences,InstallJammer,home,directory,does,not,already,exist,#1649235],1b2,Fixed,bug,where,editing,virtual,text,value,could,cause,error,some,cases,#1650172],1b2,Fixed,bug,where,command,line,builds,could,not,specify,relative,project,file,#1648430][$XTITLE$]1,1[$XTITELEND$][$XKEYS$]1,1[$XKEYSEND$]`;";
s[24] = "1.1b2^11b2.html^1.1b2 (January 23rd, 2007)Minor Bug FixesFixed a typo in ::BuilderAPI::GetAction.Fixed a b...^1.1b2^1b2,January,23rd,2007,Minor,Bug,Fixes,Fixed,typo,Fixed,bug,where,Default,Language,was,not,being,written,out,installer,meant,that,even,Default,Language,was,specified,was,being,ignored,installer,startup,Fixed,bug,where,help,documentation,for,command,line,options,was,pointing,non,existent,page,Fixed,typo,that,causes,startup,failure,when,auto,update,fails,for,some,reason,Turned,off,auto,update,check,default,until,it's,ready,Fixed,bug,where,InstallJammer,would,fail,could,not,create,its,registry,directory,Program,Files,Windows,Program,Files,not,writable,InstallJammer,attempt,create,its,registry,COMMON_APPDATA,directory,instead,Replaced,LZMA,binaries,Windows,with,proper,ones,fixes,error,that,occur,installers,that,compiled,with,LZMA,Windows,Fixed,bug,where,install,would,fail,Default,Setup,Type,did,not,exist,installer,InstallJammer,now,pick,first,Setup,Type,list,default,does,not,exist,1b2[$XTITELEND$][$XKEYS$]1,1b2[$XKEYSEND$]`;";
s[25] = "1.1b1^11b1.html^1.1b1 (January 17th, 2007)This is a very big release, so not all of the changes are noted here. ...^1.1b1^1b1,January,17th,2007,very,big,release,not,all,changes,noted,list,everything,could,remember,Major,Enhancements,Changed,underlying,file,format,for,installers,homegrown,format,that,allows,for,more,customization,Installkits,have,all,been,updated,GUI,components,now,dynamically,loaded,that,Console,Silent,installs,can,run,machines,with,libraries,also,resulted,installkits,being,much,smaller,for,most,platforms,Added,new,AIX,FreeBSD,Solaris,sparc,#1459564,#1487035],Added,support,for,building,TAR,files,with,without,GZIP,from,project,Added,LZMA,compression,support,#1487034],Added,support,for,solid,archives,solid,archive,built,one,big,file,before,being,compressed,can,often,result,installers,that,much,smaller,Solid,archives,must,first,extracted,temporary,location,before,they,can,installed,though,Added,support,for,defining,custom,command,line,options,for,installers,Added,support,for,specifying,custom,build,install,location,for,every,file,group,directory,file,project,Added,support,for,relative,file,locations,install,builder,#1525104],Added,support,for,customizing,compression,for,every,file,group,directory,file,project,means,some,file,groups,directories,even,single,files,can,all,compressed,with,different,compression,methods,choice,yours,Added,Console,install,mode,for,installing,via,console,non,Windows,platforms,#1546821],Added,new,Test,Uninstall,section,for,specifying,options,when,testing,uninstaller,Added,support,for,creating,shortcuts,under,Linux,FreeBSD,program,menus,#1487037],Added,support,for,prompting,user,for,root,when,installer,requires,#1487036],Deleted,files,longer,removed,from,project,They,disabled,greyed,out,file,group,tree,can,deleted,continue,part,project,#1525114],Added,new,Upgrade,Application,property,for,projects,that,denotes,that,project,upgrade,install,another,application,Some,actions,for,new,projects,have,been,changed,not,executed,upgrade,install,Added,support,for,registering,application,with,RPM,DPKG,databases,through,Register,Package,action,InstallJammer,documentation,now,includes,PDF,version,user,guide,Major,Bug,Fixes,Fixed,bug,that,was,causing,non,Latin,characters,display,incorrectly,Linux,other,UNIX,platforms,#1522660],Fixed,bug,where,installers,could,not,built,name,installer,path,contained,non,Latin,characters,#1517067],Symbolic,links,that,included,file,group,now,handled,links,installer,same,link,created,pointing,same,file,target,system,during,installation,#1499834],Fixed,bug,where,multiple,installations,application,same,machine,would,removed,when,only,one,uninstallers,was,executed,#1533190],New,Actions,Console,Ask,Yes,Console,Clear,Screen,Console,Get,User,Input,Console,Message,Console,Pause,Fetch,URL,Generate,UID,Launch,File,Add,Install,Info,Get,Previous,Install,Info,Install,Program,Folder,Shortcut,Reboot,Shutdown,System,Register,Package,Import,Windows,Registry,File,Remove,Windows,Registry,Key,#1596457],Focus,Widget,New,Conditions,Execute,Script,Condition,Object,Test,Condition,Virtual,Text,Test,Condition,Env,Variable,Test,Condition,Package,Test,Condition,Port,Test,Condition,File,Extension,Test,Condition,File,Type,Test,Condition,Registry,Test,Condition,Minor,Enhancements,Added,new,Copyright,poperty,for,projects,added,Windows,resource,information,Windows,executable,when,built,Added,new,preference,save,only,toplevel,directories,files,when,saving,project,mostly,for,developers,who,using,InstallJammer,project,template,that,then,built,from,command,line,Added,Default,Install,Mode,property,current,default,Standard,GUI,install,Added,section,for,Package,Information,that,used,when,adding,packages,local,packaging,system,Linux,Added,common,Data,property,all,objects,that,can,used,store,user,specific,data,object,which,can,then,used,other,actions,conditions,Added,Target,Filename,property,for,files,that,allow,installed,files,renamed,target,system,allows,for,total,mapping,files,installer,during,installation,Comment,Data,properties,objects,not,stored,install,they,blank,just,saves,little,space,when,building,Added,new,Show,Setup,Type,property,Setup,Types,specify,that,given,Setup,Type,should,not,offered,choice,during,installation,Actions,Panes,with,conditions,now,shown,with,beside,title,quick,way,see,that,they,affected,some,action,New,objects,added,since,last,time,project,was,opened,added,blue,quick,way,see,what,new,project,Added,new,default,Setup,Actions,action,group,that,execute,before,command,line,options,parsed,can,should,only,used,for,setting,virtual,text,manipulating,platform,specific,command,line,options,before,installer,really,gets,going,Added,new,test,option,for,testing,Console,mode,non,UNIX,platforms,open,console,window,start,install,inside,Added,new,preferences,for,specifying,custom,locations,for,Themes,Actions,Conditions,allow,developers,create,own,custom,components,locations,outside,InstallJammer,directories,Added,button,stop,install,builds,that,progress,Added,new,properties,Add,Widget,action,that,allow,any,non,label,widget,have,label,included,part,widget,itself,makes,easier,add,new,widgets,without,always,having,add,second,widget,for,label,Added,new,browse,entry,widget,Add,Widget,action,entry,with,browse,button,for,selecting,file,directory,target,system,Minor,Bug,Fixes,Fixed,bug,where,using,Choose,Components,pane,non,Custom,setup,type,would,result,blank,component,list,#1614930],Fixed,bug,where,files,were,being,included,platform,where,file,group,had,not,been,included,#1615241],Fixed,bug,where,Choose,Components,pane,would,error,when,populating,component,list,child,component,was,added,where,parent,was,not,#1611703],Fixed,bug,where,License,Agreement,pane,would,not,disable,Yes,button,first,display,which,would,allow,user,skip,license,without,checking,Yes,button,#1593788],Fixed,typo,Create,File,Link,action,#1588953],Fixed,bug,where,File,Group,that,was,deactivated,during,installation,would,still,installed,#1585473],Fixed,bug,where,Condition,that,was,deactivated,during,installation,would,still,checked,#1585469],Fixed,bug,where,entry,widget,added,through,Add,Widget,action,would,lose,its,virtual,text,when,pane,was,displayed,#1585399][$XTITLE$]1,1b1[$XTITELEND$][$XKEYS$]1,1b1[$XKEYSEND$]`;";
s[26] = "1.0.4^104.html^1.0.4 (October 25th, 2006)This release fixes quite a few bugs that have been reported by users (...^1.0.4^October,25th,2006,release,fixes,quite,few,bugs,that,have,been,reported,users,thank,you,all,adds,some,new,actions,lot,debugging,changes,release,could,called,debug,release,for,all,changes,that,have,gone,support,debugging,should,make,lot,easier,for,developers,testers,alike,track,down,problems,installer,debug,output,should,very,thorough,now,but,always,like,suggestions,there's,something,missing,don't,hesitate,ask,Bugs,***,POTENTIAL,INCOMPATIBILITY,***,Fixed,bug,where,mismatched,virtual,text,could,cause,error,when,substituting,text,was,causing,installation,errors,Japanese,systems,where,characters,were,being,interpreted,directory,paths,potentially,incompatible,you,using,inside,virtual,text,substitute,Tcl,commands,does,not,affect,Script,actions,conditions,like,Execute,Script,Script,Condition,where,scripts,properly,substituted,eval'd,Tcl,commands,#1578013],Fixed,bug,installjammer,script,that,would,cause,startup,fail,bit,systems,because,MACH,was,not,recognized,Fixed,bug,where,extra,registry,key,would,cause,lookup,failure,now,strip,any,extra,from,key,before,looking,registry,Fixed,bug,where,Launch,Web,Browser,would,fail,error,Now,we're,running,under,KDE,Gnome,action,attempt,use,default,method,for,launching,URL,under,those,environments,that,fails,we're,using,different,window,manager,action,attempt,find,suitable,browser,based,environment,known,browsers,Fixed,bug,Add,Widget,action,that,would,cause,errors,radiobutton,was,added,with,values,that,looked,like,booleans,Value,property,now,converted,looks,like,boolean,before,creating,radiobuttons,#1583094],Fixed,bug,Choose,Directory,dialog,where,clicking,window,would,cause,error,#1565652],Fixed,bug,Choose,Directory,dialog,where,choosing,root,level,directory,like,would,not,work,#1565665],Fixed,bug,Windows,shortcut,creation,where,long,paths,could,not,used,would,end,looking,like,path,with,some,junk,characters,end,#1565654],Fixed,bug,where,user,could,accidentally,delete,entire,Company,directory,Windows,without,knowing,Now,check,see,directory,looks,like,<%Company%>,does,don't,delete,unless,it's,totally,empty,#1575801],Fixed,bug,where,installing,Windows,uninstall,registry,entry,could,fail,don't,have,permission,write,HKEY_LOCAL_MACHINE,fails,we'll,try,write,HKEY_CURRENT_USER,uninstall,registry,instead,#1578278],Enhancements,Added,lot,new,debugging,output,throughout,installation,provide,more,information,when,running,debug,mode,Added,new,variable,specify,that,debug,output,should,console,When,running,debug,mode,mimic,what,goes,out,debug,log,not,debug,mode,you,still,see,debug,output,but,with,debug,log,With,open,console,set,upon,startup,When,debugging,any,comment,object,output,along,with,regular,debug,output,allows,developers,comment,object,for,other,developers,see,when,running,debug,mode,Added,new,Brazilian,Portugese,translations,thanks,Alan,Carvalho,Assis,Added,new,Log,Debug,Message,action,Added,new,Modify,Object,action,Added,new,Add,Directory,Path,action,Added,new,Remove,Directory,from,Path,action,Added,new,Add,Pane,Order,action,Added,new,Remove,Pane,from,Order,action,Added,new,Window,State,property,for,Install,Windows,Shortcut,action,Added,new,Add,Uninstall,property,for,Unpack,Stored,File,action,Added,new,Add,Uninstall,property,for,Add,Windows,Registry,Key,action,Move,Pane,action,now,appends,specified,pane,back,order,wizard,Added,entry,widget,possible,type,for,Add,Widget,actions,Panes,marked,inactive,skipped,Files,marked,inactive,skipped,when,building,list,files,install,4[$XTITELEND$][$XKEYS$]1,4[$XKEYSEND$]`;";
s[27] = "1.0.3^103.html^1.0.3 (September 19th, 2006)BugsFixed a typo in the Add Windows File Type action that would ...^1.0.3^September,19th,2006,Bugs,Fixed,typo,Add,Windows,File,Type,action,that,would,cause,error,when,Icon,Path,was,specified,#1533420],Fixed,bug,where,some,user,systems,don't,have,time,format,available,We'll,use,long,hand,version,from,now,would,cause,error,some,systems,when,selecting,file,File,Group,tree,#1545596],Fixed,bug,where,just,clicking,File,Group,File,Group,tree,would,cause,into,rename,edit,mode,Fixed,bug,where,COMMON_*,directories,don't,work,Windows,From,now,we'll,try,use,specific,counterpart,COMMON,was,not,found,#1551016],Fixed,few,other,bugs,related,running,InstallJammer,Windows,Fixed,bug,where,including,TWAPI,extension,did,not,actually,load,library,when,installer,started,Modified,Script,Condition,allow,Tcl,commands,variables,substituted,within,script,Fixed,bug,where,Update,files,with,more,recent,date,check,was,not,accurately,comparing,files,whose,dates,were,identical,those,cases,files,would,installed,anyway,when,they,should,skipped,Fixed,bug,where,Root,Key,was,being,ignored,for,registry,keys,Add,Windows,Registry,Key,action,#1557936],Fixed,bug,where,editing,text,certain,properties,could,cause,error,when,trying,save,#1533009],Message,catalogs,now,stored,installer,during,quick,build,Enhancements,Added,German,translations,thanks,Hans,Hellwege,Added,new,File,Actions,group,with,some,new,actions,See,documentation,for,description,each,new,action,Added,new,Adjust,Line,Feeds,action,Added,new,Backup,File,action,Added,new,Change,File,Ownership,action,Added,new,Change,File,Permissions,action,Added,new,Create,File,Link,action,Added,new,Copy,File,action,Added,new,Delete,File,action,Added,new,Read,File,Into,Virtual,Text,action,Added,new,Rename,File,action,Added,new,Replace,Text,File,action,Added,new,Write,Text,File,action,3[$XTITELEND$][$XKEYS$]1,3[$XKEYSEND$]`;";
s[28] = "1.0.2^102.html^1.0.2 (August 1st, 2006)BugsHooked up the Help button in the New Project Wizard to go to the...^1.0.2^August,1st,2006,Bugs,Hooked,Help,button,New,Project,Wizard,Step,Step,tutorial,help,documentation,Fixed,bug,where,Alias,property,was,not,reflecting,correct,value,when,switching,between,nodes,File,Group,tree,#1521556],Changed,way,multiple,selection,File,Group,tree,works,when,using,shift,click,InstallJammer,now,select,all,nodes,between,two,shift,click'd,nodes,regardless,parent,Scott,Specker],Fixed,bug,where,Execute,Script,would,not,accurately,report,back,error,#1521867],pane,changes,while,moving,forward,backward,like,due,Move,Pane,action,want,stop,moving,because,pane,has,changed,#1526114],Fixed,bug,Add,Windows,File,Type,that,caused,fail,invalid,command,#1530808],Replaced,Linux,installkit,with,new,non,threaded,build,means,that,Linux,installs,longer,use,threads,but,also,means,that,Linux,installs,longer,rely,pthread,library,target,system,#1525293],Replaced,Windows,installkit,with,new,one,that,includes,new,command,create,Windows,shortcuts,#1532013],Enhancements,installkit,for,Windows,now,500k,smaller,thanks,Jeremy,Collake's,awesome,PECompact2,software,Record,main,InstallJammer,window,maximized,Windows,restore,that,state,when,restarting,InstallJammer,2[$XTITELEND$][$XKEYS$]1,2[$XKEYSEND$]`;";
s[29] = "1.0.1^101.html^1.0.1 (July 5th, 2006)BugsFixed a bug where executing some actions before the first pane is ...^1.0.1^July,5th,2006,Bugs,Fixed,bug,where,executing,some,actions,before,first,pane,displayed,would,cause,error,InstallJammer,was,attempting,update,widgets,pane,when,was,pane,update,Clicking,outside,entry,while,making,new,folder,Choose,Directory,dialog,now,finish,edit,instead,reverting,text,#1510752],Fixed,bug,where,specifying,Default,Language,was,not,working,properly,during,installation,Allow,Language,Selection,Default,Language,always,used,Allow,Language,Selection,Yes,InstallJammer,first,attempt,determine,user's,system,language,available,use,that,default,language,select,dialog,InstallJammer,cannot,determine,system,language,one,don't,have,language,select,dialog,default,Default,Language,#1510750],Fixed,bug,where,Cancel,button,Preferences,dialog,didn't,actually,reset,preferences,#1508941],Fixed,bug,where,auto,complete,typing,was,turned,for,Help,Browser,combobox,Preferences,dialog,was,causing,user,not,able,type,location,help,browser,Fixed,bug,where,building,from,command,line,would,include,files,directories,that,were,marked,inactive,project,Fixed,bug,where,Active,property,node,File,Group,tree,could,get,out,sync,with,its,check,image,#1505408],Fixed,bug,where,InstallJammer,was,not,setting,modified,file,after,was,installed,target,system,meant,that,every,file,installed,had,current,instead,what,was,stored,installer,#1505025],Fixed,bug,where,error,dialog,when,renaming,adding,virtual,text,could,get,into,weird,state,user,was,doing,bunch,weird,stuff,Instead,just,post,error,dialog,cancel,edit,stop,whole,process,#1509526],Fixed,bug,where,renaming,virtual,text,variable,was,not,saving,properly,#1509526],Fixed,bug,where,adding,new,virtual,text,with,value,would,not,get,saved,#1511881],Fixed,bug,that,caused,InstallJammer,not,recognize,versions,properly,for,Blackdown,Java,JRE,they,use,instead,#1511881],Fixed,bug,that,would,cause,error,were,looking,for,JRE,Windows,system,that,had,never,installed,one,#1511871],Fixed,bug,that,would,cause,files,added,directories,that,direct,child,Windows,drive,lose,make,files,install,wrong,place,#1511627],Fixed,bug,where,InstallJammer,could,create,temporary,directory,root,then,not,able,install,later,non,root,#1513795],Fixed,bug,that,caused,InstallJammer,ignore,hidden,files,when,building,lists,files,directories,for,packaging,1[$XTITELEND$][$XKEYS$]1,1[$XKEYSEND$]`;";
s[30] = "1.0^10.html^1.0 (June 18th, 2006)As of the 1.0 release, InstallJammer is now released under the GNU General ...^1.0^June,18th,2006,release,InstallJammer,now,released,under,GNU,General,Public,License,GPL,Bugs,Fixed,bug,that,would,cause,user,input,into,entry,field,substituted,boolean,value,they,typing,Fixed,bug,that,would,cause,files,that,have,been,installed,previously,fail,when,trying,install,over,Fixed,bug,that,would,cause,Make,New,Folder,button,Choose,Directory,dialog,fail,Fixed,bug,that,would,cause,virtual,text,table,error,when,switching,between,languages,edit,was,currently,active,Fixed,bug,that,was,causing,result,virtual,text,not,set,for,Execute,Script,action,0[$XTITELEND$][$XKEYS$]1,0[$XKEYSEND$]`;";
s[31] = "1.0rc3^10rc3.html^1.0rc3 (May 23rd, 2006)BugsFixed a bug that would cause message boxes to error on Windows duri...^1.0rc3^0rc3,May,23rd,2006,Bugs,Fixed,bug,that,would,cause,message,boxes,error,Windows,during,command,line,build,Since,Windows,doesn't,have,console,can,output,use,message,dialogs,instead,let,user,know,when,something,happens,Fixed,bug,that,was,causing,failure,command,line,builds,1486397],Fixed,bug,that,would,cause,error,New,Project,Wizard,user,didn't,all,way,last,screen,wizard,Fixed,bug,that,would,cause,unrecognized,error,was,actual,error,while,trying,preview,pane,message,box,would,never,come,instead,come,with,error,that,doesn't,actually,tell,you,what,problem,Fixed,virtual,text,variables,for,user,info,panes,variables,used,now,<%UserInfoName%>,<%UserInfoCompany%>,Fixed,bug,where,text,label,for,text,properties,was,prepending,word,Edit,every,label,Fixed,bug,that,would,cause,Unpack,Stored,File,action,fail,Fixed,bug,that,would,cause,wizard,fail,some,platforms,with,error,about,resizable,Fixed,bug,that,would,cause,error,virtual,text,variables,Execute,External,Program,action,were,left,blank,Enhancements,Build,project,files,now,write,out,with,UNIX,linefeeds,Unpack,Stored,File,longer,respect,File,Update,Method,for,given,file,isn't,very,intuitive,anyway,action,can,always,have,its,own,conditions,needs,Modified,Choose,Directory,dialog,show,drives,Windows,that,user,can,change,different,drive,Added,last,missing,translation,strings,0rc3[$XTITELEND$][$XKEYS$]1,0rc3[$XKEYSEND$]`;";
s[32] = "1.0rc1^10rc1.html^1.0rc1 (May 10th, 2006)BugsFixed a bug that was causing installers to not all share the same b...^1.0rc1^0rc1,May,10th,2006,Bugs,Fixed,bug,that,was,causing,installers,not,all,share,same,background,color,would,cause,installers,look,odd,most,UNIX,platforms,because,colors,didn't,match,Fixed,bug,where,radiobuttons,license,pane,were,not,reflecting,state,properly,Fixed,bug,that,was,causing,InstallJammer,ignore,Allow,Language,Selection,property,Fixed,bug,install,builder,that,would,cause,builder,not,remember,paned,window,locations,between,sessions,Fixed,bug,Execute,External,Program,action,that,would,cause,programs,fail,they,had,spaces,backspaces,names,Enhancements,Execute,Script,actions,now,execute,global,level,Added,Working,Directory,property,Execute,External,Program,action,0rc1[$XTITELEND$][$XKEYS$]1,0rc1[$XKEYSEND$]`;";
s[33] = "1.0b2^10b2.html^1.0b2 (April 19th, 2006)Special Note for 1.0b2With the amount of changes in this release, I hi...^1.0b2^0b2,April,19th,2006,Special,Note,for,0b2,With,amount,changes,release,highly,recommend,that,you,build,new,project,instead,trying,convert,your,old,project,tried,make,conversion,smooth,possible,but,with,amount,changes,was,very,difficult,Except,for,bug,fixes,truly,last,release,make,changes,any,new,project,from,until,final,release,hopefully,not,need,any,conversion,unless,it's,fix,bug,Big,Changes,These,changes,create,incompatibilities,with,way,InstallJammer,currently,works,Unless,otherwise,stated,all,incompatibilities,automatically,converted,when,you,load,your,old,project,into,new,version,InstallJammer,Added,Multi,Language,Support,Installers,Installers,InstallJammer,can,now,support,multiple,languages,Included,release,Spanish,thanks,Jose,Jurado,French,thanks,Olivier,Touze,message,catalogs,support,these,languages,installers,When,converting,your,project,you,asked,you,want,update,all,text,your,project,clear,any,new,text,you,may,have,added,before,updating,but,you,need,get,new,multi,language,support,New,Default,Action,Groups,New,action,groups,added,every,new,project,these,default,groups,executed,InstallJammer,automatically,They,Startup,Actions,Finish,Actions,Cancel,Actions,Please,read,through,documentation,What,Action,Groups,for,more,information,what,these,new,groups,Changed,Text,Properties,Advanced,Properties,for,some,Actions,Conditions,Since,text,properties,now,localized,language,some,text,properties,actions,conditions,had,changed,over,Standard,properties,don't,want,scripts,strings,that,not,messages,localized,language,Bugs,Fixed,typo,Add,Windows,File,Command,action,that,was,causing,fail,Fixed,bug,where,creating,new,Setup,Type,would,cause,error,1453794],Fixed,bug,where,editing,name,File,Group,would,cause,error,when,trying,save,new,name,1453794],Fixed,bug,uninstall,Clicking,when,uninstall,would,ask,you,wanted,proceed,with,uninstall,would,still,proceed,Fixed,bug,where,InstallJammer,was,not,respecting,File,Update,Method,file,group,All,installs,were,using,default,check,for,newer,files,date,Fixed,bug,Install,Wrapped,Script,action,that,was,causing,not,work,Fixed,Install,Wish,Binary,action,previously,wasn't,working,Fixed,bug,where,installing,byte,file,Windows,would,cause,error,Fixed,bug,where,including,files,with,non,ASCII,characters,installer,would,cause,InstallJammer,fail,when,building,installer,All,filenames,should,now,acceptable,Fixed,bug,where,<%Username%>,virtual,text,variable,was,not,being,setup,properly,when,user,was,root,meant,that,Require,Root,would,only,work,user,had,actually,logged,into,session,root,instead,just,SU'ing,root,Fixed,bug,where,double,clicking,row,border,between,rows,table,would,cause,error,Fixed,bug,that,could,occur,when,clicking,into,another,cell,while,editing,property,Changed,way,project,directories,handled,when,creating,new,install,Creating,project,file,directory,without,subdirectory,would,cause,entire,directory,deleted,when,deleting,project,All,projects,now,built,with,own,subdirectory,Normalize,home,directory,UNIX,platforms,was,causing,bug,during,uninstallation,when,trying,remove,installjammerinfo,file,Fixed,bug,where,trying,exit,during,build,would,cause,error,bad,proc,name,You,still,can't,exit,close,project,during,build,That's,yet,come,Save,active,component,before,previewing,that,all,latest,changes,appear,preview,window,Fixed,bug,where,some,properties,would,not,get,saved,when,switching,from,one,component,next,Fixed,bug,where,testing,install,that,needed,rebuilt,would,cause,error,due,missing,command,now,wait,until,rebuild,done,before,testing,All,text,boxes,all,themes,now,word,wrap,instead,character,wrap,All,boolean,virtual,text,now,handled,auto,converted,when,setting,virtual,text,makes,easier,deal,with,checkbuttons,checks,Changed,display,embedded,textboxes,Instead,making,entire,fram,with,scrollbars,appear,sunken,only,make,textbox,itself,appear,sunken,1453799],Fixed,bug,where,editing,text,property,condition,would,cause,error,when,trying,save,new,text,Added,checks,make,sure,files,Temp,InstallInfoDir,directories,don't,get,written,out,install,log,These,directories,automatically,cleaned,InstallJammer,anyway,Fixed,bug,where,hittin,Escape,while,editing,property,Conditions,Editor,would,actually,cause,window,close,Fixed,bug,where,some,information,was,not,being,saved,for,some,platforms,they,were,not,active,new,project,Fixed,bug,where,Platform,Information,was,not,accurately,being,updated,when,closing,opening,install,projects,When,browsing,for,install,directory,during,installation,longer,append,directory,end,what,user,chooses,They,however,have,option,make,new,folder,target,system,for,installing,into,Enhancements,Added,multi,language,support,for,installers,HUGE,enhancement,that,was,originally,slated,for,release,but,demand,was,high,that,finished,early,Added,message,catalogs,for,Spanish,French,languages,Modified,build,install,processes,use,threads,instead,external,processes,save,overhead,always,starting,new,process,Install,builds,now,almost,twice,fast,previous,releases,Installation,should,see,pretty,good,speed,well,Completed,help,documentation,hooked,throughout,install,builder,means,that,clicking,Help,button,hitting,anywhere,InstallJammer,take,you,directly,right,place,documentation,Added,new,properties,for,files,directories,Every,file,directory,install,can,now,customized,Added,new,<%ApplicationURL%>,virtual,text,Added,new,<%ShortAppName%>,virtual,text,Made,main,toolbar,buttons,22x22,instead,16x16,Added,Build,for,Final,Release,checkbutton,build,screen,checkbutton,builds,installers,without,debugging,options,with,some,other,things,cleaned,that,they,ready,for,final,release,customers,Added,new,Install,Program,Folder,for,All,Users,property,for,Windows,platforms,Added,checkbutton,Select,Program,Folder,pane,let,user,install,program,folder,for,all,users,instead,just,current,user,Added,new,Quick,Build,button,main,toolbar,Removed,option,rebuild,without,repackaging,files,now,Quick,Build,Removed,option,save,main,tcl,when,building,Build,files,now,always,saved,build,subdirectory,project,directory,Added,new,Launch,Web,Browser,action,that,opens,web,browser,specified,URL,Added,new,Unpack,Stored,File,action,that,unpack,file,stored,installer,specified,location,Added,new,Install,Desktop,Shortcut,action,does,exactly,what,other,install,shortcut,actions,except,that,automatically,install,shortcut,target,desktop,for,every,supported,window,manager,available,Added,new,Check,for,Previous,Install,action,that,sets,variables,<%PreviousInstallExists%>,<%PreviousInstallDir%>,Added,new,Set,Virtual,Text,action,set,value,virtual,text,variable,specified,language,Added,new,features,for,new,projects,tell,InstallJammer,add,checkbuttons,Setup,Complete,pane,your,installer,Added,new,<%JavaFound%>,virtual,text,Locate,Java,Runtime,action,Added,new,<%Tail,filename,virtual,text,get,tail,end,file,path,Added,ability,substitute,message,catalog,text,virtual,text,variable,For,example,<%PaneID,BackButton%>,return,Back,Button,text,value,for,pane,identified,PaneID,Added,new,Exit,Type,property,Exit,action,that,specifies,whether,we're,exiting,Cancel,Finish,condition,mostly,affects,what,actions,InstallJammer,take,during,exit,including,whether,Finish,Actions,Cancel,Actions,action,group,called,Removed,standard,InstallJammer,virtual,text,from,Virtual,Text,screen,From,now,only,virtual,text,added,project,appear,Added,new,Windows,Resource,properties,Install,Wrapped,Script,action,Files,now,stored,installer,instead,filename,makes,things,lot,cleaner,also,obscures,filenames,bit,Changed,default,geometry,for,InstallJammer,that,doesn't,fill,entire,screen,lower,resolution,monitors,InstallJammer,now,remembers,size,placement,panes,throughout,install,builder,Resizing,panes,remembered,between,sessions,Changed,default,file,extension,non,Windows,systems,from,bin,nothing,Most,Linux,systems,seem,recognize,that,executable,files,shouldn't,have,extension,Added,prefix,option,installs,that,lets,user,specify,install,directory,prefix,from,command,line,Added,new,default,Action,Cancel,Actions,Finish,Actions,Startup,Actions,Cancel,Actions,Finish,Actions,now,get,called,automatically,from,within,installer,uninstaller,They,don't,need,executed,from,specific,panes,Removed,Enable,InstallJammer,Version,System,option,We're,going,always,save,versions,from,now,When,adding,default,application,directory,for,new,project,now,just,add,directory,itself,set,Destination,Directory,<%InstallDir%>,instead,adding,all,files,contained,directory,achieve,same,effect,having,application,install,root,install,directory,Removed,separator,from,Custom,Blank,Pane,Modern,Wizard,theme,added,separator,underneath,image,text,box,looks,more,like,other,modern,wizards,1453799],uninstaller,now,look,for,install,log,InstallJammer,info,directory,can't,find,one,stored,inside,itself,Uninstallers,now,delete,info,directory,when,everything,else,done,make,sure,cleanup,final,traces,application,0b2[$XTITELEND$][$XKEYS$]1,0b2[$XKEYSEND$]`;";
s[34] = "1.0b1^10b1.html^1.0b1 (February 12th, 2006)Big ChangesThese changes create incompatibilities with the way Inst...^1.0b1^0b1,February,12th,2006,Big,Changes,These,changes,create,incompatibilities,with,way,InstallJammer,currently,works,Unless,otherwise,stated,all,incompatibilities,automatically,converted,when,you,load,your,old,project,into,new,version,InstallJammer,File,Groups,Overhauled,Changed,way,directories,file,groups,work,Instead,treating,root,directory,being,installed,into,file,group,directory,every,directory,file,group,has,its,directory,created,gives,more,consistent,approach,directories,file,groups,What,you,see,what,you,get,All,directories,file,group,created,just,you,see,file,group,display,Think,file,group,root,directory,created,when,installing,every,directory,contained,file,group,created,underneath,means,that,instead,adding,single,directory,for,your,whole,application,you'll,have,add,all,contents,directory,but,approach,more,line,with,how,other,installers,work,well,how,most,people,would,expect,work,Choosing,your,application,directory,when,creating,new,install,automatically,grab,contents,that,directory,setup,your,Program,Files,file,group,correctly,Modify,Button,Action,Replaced,Modify,Button,action,has,been,replaced,new,Modify,Widget,action,action,more,generic,can,execute,any,widget,pane,instead,just,wizard,buttons,Unlike,Modify,Button,action,Modify,Widget,action,can,specify,multiple,widgets,separated,same,action,InstallJammer,modify,all,once,Bugs,Fixed,bug,conditions,editor,where,closing,window,with,would,put,editor,into,unstable,state,Fixed,bug,where,building,install,would,cause,active,component,blank,Fixed,bug,that,would,cause,status,progressbar,disappear,between,platform,builds,Fixed,bug,where,escaping,while,editing,property,could,sometimes,cause,error,Fixed,bug,where,Windows,registry,actions,would,still,display,message,non,Windows,systems,Fixed,bug,where,user,chose,new,installation,directory,application,would,install,into,that,directory,instead,creating,subdirectory,beneath,Fixed,bug,where,uninstall,would,not,center,screen,during,startup,Fixed,Select,Destination,pane,allow,configuration,Destination,Folder,label,1370424],longer,install,Windows,shortcut,target,does,not,exist,1370423],Fixed,bug,that,was,causing,command,line,builds,fail,1374874],Fixed,bug,where,unselecting,component,Custom,install,would,not,disable,component,during,installation,Fixed,bug,that,would,cause,Icon,Image,properties,overwritten,anytime,project,was,loaded,1367770],Fixed,bug,where,Execute,Action,action,would,not,execute,single,action,only,Action,Group,Don't,auto,scroll,build,log,user,has,moved,read,something,else,Fixed,bug,where,InstallJammer,would,forget,Build,Platforms,when,saving,Enhancements,Executables,now,stored,subdirectory,project,instead,root,project,directory,puts,all,installers,one,place,during,building,allows,for,some,expansion,later,Added,new,File,Permission,condition,check,file,permissions,target,system,Added,new,Modify,Widget,action,change,state,text,widget,pane,Added,new,Locate,Java,Runtime,action,locate,best,available,Java,runtime,target,system,Added,new,Get,Java,Property,action,get,value,property,from,Java,properties,file,Added,new,Wait,action,that,cause,InstallJammer,wait,specified,amount,time,before,proceeding,with,install,Added,checks,for,properties,that,attempt,verify,that,any,virtual,text,property,complete,valid,Added,new,Require,Root,Root,Install,Directory,properties,UNIX,platforms,These,let,you,require,installing,user,root,adjust,default,installation,directory,user,installing,root,Added,new,<%Username%>,virtual,text,that,contains,username,installing,user,Added,button,explore,test,installs,main,toolbar,Went,through,all,install,panes,each,theme,made,sure,that,all,widgets,had,names,that,properties,could,modified,project,Added,Required,Component,option,components,specify,that,component,should,not,allowed,unselected,during,Custom,installation,Added,ability,drag,drop,Setup,Types,Components,change,ordering,order,changes,order,they,displayed,during,installation,Added,scrollbars,main,project,listing,Added,new,Default,File,Permission,Default,Directory,Permission,properties,UNIX,platforms,define,default,permission,masks,during,installation,Added,right,click,menu,option,File,Group,tree,create,shortcut,for,file,Windows,Desktop,Program,Folder,Added,property,Execute,External,Program,action,specify,text,box,update,without,put,while,program,running,Also,change,way,data,read,from,external,program,that,instead,being,line,line,data,read,becomes,available,makes,possible,configure,make,actions,from,within,install,output,continually,update,text,box,builds,Added,new,Edit,Pane,Code,Restore,Original,Pane,buttons,each,property,window,allows,you,edit,code,that,used,create,pane,make,look,any,way,you,want,Added,ability,select,multiple,file,groups,directories,files,File,Group,tree,set,permissions,all,once,InstallJammer,now,automatically,remove,unused,file,groups,components,when,building,install,component,includes,file,group,that,was,not,saved,because,was,inactive,for,any,other,reason,file,group,removed,from,component's,list,file,groups,before,building,warning,message,output,build,log,when,happens,0b1[$XTITELEND$][$XKEYS$]1,0b1[$XKEYSEND$]`;";
s[35] = "Getting Started^GettingStarted.html^The easiest way to get started using InstallJammer for the first time is to read through some of our...^Getting Started^easiest,way,get,started,using,InstallJammer,for,first,time,read,through,some,tutorials,you,have,good,grasp,installers,how,they,work,you,can,probably,give,quick,read,through,Create,New,Install,Fast,get,started,you,want,more,detailed,look,building,new,install,read,through,Create,New,Install,Step,Step,tutorial,you're,already,familiar,with,how,use,InstallJammer,you,just,want,learn,something,maybe,you,didn't,know,already,you,can,read,through,Frequently,Asked,Questions,see,maybe,what,you're,looking,for,Once,you,have,your,first,install,project,built,read,through,Getting,Know,Install,Builder,give,you,good,introduction,InstallJammer's,install,builder,how,use,effectively,After,you,finish,learning,your,way,around,InstallJammer's,install,builder,read,little,bit,more,about,Virtual,Text,its,use,within,InstallJammer,You,might,also,want,read,through,What,Virtual,Text,list,Virtual,Text,Definitions,Virtual,Directory,Definitions,Once,you,understand,virtual,text,little,better,it's,time,learn,about,what,customer,really,sees,panes,your,install,Read,What,Panes,become,more,familiar,with,how,InstallJammer,displays,installer,user,When,you,think,you,understand,basics,installs,use,virtual,text,you,might,want,read,through,What,Actions,Actions,used,throughout,install,process,it's,worthwhile,read,what,they,how,you,use,what,types,actions,available,After,reading,about,actions,you'll,probably,want,know,how,control,those,actions,Read,What,Conditions,get,feel,for,how,InstallJammer,controls,flow,your,installer,Started[$XTITELEND$][$XKEYS$]Getting,Started[$XKEYSEND$]`;";
s[36] = "Frequently Asked Questions^FrequentlyAskedQuestions.html^1.  How do I save relative paths for the files in my install project?Most installers give you th...^Frequently Asked Questions^How,save,relative,paths,for,files,install,project,Most,installers,give,you,option,check,box,that,allows,you,save,all,files,your,project,relative,paths,Relative,usually,being,relative,location,project,file,itself,extremely,useful,feature,since,most,developers,don't,usually,put,work,same,locations,own,machines,Instead,just,simple,check,box,for,saving,paths,relative,InstallJammer,allows,you,ability,completely,map,location,any,file,your,project,done,through,Location,property,for,directories,files,you,select,file,directory,your,project,you,see,standard,property,called,Location,property,tells,InstallJammer,where,find,file,directory,local,system,you,click,Location,property,you,see,browse,button,that,opens,popup,for,specifying,location,InstallJammer,lets,you,specify,location,directory,that,can,stored,back,into,project,file,itself,one,that,you,can,store,your,own,local,copy,your,InstallJammer,preferences,location,specified,for,directory,actual,location,that,directory,not,directory,that,contains,that,directory,location,specified,for,file,directory,that,contains,that,file,Locations,can,specified,full,directory,path,relative,directory,path,virtual,text,relative,directory,path,relative,location,project,file,itself,Virtual,text,can,contain,full,relative,path,substituted,build,time,get,file,location,For,example,you,could,specify,Location,your,main,application,directory,<%BaseDir%>,Then,your,Virtual,Text,Strings,table,create,new,virtual,text,variable,BaseDir,with,location,your,application,Then,you,can,actually,build,from,command,line,with,different,location,specifying,DBaseDir,Where,best,place,put,project,file,that,part,application,directory,Many,developers,wish,put,InstallJammer,project,files,somewhere,within,application,structure,that,project,file,can,easily,included,when,packaging,application,itself,that,project,file,can,maintained,same,source,repository,application,itself,It's,best,put,your,project,file,its,own,subdirectory,because,InstallJammer,uses,project,file,location,base,for,creating,subdirectory,best,place,put,your,project,file,that,part,your,application,directory,subdirectory,off,main,application,directory,subdirectory,would,nicely,With,place,you,can,easily,specify,Location,your,main,application,directory,have,all,your,application,files,relative,your,project,file,Since,relative,Locations,relative,project,file,Location,means,that,files,located,one,directory,down,How,build,from,command,line,with,different,location,for,application,easily,done,giving,directories,your,install,project,virtual,text,Location,Location,directory,specified,virtual,text,you,can,then,specify,new,value,for,that,virtual,text,command,line,when,you,build,Let's,say,you,have,main,application,directory,you,specify,Location,that,directory,<%BaseDir%>,Then,your,project,file,you,can,create,new,virtual,text,variable,called,BaseDir,with,value,Now,you,want,build,from,command,line,with,different,directory,location,for,your,application,you,installjammer,DBaseDir,mpi,option,lets,you,specify,virtual,text,variable,value,that,overridden,install,project,before,installer,built,last,argument,command,line,always,path,your,project,file,Using,above,command,your,project,built,with,your,application,files,located,Asked,Questions[$XTITELEND$][$XKEYS$]Frequently,Asked,Questions[$XKEYSEND$]`;";
s[37] = "Getting to Know the Install Builder^GettingToKnowTheInstallBuilder.html^Read through the following sections to help you get to know the install builder a little better.  Ea...^Getting to Know the Install Builder^Read,through,following,sections,help,you,get,know,install,builder,little,better,Each,section,descibes,different,pieces,install,builder,how,use,Know,Install,Builder[$XTITELEND$][$XKEYS$]Getting,Know,Install,Builder[$XKEYSEND$]`;";
s[38] = "Install Builder Preferences^InstallBuilderPreferences.html^DirectoriesProject Directory LocationThis preference defines the location of your InstallJamme...^Install Builder Preferences^Directories,Project,Directory,Location,preference,defines,location,your,InstallJammer,projects,You,can,choose,save,your,projects,anywhere,but,InstallJammer,use,property,default,location,for,new,projects,when,they,created,Custom,Theme,Directory,Location,preference,defines,where,InstallJammer,look,for,custom,themes,that,you,may,have,for,your,version,InstallJammer,directory,specified,must,contain,subdirectory,for,every,theme,theme,added,list,available,themes,when,creating,new,project,Custom,Action,Directory,Location,preference,defines,where,InstallJammer,look,for,custom,actions,that,you,may,have,for,your,version,InstallJammer,directory,can,contain,any,number,action,files,that,then,appear,list,available,actions,under,category,Custom,Actions,Custom,Condition,Directory,Location,preference,defines,where,InstallJammer,look,for,custom,actions,that,you,may,have,for,your,version,InstallJammer,directory,can,contain,any,number,condition,files,that,then,appear,list,available,conditions,under,category,Custom,Conditions,External,Programs,File,Explorer,preference,defines,default,file,explorer,when,using,explore,features,InstallJammer,one,not,specified,InstallJammer,attempt,use,default,file,explorer,for,your,system,Windows,InstallJammer,always,use,Windows,Explorer,unless,specified,UNIX,systems,InstallJammer,attempt,determine,best,file,explorer,based,your,window,manager,Help,Browser,preference,defines,web,browser,you,wish,use,when,browsing,InstallJammer's,help,documentation,default,InstallJammer,attempt,find,best,browser,based,your,system,environment,list,acceptable,browsers,InstallJammer,Almost,any,web,browser,should,work,properly,Editor,preference,defines,external,editor,program,use,when,editing,long,text,within,install,builder,editor,specified,clicking,button,edit,text,field,save,text,temporary,file,then,launch,external,editor,that,file,builder,then,watch,file,for,changes,repopulate,project,with,new,data,Note,that,InstallJammer,not,create,console,window,for,editing,with,text,based,editor,InstallJammer,Update,Check,for,updates,InstallJammer,startup,preference,true,InstallJammer,check,for,new,versions,itself,everytime,started,false,you,must,check,for,updates,yourself,using,Check,for,Updates,Now,button,tab,Use,proxy,server,true,InstallJammer,use,HTTP,proxy,server,when,checking,for,its,updates,Proxy,Host,hostname,for,proxy,server,use,Proxy,Port,port,for,proxy,server,use,Builder,Preferences[$XTITELEND$][$XKEYS$]Install,Builder,Preferences[$XKEYSEND$]`;";
s[39] = "Install Builder Command Line Options^Command-LineOptions.html^InstallJammer can be started with several command-line options that make building installs easier fo...^Install Builder Command Line Options^InstallJammer,can,started,with,several,command,line,options,that,make,building,installs,easier,for,some,jobs,most,cases,these,used,provide,quick,builds,single,project,build,projects,using,scripts,other,programs,installjammer,option,option,build,ProjectFile,you,building,from,command,line,generally,recommended,that,build,last,option,before,project,file,name,tells,InstallJammer,where,options,switches,end,where,project,file,name,begins,Every,argument,after,build,joined,together,make,file,name,you,can,include,spaces,command,line,InstallJammer,join,properly,same,true,for,other,options,Anytime,argument,encountered,that,doesn't,match,one,given,switches,options,its,value,appended,value,previous,option,allows,for,spaces,command,line,InstallJammer,join,properly,where,makes,most,sense,installjammer,DAppName,Application,quick,build,build,file,mpi,arguments,command,line,joined,like,DAppName,Application,quick,build,build,file,mpi,Command,line,Options,build,option,specifies,that,given,project,file,should,loaded,built,without,loading,install,builder,GUI,option,good,for,building,installs,from,other,programs,regular,times,using,scheduling,should,generally,last,switch,specified,before,project,file,name,build,dir,<directory>,Specifies,directory,use,temporary,directory,when,building,InstallJammer,attempt,create,directory,does,not,already,exist,build,for,release,option,specified,project,file,being,built,built,for,final,release,build,log,file,Specifies,filename,save,build,log,information,default,build,log,project,directory,control,script,<scriptFile>,option,specifies,script,source,when,InstallJammer,building,from,command,line,D<option>,<value>,Set,value,option,value,DAppName,Software,override,default,value,stored,AppName,with,value,Software,useful,for,over,setting,options,different,installs,during,command,line,builds,that,single,project,file,can,manipulated,many,different,builds,Any,number,options,can,specified,manner,Each,one,processed,order,which,was,specified,command,line,help,Displays,usage,information,for,InstallJammer,output,dir,<directory>,Specifies,output,directory,store,resulting,installers,when,they,built,InstallJammer,attempt,create,directory,does,not,already,exist,platform,<platform>,option,can,specified,with,option,tell,InstallJammer,only,build,certain,platforms,Each,platform,name,specified,with,built,instead,building,all,platforms,default,option,More,than,one,platform,can,specified,each,platform,appended,build,list,quick,build,option,specified,given,project,file,rebuilt,without,repackaging,files,for,installer,just,quick,build,GUI,quiet,Turn,off,messages,from,InstallJammer,while,building,Errors,still,reported,stderr,test,option,can,specified,with,build,option,tell,InstallJammer,test,install,once,has,been,built,install,builder,GUI,still,not,loaded,install,execute,when,build,complete,verbose,option,tells,InstallJammer,show,verbose,output,when,building,version,Display,version,information,for,InstallJammer,exit,Builder,Command,Line,Options[$XTITELEND$][$XKEYS$]Command,Line,Options[$XKEYSEND$]`;";
s[40] = "Application Information^ApplicationInformation.html^Application InformationApplication IDA unique identifier for this application.The Applicat...^Application Information^Application,Information,Application,unique,identifier,for,application,Application,defined,when,project,first,created,used,identify,application,subsequent,installs,same,machine,during,uninstallation,Application,can,accessed,with,<%ApplicationID%>,vitrual,text,Application,Name,name,application,you,installing,name,used,throughout,install,when,application,name,used,can,accessed,using,virtual,text,<%AppName%>,Application,URL,main,web,address,for,information,about,your,application,used,for,information,tell,users,where,they,can,find,your,application,web,application,URL,can,accessed,using,<%ApplicationURL%>,virtual,text,Company,Your,company,name,field,can,used,throughout,install,easy,way,retrieve,name,company,producing,application,default,InstallJammer,uses,company,its,default,install,location,company,name,can,accessed,using,virtual,text,<%Company%>,Copyright,property,specifies,your,copyright,notice,any,included,Copyright,field,resources,Windows,executable,copyright,can,accessed,using,<%Copyright%>,virtual,text,Install,Icon,icon,used,throughout,install,icon,path,given,relative,path,InstallJammer,first,attempt,locate,image,file,project's,own,directory,then,InstallJammer's,root,directory,default,all,panes,within,install,that,contain,icon,use,icon,but,most,install,themes,allow,you,change,icon,for,each,pane,pane,not,modified,icon,used,when,applicable,install,icon,can,accessed,using,virtual,text,<%Icon%>,Install,Image,main,image,used,throughout,install,image,path,given,relative,path,InstallJammer,first,attempt,locate,image,file,project's,own,directory,then,InstallJammer's,root,directory,default,all,panes,within,install,that,contain,image,use,image,but,most,install,themes,allow,you,change,image,for,each,pane,pane,not,modified,image,used,when,applicable,install,image,can,accessed,using,virtual,text,<%Image%>,Install,Version,numeric,version,used,InstallJammer,for,your,application,Install,versions,used,during,installation,determine,what,version,files,within,install,useful,for,when,you,want,overwrite,certain,files,that,may,already,exist,but,only,install,has,higher,version,version,can,accessed,using,virtual,text,<%InstallVersion%>,Short,Application,Name,shortened,name,for,your,application,usually,all,lowercase,contains,spaces,used,UNIX,systems,installation,directory,Even,though,most,all,modern,UNIX,systems,support,spaces,file,directory,names,it's,usually,considered,bad,form,short,application,name,can,accessed,using,virtual,text,<%ShortAppName%>,Upgrade,Application,property,not,null,specifies,Application,another,install,project,that,project,meant,upgrade,upgrade,installer,one,that,skips,some,procedures,regular,installer,adds,its,information,uninstall,previously,installed,application,upgrade,application,can,accessed,using,<%UpgradeApplicationID%>,virtual,text,Version,String,version,application,version,string,for,you,identify,release,version,your,application,InstallJammer,does,not,use,version,for,anything,can,anything,you,like,version,string,can,accessed,using,virtual,text,<%Version%>,Install,Features,Allow,Language,Selection,property,true,user,allowed,select,language,use,for,messages,during,installation,false,Default,Language,always,used,Cancelled,Install,Action,What,InstallJammer,should,install,cancelled,user,cancels,install,after,main,installation,files,has,already,begun,some,application,already,copied,onto,system,option,lets,installer,rollback,any,modifications,that,have,been,made,installer,since,started,running,Default,Language,property,specifies,default,language,use,when,installing,InstallJammer,attempt,determine,best,language,based,user's,system,settings,but,settings,can,found,language,default,language,selection,language,selection,allowed,default,language,always,used,Default,System,Language,property,true,installer,use,default,language,target,system,that,language,has,been,compiled,into,installer,system,language,not,part,installer,property,false,Default,Language,used,Enable,Response,File,property,true,enable,response,file,save,response,file,command,line,options,your,installer,allows,user,pass,save,response,file,when,running,installer,save,responses,output,file,that,can,then,read,back,during,later,installs,using,response,file,option,very,handy,for,users,who,need,run,installer,multiple,machines,for,multiple,people,where,should,all,run,same,way,Read,more,about,what,virtual,text,included,response,file,Add,Response,File,Info,action,Extract,Solid,Archives,Startup,property,true,installer,includes,any,solid,archives,they,extracted,soon,installer,starts,user,shown,progress,bar,archives,extracted,option,only,useful,you,need,your,files,extracted,before,you,begin,actual,installation,process,default,InstallJammer,extract,solid,archives,just,before,begins,actual,file,installation,Wizard,Height,Specifies,height,installer,uninstaller,wizard,window,Defaults,whatever,default,for,chosen,installer,theme,Wizard,Width,Specifies,width,installer,uninstaller,wizard,window,Defaults,whatever,default,for,chosen,installer,theme,Project,Preferences,Command,Line,Failure,Action,What,InstallJammer,should,file,missing,from,install,when,building,from,command,line,When,InstallJammer,building,from,command,line,passing,option,user,doesn't,have,ability,recognize,problems,correct,option,specifically,deals,with,case,that,file,that,should,part,install,missing,InstallJammer,needs,know,what,Compression,Level,Define,compression,level,use,when,packing,files,tells,InstallJammer,what,level,compression,use,when,packing,files,installer,means,lower,compression,levels,but,faster,rate,packing,unpacking,means,higher,compression,but,sometimes,slower,unpacking,default,level,Compression,Method,specifies,default,compression,method,use,when,packing,files,into,installer,choices,lzma,lzma,solid,none,zlib,zlib,solid,solid,archive,when,all,files,packaged,actually,packed,into,single,file,before,they,compressed,into,installer,has,advantage,much,higher,rate,compression,since,entire,file,compressed,once,instead,bunch,little,files,compressed,separately,Solid,archives,cannot,read,directly,from,within,installer,though,they,must,first,extracted,temporary,location,before,they,can,installed,require,target,system,have,temporary,location,that,big,enough,hold,your,entire,uncompressed,archive,before,installation,begins,ZLIB,default,compression,method,because,fast,efficient,doesn't,require,separate,extraction,step,LZMA,can,much,better,compression,method,some,cases,but,highly,recommended,that,you,not,use,lzma,compression,unless,solid,archive,LZMA,compression,very,slow,doesn't,gain,much,most,files,over,ZLIB,but,can,big,win,when,using,solid,archives,you,have,larger,file,that,would,benefit,from,LZMA,compression,you,can,always,compress,just,that,one,file,specifying,Compression,Method,file,group,tree,InstallJammer,can,easily,compress,every,single,file,installer,with,different,compression,method,you,want,Default,Directory,Location,property,set,specifies,default,Location,use,for,all,files,directories,that,direct,descendants,file,group,own,Location,property,not,set,allows,project,specify,that,every,file,directory,project,should,located,particular,place,system,relative,project,file,for,example,file,directory,specifies,its,own,Location,overrides,default,value,Include,Install,Debugging,Options,Include,command,line,debugging,options,install,During,testing,InstallJammer,includes,small,set,debugging,options,that,can,passed,installs,command,line,These,options,allow,install,builder,debug,install,while,running,Debugging,options,should,turned,off,before,distributing,release,your,installer,can,done,disabling,option,building,your,installs,for,final,release,Preserve,UNIX,File,Permissions,property,true,InstallJammer,record,current,file,permissions,each,file,directory,stored,installer,restore,when,they,installed,Any,permissions,which,have,been,set,for,file,directory,project,override,these,permissions,but,default,permissions,recorded,build,system,restored,target,install,system,Preserve,Windows,File,Attributes,property,true,InstallJammer,remember,file,attributes,each,file,directory,stored,installer,restore,when,they,installed,Any,attributes,which,have,been,set,for,file,directory,project,override,these,attributes,but,default,attributes,recorded,build,system,restored,target,install,system,Refresh,File,List,Before,Building,property,true,InstallJammer,automatically,search,for,new,deleted,files,directories,before,building,any,installers,automatically,pick,any,changes,made,directories,your,installer,before,new,installers,built,Save,Only,Toplevel,Directories,option,tells,InstallJammer,that,you,only,want,save,files,directories,that,direct,child,file,group,means,that,directories,file,group,not,saved,recursively,option,useful,for,building,projects,dynamically,using,command,line,tools,where,you,don't,want,GUI,builder,save,files,for,you,File,Groups,Directories,project,have,Save,Files,property,which,basically,acts,finer,grained,version,property,You,can,set,that,particular,File,Group,directory,should,not,save,its,files,instead,entire,project,Saving,only,toplevel,directories,should,used,with,caution,Any,change,you,make,any,file,directory,that,not,toplevel,lost,since,not,saved,install,project,Skip,Unused,File,Groups,property,true,means,that,InstallJammer,skip,any,file,groups,finds,that,not,being,used,component,can,easy,way,disabling,entire,file,group,without,removing,from,project,property,false,all,file,groups,included,installer,regardless,whether,they,used,Information[$XTITELEND$][$XKEYS$]Application,Information[$XKEYSEND$]`;";
s[41] = "Platform Information^PlatformInformation.html^Platform options describe options that are specific to each platform in an install project. When an ...^Platform Information^Platform,options,describe,options,that,specific,each,platform,install,project,When,install,built,these,options,saved,only,installer,for,that,platform,Active,Whether,not,platform,active,When,platform,inactive,nothing,InstallJammer,use,affect,Mainly,means,that,installer,for,inactive,platform,not,built,but,several,other,things,also,disabled,when,platform,inactive,All,properties,for,platform,still,saved,with,your,project,platform,can,easily,enabled,again,later,time,You,should,mark,platform,inactive,you,don't,plan,distribute,your,application,for,that,platform,Build,Separate,Archives,property,true,installer,for,platform,built,separate,archive,files,instead,being,built,single,executable,file,useful,for,splitting,larger,files,for,when,installation,done,from,DVD,Default,Destination,Directory,default,destination,directory,for,your,application,where,your,application,default,installing,target,system,user,does,not,modify,directory,not,given,option,modify,directory,Default,Directory,Permission,Mask,UNIX,only,default,permission,mask,use,when,installing,directories,When,directory,created,target,system,during,installation,option,tells,InstallJammer,default,permission,mask,use,when,creating,separate,permission,has,been,set,for,directory,override,default,permission,Default,File,Permission,Mask,UNIX,only,default,permission,mask,use,when,installing,files,When,file,installed,target,system,during,installation,option,tells,InstallJammer,default,permission,mask,use,when,installing,separate,permission,has,been,set,for,file,override,default,permission,Default,Install,Mode,property,sets,default,install,mode,for,installer,user,has,not,specified,different,mode,command,line,user,not,given,option,specify,mode,allows,you,make,console,silent,only,installer,that,user,cannot,use,any,other,way,Default,Program,Folder,Windows,only,default,Program,Folder,name,under,user's,menu,default,Program,Folder,store,your,application's,shortcuts,Windows,platform,you,create,shortcuts,<%ProgramFolder%>,directory,default,name,for,that,folder,Default,Setup,Type,default,setup,type,chosen,during,installation,user,allowed,change,setup,type,during,installation,default,one,chosen,user,not,allowed,change,setup,type,setup,type,that,installed,default,Fall,Back,Console,Mode,UNIX,only,property,tells,InstallJammer,that,installer,should,fall,back,console,mode,installation,GUI,mode,fails,initialize,for,some,reason,means,that,user,chooses,GUI,mode,defaulted,one,but,they,not,have,GUI,environment,installer,automatically,detect,launch,into,console,install,Include,Windows,API,Extension,Windows,only,Whether,not,pack,TWAPI,extension,into,your,installer,Tcl,Windows,API,Extension,provides,commands,Tcl,scripting,level,some,internal,Windows,APIs,provides,ability,for,you,script,Windows,specific,features,into,your,installer,like,services,user,account,commands,etc,that,would,not,normally,available,Install,Executable,Description,Windows,only,property,describes,text,used,File,Description,field,Windows,install,executable,default,<%AppName%>,<%Version%>,Setup,Install,Executable,Name,name,your,installer,executable,file,that,InstallJammer,create,when,builds,your,installer,installer,built,build,subdirectory,your,project,directory,Install,Program,Folder,for,All,Users,Windows,only,option,true,InstallJammer,create,Program,Folder,under,Start,menu,for,all,users,system,not,just,user,installing,application,Program,Executable,main,executable,for,your,application,field,contains,main,executable,for,your,application,used,throughout,install,for,things,like,creating,shortcuts,your,application,starting,your,application,when,install,complete,your,program,does,not,have,actual,program,entry,point,you,can,just,leave,blank,Program,License,LICENSE,file,for,your,application,Your,application,not,required,contain,LICENSE,file,but,some,you,have,one,value,tells,InstallJammer,where,look,for,when,offering,user,ability,read,also,appropriate,most,cases,create,shortcut,your,LICENSE,file,your,Program,Folder,Program,Readme,README,file,for,your,application,Your,application,not,required,contain,README,file,but,some,you,have,one,value,tells,InstallJammer,where,look,for,when,offering,user,ability,read,also,appropriate,most,cases,create,shortcut,your,README,file,your,Program,Folder,Prompt,for,Root,Password,property,true,Require,Root,User,true,user,asked,specify,root,password,continue,instead,just,getting,failure,message,installer,exiting,When,user,enters,root,password,installer,restarted,with,same,options,InstallJammer,attempts,use,given,tools,for,current,desktop,environment,available,KDE,use,kdesu,Gnome,use,gksu,gnomesu,found,All,other,environments,attempt,use,one,previously,mentioned,tools,found,Finally,none,these,tools,can,found,user,either,get,xterm,they,not,running,from,console,simply,ask,for,password,console,they,Require,Administrator,Windows,only,property,true,resulting,installer,only,work,user,administrator,target,Windows,system,For,Vista,beyond,means,installer,built,executable,that,requires,administrator,privileges,user,asked,for,administrator,password,before,install,executed,earlier,versions,Windows,installer,check,see,current,user,Administrators,group,show,error,message,exit,user,not,administrator,Require,Root,User,UNIX,only,Whether,not,user,must,install,application,root,Some,applications,require,root,user,install,UNIX,system,option,tells,InstallJammer,that,user,cannot,run,install,unless,run,root,InstallJammer,check,username,during,install,initialization,fail,with,error,message,user,not,root,Root,Destination,Directory,UNIX,only,default,destination,directory,when,user,installing,root,most,cases,application,can,either,install,system,location,user,root,into,user's,home,directory,user,not,root,root,destination,directory,tells,InstallJammer,where,application,should,installed,user,installing,root,user,not,root,option,left,blank,InstallJammer,fall,back,Default,Destination,Directory,for,all,installs,option,does,not,need,Require,Root,User,default,destination,adjusted,user,root,even,you,don't,require,root,unless,blank,Use,Uncompressed,Binaries,Windows,only,property,true,Windows,installers,built,uncompressed,binaries,Installers,built,with,InstallJammer,compressed,using,varying,compression,technologies,for,each,platform,attempt,keep,installers,smaller,cost,slight,increase,startup,time,Some,anti,virus,software,can,mistakenly,mark,compressed,binary,having,virus,when,they,actually,don't,For,reason,sometimes,best,build,with,original,uncompressed,binaries,Windows,platforms,you,build,with,uncompressed,binaries,your,installers,several,megabytes,larger,than,compressed,versions,Windows,File,Icon,Windows,only,ico,associate,with,your,installer,icon,path,given,relative,path,InstallJammer,first,attempt,locate,ico,file,project's,own,directory,then,InstallJammer's,root,directory,specified,icon,shown,Windows,Explorer,main,icon,title,bar,your,installer,use,values,file,You,must,specify,icon,file,that,contains,all,possible,size,color,combinations,for,icon,default,icon,associated,with,installers,Windows,some,icons,have,been,provided,that,meet,specifications,Information[$XTITELEND$][$XKEYS$]Platform,Information[$XKEYSEND$]`;";
s[42] = "Package and Archive Information^PackageAndArchiveInformation.html^Package InformationPackage information can be used by you in your own installer, but its main use ...^Package and Archive Information^Package,Information,Package,information,can,used,you,your,own,installer,but,its,main,use,actions,InstallJammer,that,register,your,application,with,different,packaging,systems,Since,most,information,same,across,package,databases,section,provides,easy,way,specify,information,once,then,let,InstallJammer,use,right,bits,for,each,different,package,system,information,used,Register,Package,action,you,plan,registering,your,application,with,system,package,manager,highly,recommended,that,you,fill,all,information,for,your,package,Some,package,managers,not,accept,package,that,missing,pieces,following,data,Package,Description,long,text,description,your,package,can,include,multiple,lines,that,describe,what,your,application,what,does,Package,License,should,one,line,description,license,your,application,uses,usually,something,very,simple,GPL,MPL,Apache,etc,Package,Maintainer,name,mail,address,person,who,maintains,your,application,should,you,want,contacted,form,Person's,Name,<email@address,com>,Package,Name,name,your,application,have,package,database,should,all,lowercase,short,should,not,full,name,your,application,Package,Packager,name,mail,person,who,packages,your,application,would,you,person,building,installer,Package,Release,release,version,your,application,default,InstallJammer,uses,<%PatchVersion%>,from,your,<%InstallVersion%>,for,value,Package,Summary,one,line,summary,description,your,package,short,description,that,briefly,describes,your,package,Package,Description,gives,long,version,Package,Version,version,your,application,InstallJammer,uses,<%MajorVersion%>,<%MinorVersion%>,from,your,<%InstallVersion%>,default,since,that's,what,most,package,managers,expect,Tar,Archive,Information,section,describes,information,for,building,tar,file,your,application,section,active,InstallJammer,build,tar,file,alongside,your,other,platform,specific,installers,Active,true,InstallJammer,build,tar,file,your,application,when,builds,rest,your,installers,Compression,Level,level,gzip,compression,use,when,compressing,your,tar,file,file,not,gzipped,all,just,plain,tar,file,You,want,remove,from,output,file,name,you,not,using,compression,Default,Directory,Permission,Mask,default,permission,mask,use,when,storing,directories,separate,permission,has,been,set,for,directory,override,default,permission,Default,File,Permission,Mask,default,permission,mask,use,when,storing,files,separate,permission,has,been,set,for,file,override,default,permission,Output,File,Name,name,tar,file,output,file,subdirectory,your,project,directory,alongside,your,other,installers,Virtual,Text,Map,map,strings,use,each,file,directory,stored,tar,file,string,map,list,pairs,that,specify,that,one,string,should,mapped,another,default,map,all,instances,<%InstallDir%>,desination,file,name,<%ShortAppName%>,That,means,that,all,files,being,installed,<%InstallDir%>,end,subdirectory,after,your,short,application,name,with,rest,directory,structure,intact,Zip,Archive,Information,section,describes,information,for,building,zip,file,your,application,section,active,InstallJammer,build,zip,file,alongside,your,other,platform,specific,installers,Active,true,InstallJammer,build,zip,file,your,application,when,builds,rest,your,installers,Compression,Level,level,compression,use,when,compressing,your,zip,file,Output,File,Name,name,zip,file,output,file,subdirectory,your,project,directory,alongside,your,other,installers,Virtual,Text,Map,map,strings,use,each,file,directory,stored,zip,file,string,map,list,pairs,that,specify,that,one,string,should,mapped,another,default,map,all,instances,<%InstallDir%>,desination,file,name,<%ShortAppName%>,That,means,that,all,files,being,installed,<%InstallDir%>,end,subdirectory,after,your,short,application,name,with,rest,directory,structure,intact,Archive,Information[$XTITELEND$][$XKEYS$]Package,Archive,Information[$XKEYSEND$]`;";
s[43] = "Groups and Files^GroupsAndFiles.html^The file groups tree is used to coordinate the files and directories that will be included in your i...^Groups and Files^file,groups,tree,used,coordinate,files,directories,that,included,your,installer,Files,directories,stored,under,file,group,file,groups,then,made,part,component,multiple,components,When,install,first,created,single,file,group,called,Program,Files,created,with,project,you,only,creating,simple,installer,for,your,application,one,file,group,usually,all,that,you,need,See,Files,Directories,for,more,information,about,files,directories,that,contained,within,file,groups,File,Group,Properties,File,groups,further,defined,individual,properties,When,file,group,created,setup,with,default,set,properties,that,you,can,alter,you,need,Each,file,group,has,set,standard,properties,that,properties,that,shared,many,components,InstallJammer,set,Advanced,Properties,that,specific,file,groups,Standard,Properties,See,Standard,Properties,Active,file,group,marked,inactive,all,files,directories,included,that,group,not,included,installer,when,built,Compression,Method,property,defines,method,compression,for,given,file,group,All,other,files,directories,given,file,group,have,same,compression,method,compression,method,left,blank,default,compression,method,for,project,used,Destination,Directory,directory,file,group,installed,target,system,default,<%InstallDir%>,main,installation,directory,Display,Name,property,set,specifies,name,display,when,name,file,group,shown,during,installation,property,left,blank,actual,name,file,group,used,File,Update,Method,property,tells,InstallJammer,what,with,files,when,updating,target,system,Updating,when,file,already,exists,need,determine,what,with,file,Follow,File,Links,property,true,any,linked,files,found,within,file,group,followed,file,they,link,stored,actual,file,installer,property,false,any,links,saved,links,installer,recreated,link,target,system,during,installation,Name,name,file,group,Save,Files,property,false,only,toplevel,directories,file,group,saved,All,files,subdirectories,top,directories,not,stored,project,file,discovered,build,time,useful,when,you,only,want,store,directory,but,want,everything,that,directory,built,dynamically,Size,size,property,specified,tells,InstallJammer,override,what,may,actually,size,files,stored,file,group,use,given,size,instead,size,should,given,integer,only,which,automatically,converted,readable,size,during,installation,Version,property,tells,InstallJammer,what,Install,Version,store,for,file,group,target,system,property,left,blank,InstallJammer,use,global,<%InstallVersion%>,variable,for,project,Build,Platforms,list,all,platforms,that,supported,InstallJammer,whether,not,file,group,should,built,for,each,platform,platform,marked,file,group,not,included,when,installer,for,that,platform,built,possible,build,file,group,into,multiple,platforms,then,not,install,file,group,based,parameters,during,installation,but,option,specifically,tells,InstallJammer,not,even,include,file,group,for,given,platform,Permissions,feature,allows,you,set,file,permissions,for,given,file,group,file,directory,default,permissions,set,which,means,that,file,directory,installed,with,some,default,permissions,target,system,Permissions,file,group,refer,directory,that,created,for,file,group,not,all,files,file,group,Directories,files,can,set,with,own,permissions,set,group,when,multiple,files,directories,selected,Both,Windows,attributes,UNIX,permissions,provided,applied,based,target,system,file,has,both,Windows,attributes,UNIX,permissions,Windows,attributes,applied,when,file,installed,Windows,system,UNIX,permissions,applied,when,installed,UNIX,system,Creating,new,file,group,Click,Add,New,File,Group,button,toolbar,add,new,file,group,your,install,new,file,group,created,with,default,values,that,you,can,change,after,its,creation,Your,new,file,group,bottom,list,Deleting,file,group,Click,Delete,button,toolbar,delete,selected,nodes,from,your,install,can,also,done,through,Delete,key,your,keyboard,Any,selected,nodes,file,group,tree,deleted,includes,files,directories,file,groups,Adding,files,file,group,Click,Add,Files,File,Group,button,toolbar,add,new,files,selected,file,group,file,dialog,open,ask,you,select,files,you,wish,add,file,group,Files,can,also,added,program,folder,dragging,dropping,from,your,file,explorer,Most,major,window,managers,supported,Adding,directories,file,group,Click,Add,Directory,File,Group,button,toolbar,add,new,files,selected,file,group,directory,selection,dialog,open,ask,you,select,directory,you,wish,add,file,group,Directories,can,also,added,program,folder,dragging,dropping,from,your,file,explorer,Most,major,window,managers,supported,Deleting,files,from,file,group,Click,Delete,button,toolbar,delete,selected,nodes,from,your,install,can,also,done,through,Delete,key,your,keyboard,Selected,nodes,file,group,tree,including,files,directories,directly,beneath,file,group,deleted,from,project,Only,files,directories,that,directly,beneath,file,group,can,deleted,Subdirectories,files,that,contained,within,directories,cannot,deleted,from,project,you,not,wish,include,files,directories,that,contained,subdirectory,you,simply,uncheck,Files,directories,that,unchecked,not,included,install,when,built,done,that,once,you,include,directory,file,group,InstallJammer,maintain,entire,directory,structure,regardless,what,included,installer,You,can,always,add,other,subdirectories,directly,file,group,have,install,anywhere,you,like,based,Destination,Directory,Excluding,files,directories,from,project,Files,directories,can,excluded,from,build,unchecking,activating,file,group,tree,Any,file,directory,that,does,not,have,check,mark,considered,inactive,ignored,InstallJammer,when,building,your,installer,Disabling,directory,automatically,disable,everything,contained,that,directory,even,other,files,directories,directory,checked,Once,you,disable,directory,all,its,subdirectories,files,disabled,well,you,wish,disable,entire,directory,but,still,include,subdirectories,beneath,you,need,add,those,subdirectories,directly,file,group,You,can,modify,install,locations,through,Destination,Directory,property,File,Explorer,File,Explorer,button,bring,directory,file,explorer,which,can,used,drag,drop,files,directories,into,file,groups,you,did,not,specify,file,explorer,your,preferences,InstallJammer,attempt,find,best,one,based,your,window,manager,Windows,defaults,Windows,Explorer,You,can,specify,exactly,which,file,explorer,you,want,use,your,preferences,InstallJammer,supports,drag,drop,most,major,window,managers,Files[$XTITELEND$][$XKEYS$]Groups,Files[$XKEYSEND$]`;";
s[44] = "Files and Directories^FilesAndDirectories.html^Files and directories are added to your project in File Groups.  Each file or directory in your proj...^Files and Directories^Files,directories,added,your,project,File,Groups,Each,file,directory,your,project,has,its,own,set,properties,that,override,default,values,specified,its,File,Group,default,file,directory,inherit,properties,its,parents,tree,going,back,far,File,Group,When,adding,files,directories,file,group,they,begin,with,specific,options,which,means,that,they,inherit,properties,File,Group,you,modify,properties,directory,automatically,affect,properties,all,files,subdirectories,that,directory,Modifying,properties,file,only,change,that,file,You,can,also,select,multiple,files,directories,change,properties,all,once,important,remember,that,properties,file,groups,directories,propagate,down,affect,all,files,directories,beneath,Looking,File,Directory,Details,show,you,what,values,currently,affect,selected,file,directory,Files,that,have,been,newly,added,project,since,last,time,project,was,loaded,appear,blue,makes,easy,detect,when,InstallJammer,has,modified,current,project,because,has,automatically,picked,new,file,while,recursively,searching,through,directories,Files,that,disabled,greyed,out,mean,that,InstallJammer,cannot,find,file,local,system,file,may,have,been,deleted,system,location,file,may,have,changed,You,can,find,file,again,changing,its,Location,property,changing,Location,its,containing,directory,Files,that,cannot,found,not,included,when,install,built,Files,cannot,deleted,from,included,directory,file,tree,InstallJammer,keeps,track,entire,structure,directory,deleting,file,from,project,would,only,result,InstallJammer,finding,again,next,time,you,build,you,don't,want,include,file,your,installer,just,uncheck,mark,inactive,Standard,Properties,See,Standard,Properties,Active,file,marked,inactive,that,file,not,included,when,installer,built,directory,marked,inactive,that,directory,all,files,directories,beneath,not,included,when,installer,built,Compression,Method,property,defines,method,compression,for,selected,file,directory,specified,directory,all,other,files,directories,beneath,selected,directory,have,same,compression,method,compression,method,left,blank,default,compression,method,for,project,used,Destination,Directory,specifies,directory,target,system,that,directory,file,install,into,Modifying,Destination,Directory,directory,automatically,affect,destination,every,file,directory,that,directory,since,they,inherit,properties,from,parent,Desination,Directory,set,directory,means,name,directory,where,directory,created,target,system,Destination,Directory,for,file,directory,target,file,placed,INTO,target,system,See,Install,Location,under,File,Directory,Details,know,for,sure,where,given,file,directory,installed,File,Update,Method,property,tells,InstallJammer,how,behave,when,installing,file,directory,target,system,that,already,exists,Modifying,File,Update,Method,directory,automatically,affect,update,method,every,file,directory,that,directory,does,not,modify,File,Update,Method,property,but,they,inherit,from,parent,Location,property,specifies,location,given,file,directory,local,system,When,changing,location,file,directory,you,can,specify,that,location,provided,should,stored,project,file,itself,your,local,preferences,location,stored,your,local,preferences,not,affect,location,project,file,only,used,when,project,loaded,current,machine,allows,developers,specify,different,locations,for,projects,own,machines,without,having,change,locations,within,project,file,itself,location,specified,location,file,directory,derived,from,its,parents,going,tree,Looking,File,Details,for,particular,file,directory,show,you,location,where,InstallJammer,has,found,Target,Filename,file,only,property,specifies,name,that,file,should,created,target,system,during,installation,Destination,Directory,can,specify,where,file,should,installed,but,property,specifies,what,named,when,gets,Version,property,tells,InstallJammer,what,Install,Version,store,for,file,directory,target,system,Modifying,Version,directory,automatically,affect,version,every,file,directory,that,directory,does,not,modify,Version,property,but,they,inherit,from,parent,File,Directory,Details,property,block,tell,you,all,information,about,selected,file,directory,based,its,own,properties,properties,has,inherited,from,its,parents,read,only,block,contains,mostly,information,from,build,system,about,file,directory,but,few,properties,worth,noting,Compression,Method,method,that,file,compressed,with,derived,from,its,parents,from,default,compression,method,for,project,File,Update,Method,property,tells,you,how,selected,file,directory,behave,during,installation,target,already,exists,target,system,selected,object,has,File,Update,Method,its,own,inherit,tree,until,finds,one,Install,Location,property,tells,you,how,where,selected,file,directory,installed,target,system,selected,object,has,Destination,Directory,its,own,inherit,tree,until,finds,one,Location,location,local,system,where,file,directory,resides,can,specified,Location,property,derived,from,parents,going,tree,Version,property,tells,you,Install,Version,selected,file,directory,when,installed,version,stored,for,future,installations,after,install,complete,selected,object,has,Version,its,own,inherit,tree,until,finds,one,Version,found,any,parent,global,<%InstallVersion%>,for,project,used,Permissions,feature,allows,you,set,file,permissions,for,given,file,directory,default,permissions,set,which,means,that,file,directory,installed,with,some,default,permissions,target,system,Permissions,for,directory,not,inherited,files,directories,underneath,permissions,only,apply,that,directory,Multiple,files,directories,can,selected,permissions,set,all,same,time,Both,Windows,attributes,UNIX,permissions,provided,applied,based,target,system,file,has,both,Windows,attributes,UNIX,permissions,Windows,attributes,applied,when,file,installed,Windows,system,UNIX,permissions,applied,when,installed,UNIX,system,Save,Files,property,false,all,files,subdirectories,directory,not,saved,project,file,When,directory,built,all,its,contents,dynamically,generated,from,whatever,currently,directory,allows,for,adding,directories,where,all,contents,only,stored,build,time,property,works,like,finer,grained,version,Save,Only,Toplevel,Directories,project,preference,Directories[$XTITELEND$][$XKEYS$]Files,Directories[$XKEYSEND$]`;";
s[45] = "Components^Components.html^Components are used to group file groups in your install into user-friendly categories.  Each compon...^Components^Components,used,group,file,groups,your,install,into,user,friendly,categories,Each,component,can,contain,any,file,groups,your,project,user,presented,with,option,they,can,choose,which,components,they,wish,install,default,single,component,called,Default,Component,created,for,your,project,contains,Program,Files,file,group,Standard,Properties,See,Standard,Properties,Checked,property,true,component,displayed,checked,when,first,added,component,tree,automatically,set,active,status,component,depending,value,when,first,added,tree,Component,Group,property,specified,tells,InstallJammer,put,component,into,specific,group,with,other,components,Each,component,that,shares,exact,same,name,group,grouped,together,radio,buttons,instead,check,buttons,You,must,make,sure,that,each,component,you,want,radio,group,shares,same,exact,Component,Group,name,Name,name,component,Required,Component,option,tells,InstallJammer,that,component,required,for,all,installations,therefore,not,available,for,user,uncheck,during,installation,component,still,appear,list,available,components,but,disabled,for,user,Selectable,property,set,component,displayed,component,tree,header,with,check,radio,button,Show,Component,property,false,component,not,added,component,tree,when,drawn,can,used,hide,components,that,you,don't,want,shown,during,installation,Size,size,property,specified,tells,InstallJammer,override,what,may,actually,size,files,stored,component,use,given,size,instead,size,should,given,integer,only,which,automatically,converted,readable,size,during,installation,Text,Properties,Description,brief,description,contents,component,user,able,choose,which,components,they,wish,install,during,Custom,installation,they,see,description,for,each,component,tell,what,Display,Name,name,component,display,when,populating,components,pane,property,left,blank,for,given,language,installer,use,standard,Name,property,instead,Build,Platforms,list,all,platforms,that,supported,InstallJammer,whether,not,component,should,built,for,each,platform,platform,marked,component,not,included,when,installer,for,that,platform,built,possible,build,component,into,multiple,platforms,then,not,install,component,based,parameters,during,installation,but,option,specifically,tells,InstallJammer,not,even,include,component,for,given,platform,Creating,new,component,Click,Add,New,Component,button,toolbar,add,new,component,your,install,new,component,created,with,default,values,that,you,can,change,after,its,creation,Since,components,can,nested,your,new,component,child,whatever,component,currently,selected,when,you,create,your,new,component,Deleting,component,Select,component,you,wish,delete,click,Delete,Component,button,toolbar,delete,key,your,keyboard`;";
s[46] = "Setup Types^SetupTypes.html^Setup types define a method of installation when the install is run.  The user can choose the method...^Setup Types^Setup,types,define,method,installation,when,install,run,user,can,choose,method,installation,based,setup,types,available,Each,setup,type,has,list,included,components,that,installed,user,chooses,that,setup,type,Custom,setup,type,has,special,meaning,InstallJammer,All,other,setup,types,regarded,normal,have,special,features,user,offered,ability,choose,setup,type,they,choose,Custom,they,should,also,offered,ability,select,individual,components,they,wish,install,Any,component,added,Custom,setup,type,available,user,choose,during,installation,default,InstallJammer,creates,two,setup,Typical,Custom,Standard,Properties,See,Standard,Properties,Name,name,setup,type,Show,Setup,Type,property,false,setup,type,not,shown,when,populating,setup,types,pane,used,create,setup,types,that,you,want,hidden,from,user,during,installation,Text,Properties,Description,brief,description,contents,setup,type,user,able,choose,which,setup,type,they,wish,install,they,see,description,for,each,type,tell,what,Display,Name,name,setup,type,display,when,populating,setup,types,pane,property,left,blank,for,given,language,installer,use,standard,Name,property,instead,Build,Platforms,list,all,platforms,that,supported,InstallJammer,whether,not,setup,type,should,built,for,each,platform,platform,marked,setup,type,not,included,when,installer,for,that,platform,built,possible,build,setup,type,into,multiple,platforms,then,not,install,setup,type,based,parameters,during,installation,but,option,specifically,tells,InstallJammer,not,even,include,setup,type,for,given,platform,Creating,new,setup,type,Click,Add,New,Setup,Type,button,toolbar,add,new,setup,type,your,install,new,setup,type,created,with,default,values,that,you,can,change,after,its,creation,Deleting,setup,type,Select,setup,type,you,wish,delete,click,Delete,Setup,Type,button,toolbar,delete,key,your,keyboard,Types[$XTITELEND$][$XKEYS$]Setup,Types[$XKEYSEND$]`;";
s[47] = "Panes and Actions^PanesAndActions.html^The Install / Uninstall Panes and Actions section of the install builder shows a tree of your instal...^Panes and Actions^Install,Uninstall,Panes,Actions,section,install,builder,shows,tree,your,install's,user,interface,user,interface,first,defined,set,possible,install,types,Underneath,that,list,all,panes,that,included,that,install,type,Each,pane,can,have,any,number,actions,that,execute,user,moves,through,install,Panes,Selecting,pane,tree,bring,some,information,for,that,pane,well,properties,that,you,can,modify,customize,pane,See,What,Panes,for,more,details,Actions,Selecting,action,tree,bring,some,information,for,that,action,well,properties,that,you,can,modify,customize,action,See,What,Actions,for,more,details,user,interface,tree,defines,how,user,see,your,install,when,they,run,contains,several,install,modes,that,defined,InstallJammer,beneath,those,panes,that,included,for,that,install,mode,Each,pane,can,have,any,number,actions,attached,User,Interface,Tree,Panes,actions,that,have,been,added,since,project,was,last,loaded,appear,blue,beside,pane,action's,title,tells,you,that,given,pane,action,has,conditions,attached,Common,Components,section,interface,tree,used,hold,panes,install,theme,that,don't,belong,anywhere,install,process,itself,Panes,installed,Common,Components,section,can,modified,just,like,normal,panes,but,you,don't,have,option,add,same,pane,install,type,Common,examples,background,window,that,covers,screen,behind,install,wizard,with,some,text,images,Standard,Install,section,contains,panes,used,InstallJammer,for,standard,installation,standard,installation,when,user,chooses,install,application,just,you,built,All,panes,shown,order,they,shown,interface,tree,Default,Install,default,install,when,user,has,chosen,accept,all,your,default,settings,just,install,without,changing,anything,default,install,usually,contains,just,few,screens,prompt,user,confirm,installation,then,copy,all,files,Console,Install,console,install,when,user,wants,install,program,from,command,line,instead,through,GUI,interface,console,install,run,inside,terminal,window,everything,input,output,from,terminal,Console,installs,not,supported,Windows,Silent,Install,silent,install,when,user,wants,accept,all,default,options,install,program,silently,without,GUI,interface,useful,for,some,administrators,who,have,install,application,many,different,machines,silent,install,does,not,have,any,panes,only,actions,Because,you,only,see,list,actions,under,Silent,Install,you,not,allowed,add,panes,Action,Groups,Action,groups,way,group,actions,together,into,one,place,action,group,can,contain,any,number,actions,execute,has,its,own,conditions,properties,well,those,actions,holds,Action,groups,best,used,you,define,alias,for,that,you,don't,always,have,remember,action,group,how,InstallJammer,sets,default,Startup,Actions,Install,Actions,groups,when,creates,new,project,You,can,execute,all,actions,action,group,using,Execute,Actions,action,See,What,Action,Groups,Previewing,pane,Once,you've,selected,pane,you,see,button,bottom,right,hand,corner,properties,window,preview,pane,Clicking,button,pop,sample,wizard,with,pane,you're,currently,viewing,lets,you,see,pane,way,appear,during,installation,Most,options,changed,automatically,affect,appearance,preview,window,you,should,able,make,textual,design,changes,click,Preview,Pane,again,immediately,see,your,changes,Not,all,changes,immediately,seen,Some,changes,options,can,only,seen,when,actually,running,install,case,simply,build,run,test,install,your,project,see,what,panes,look,like,Editing,pane,code,Each,pane,install,defined,code,that,built,InstallJammer,gives,you,freedom,flexibility,modify,each,pane,your,install,exactly,what,you,want,Simply,click,Edit,Pane,Code,button,when,editing,pane,editor,pop,with,all,code,used,create,pane,you're,looking,you,don't,understand,code,you,might,want,read,What,starting,point,Restoring,original,pane,code,Restore,Original,Pane,button,restore,original,code,for,pane,currently,being,edited,useful,you,wish,remove,changes,you've,made,pane,you,accidentally,messed,pane,code,Restoring,pane,code,put,pane,code,back,into,its,original,state,not,modify,your,properties,though,Only,code,pane,Actions[$XTITELEND$][$XKEYS$]Panes,Actions[$XKEYSEND$]`;";
s[48] = "Command Line Options^CommandLineOptions.html^The command line options panel allows you to specify the different command-line options that will be...^Command Line Options^command,line,options,panel,allows,you,specify,different,command,line,options,that,available,your,installer,InstallJammer,sets,some,default,options,for,each,new,projects,but,these,can,all,removed,you,want,few,options,that,defined,internally,during,startup,that,cannot,overriden,your,options,They,help,which,displays,usage,information,for,installer,temp,which,allows,user,specify,temporary,directory,version,which,shows,version,information,for,installer,response,files,enabled,following,options,also,added,each,response,file,which,specifies,response,file,read,save,response,file,which,specifies,that,responses,should,saved,given,file,InstallJammer,automatically,defines,character,that,precedes,option,depending,platform,cannot,changed,characters,removed,from,option,before,processing,options,should,specified,without,any,preceding,characters,used,option,character,Windows,used,UNIX,but,really,doesn't,matter,InstallJammer,accept,either,one,either,platform,but,always,display,correct,one,when,showing,usage,information,Command,Line,Option,Properties,Option,name,option,not,including,any,preceding,option,characters,Options,case,insensitive,when,specified,command,line,user,but,they,maintain,case,when,displaying,usage,information,Virtual,Text,name,virtual,text,without,store,result,option,into,What,stored,virtual,text,result,depends,what,type,option,being,used,Type,Each,option,specific,type,each,type,behaves,differently,types,Boolean,boolean,option,means,that,user,must,specify,Yes,some,equivalent,argument,option,virtual,text,set,user,specified,they,specified,Yes,Choice,choice,option,that,has,list,possible,choices,user,can,choose,from,choices,all,case,insensitive,but,virtual,text,set,case,sensitive,For,example,you,had,option,check,that,accepted,Foo,Bar,user,could,pass,foo,command,line,but,your,virtual,text,would,still,set,Foo,eventhough,user,passed,all,lowercase,version,Prefix,prefix,option,means,that,given,option,only,prefix,that,can,specified,along,with,any,option,after,prefix,given,value,can,used,provide,generic,option,for,specifying,many,things,your,installer,Any,option,provided,prefix,switch,set,virtual,text,with,given,value,Virtual,Text,property,not,null,prepended,option,given,For,example,you,had,prefix,option,with,Virtual,Text,CommandLine,user,could,bar,command,line,you,would,have,virtual,text,<%CommandLineFoo%>,set,bar,String,string,option,means,that,user,can,specify,anything,they,want,checks,done,for,validity,You,have,check,value,yourself,using,action,virtual,text,set,value,given,string,Switch,switch,means,that,option,specified,with,argument,simply,turns,option,virtual,text,set,option,passed,command,line,not,set,all,not,passed,Debug,tells,InstallJammer,whether,given,command,line,option,meant,debugging,option,not,option,debugging,option,not,included,options,when,building,without,debugging,options,when,building,for,final,release,Hide,property,true,given,command,line,option,not,appear,list,option,when,showing,usage,installer,option,still,included,build,but,user,not,able,see,that,Value,property,has,different,meanings,depending,type,option,Boolean,option,boolean,option,Values,can,specify,list,two,values,that,translate,Yes,user,still,have,pass,Yes,command,line,but,Values,not,null,InstallJammer,set,virtual,text,first,value,user,specified,Yes,second,value,they,specified,Choice,option,choice,Values,must,contain,list,possible,values,that,legal,for,given,option,list,can,anything,you,want,but,values,themselves,case,insensitive,when,user,passes,Prefix,option,prefix,values,contains,list,possible,options,user,can,pass,values,empty,user,can,pass,any,option,they,want,command,line,with,prefix,Switch,option,switch,Values,can,contain,string,that,set,virtual,text,user,passes,option,command,line,Values,null,virtual,text,set,Description,short,description,telling,user,what,option,meant,When,user,passes,incorrect,option,specifies,help,command,line,usage,information,displayed,that,contains,all,non,hidden,options,descriptions,usage,information,for,each,option,different,for,each,option,depending,its,type,but,description,can,briefly,tell,user,what,option,for,Line,Options[$XTITELEND$][$XKEYS$]Command,Line,Options[$XKEYSEND$]`;";
s[49] = "Virtual Text^VirtualText.html^The Virtual Text panel allows you to see what virtual text and virtual directory definitions are def...^Virtual Text^Virtual,Text,panel,allows,you,see,what,virtual,text,virtual,directory,definitions,defined,InstallJammer,well,add,your,own,virtual,text,your,project,Adding,your,own,virtual,text,lets,you,customize,your,installer,using,common,strings,throughout,instead,using,constant,values,learn,more,about,virtual,text,please,read,What,Virtual,Text,Adding,New,Virtual,Text,You,can,add,your,own,virtual,text,clicking,Add,New,Virtual,Text,button,located,toolbar,panel,new,line,added,bottom,virtual,text,table,with,values,that,left,blank,for,you,fill,first,field,index,value,for,virtual,text,field,you,adding,second,field,text,that,used,for,your,new,virtual,text,within,installer,Now,that,you've,added,your,new,virtual,text,you,can,use,throughout,your,install,place,constants,Here's,Let's,say,you,add,virtual,text,definition,called,MyVirtualText,with,value,virtual,text,Anywhere,you,use,<%MyVirtualText%>,within,InstallJammer,substituted,with,text,virtual,text,since,virtual,text,can,embedded,within,other,virtual,text,you,could,set,your,virtual,text,something,like,Today's,date,<%Date%>,InstallJammer,substitution,<%Date%>,inside,your,text,whenever,you,use,Deleting,Virtual,Text,You,can,only,delete,virtual,text,that,you,have,added,your,project,Virtual,text,that,defined,InstallJammer,cannot,deleted,delete,virtual,text,definition,that,you,have,added,click,row,for,text,then,click,Delete,Virtual,Text,button,toolbar,panel,You,can,select,multiple,rows,delete,once,Text[$XTITELEND$][$XKEYS$]Virtual,Text[$XKEYSEND$]`;";
s[50] = "Disk Builder^DiskBuilder.html^The disk builder is where the actual installation binaries are built. Once you have completed all th...^Disk Builder^disk,builder,where,actual,installation,binaries,built,Once,you,have,completed,all,steps,creating,your,install,you,must,build,order,use,Building,install,Pressing,build,button,start,build,process,Only,platforms,selected,Platforms,build,section,built,allows,you,quickly,rebuild,single,platform,instead,always,having,build,all,binaries,Platforms,that,not,checked,platforms,that,not,active,not,built,Once,build,process,starts,you,can,continue,working,install,build,process,takes,place,background,convenient,your,build,long,one,you,wish,keep,making,changes,your,install,Quick,Build,quick,build,means,InstallJammer,rebuild,all,files,for,your,installer,but,won't,repackage,any,your,application,files,fast,way,rebuild,changes,you've,made,installer,when,you,haven't,actually,changed,any,files,you,installing,Build,for,final,release,option,tells,InstallJammer,that,you,building,your,installs,for,final,release,With,option,checked,InstallJammer,rebuild,full,install,including,your,application,files,even,you,select,quick,build,disable,debugging,options,resulting,installer,produces,installer,that,ready,for,distribution,customers,Builder[$XTITELEND$][$XKEYS$]Disk,Builder[$XKEYSEND$]`;";
s[51] = "Test Installer^TestRun.html^This panel allows you to test your newly-built install. By default, testing an install means just ex...^Test Installer^panel,allows,you,test,your,newly,built,install,default,testing,install,means,just,executing,binary,Save,temporary,directory,for,debugging,option,tells,InstallJammer,save,temporary,directory,created,during,installation,for,debugging,purposes,When,InstallJammer,install,runs,temporary,directory,created,hold,unpacking,program,other,temporary,files,Normally,temporary,directory,cleaned,upon,exiting,install,option,checked,temporary,directory,left,for,debugging,Test,default,mode,tells,install,use,Default,install,mode,Test,console,mode,UNIX,only,tells,install,test,console,based,version,installer,InstallJammer,launch,installer,new,console,window,Console,installs,not,available,Windows,Test,silent,mode,tells,install,use,Silent,install,mode,Test,install,without,installing,files,option,tells,your,install,run,through,all,panes,without,actually,going,through,steps,install,files,your,install,Test,install,with,open,console,option,tells,install,open,debugging,console,window,during,installation,console,allows,you,anything,you,want,while,your,install,running,Installer[$XTITELEND$][$XKEYS$]Test,Run[$XKEYSEND$]`;";
s[52] = "Test Uninstaller^TestUninstaller.html^This panel allows you to test your uninstaller after you've run the installer on your system.  Insta...^Test Uninstaller^panel,allows,you,test,your,uninstaller,after,you've,run,installer,your,system,InstallJammer,attempt,locate,uninstaller,for,last,installation,your,project,run,uninstaller,finds,Test,console,mode,UNIX,only,tells,uninstall,test,console,based,version,uninstaller,InstallJammer,launch,uninstaller,new,console,window,Console,uninstalls,not,available,Windows,Test,silent,mode,tells,uninstall,use,Silent,uninstall,mode,Test,install,without,uninstalling,files,option,tells,your,uninstall,run,through,all,panes,without,actually,going,through,steps,uninstall,files,your,install,Test,uninstall,with,open,console,option,tells,uninstall,open,debugging,console,window,during,uninstallation,console,allows,you,anything,you,want,while,your,uninstall,running,Uninstaller[$XTITELEND$][$XKEYS$]Test,Uninstaller[$XKEYSEND$]`;";
s[53] = "Object Types^ObjectTypes.html^InstallJammer uses objects to define various pieces of an install.  Almost anything that is stored i...^Object Types^InstallJammer,uses,objects,define,various,pieces,install,Almost,anything,that,stored,your,install,object,They,usually,identified,having,that,unique,name,object,Below,list,object,types,brief,description,what,they,Action,See,What,Actions,Action,Group,See,What,Action,Groups,Component,See,Components,Condition,See,What,Conditions,File,Group,See,Groups,Files,Files,Directories,See,Files,Directories,Pane,See,What,Panes,Setup,Type,See,Setup,Types,Types[$XTITELEND$][$XKEYS$]Object,Types[$XKEYSEND$]`;";
s[54] = "Standard Properties^StandardProperties.html^Some properties are standard to many objects throughout InstallJammer.  This is a list of standard p...^Standard Properties^Some,properties,standard,many,objects,throughout,InstallJammer,list,standard,properties,that,can,appear,throughout,your,project,what,they,object,defined,any,piece,install,file,group,file,action,condition,etc,unique,identifier,for,object,generated,when,object,created,does,not,change,throughout,life,object,Component,property,tells,you,what,component,was,originally,used,create,object,Active,tells,InstallJammer,whether,object,active,not,inactive,object,not,packaged,when,building,installer,Alias,alias,alias,which,call,object,Any,object,InstallJammer,that,has,can,also,have,alias,makes,easier,remember,objects,alias,instead,object,For,example,Install,Actions,group,that,created,for,new,project,aliased,called,Install,Actions,make,easier,call,from,other,actions,Comment,Comments,sometimes,provided,InstallJammer,tell,you,what,object,doing,but,they,usually,set,someone,building,project,Comments,not,used,InstallJammer,for,anything,can,contain,any,text,you,want,Conditions,tells,you,any,conditions,placed,object,that,checked,during,installation,Selecting,property,let,you,bring,Conditions,Editor,see,modify,any,conditions,object,Data,property,used,hold,user,specific,data,Just,like,comments,data,not,used,InstallJammer,safe,for,you,store,anything,you,want,into,can,helpful,for,storing,other,bits,relevant,data,with,object,system,for,use,other,objects,actions,conditions,Include,property,tells,InstallJammer,when,where,include,object,when,running,installer,uninstaller,object,either,always,included,included,only,when,testing,included,only,when,not,testing,property,affected,<%Testing%>,virtual,text,When,testing,only,objects,which,always,included,included,when,testing,created,When,not,testing,only,objects,which,always,included,included,when,not,testing,created,Properties[$XTITELEND$][$XKEYS$]Standard,Properties[$XKEYSEND$]`;";
s[55] = "What are Panes?^WhatArePanes.html^Panes are what the user sees as they move forward and backward through your installer.  Your availab...^What are Panes?^Panes,what,user,sees,they,move,forward,backward,through,your,installer,Your,available,panes,defined,theme,you,chose,when,you,created,your,project,each,theme,has,different,set,panes,different,look,feel,for,those,panes,default,install,theme,you,choose,select,default,set,panes,that,most,common,for,simple,installer,These,usually,include,welcome,pane,let,user,select,installation,directory,pane,copy,files,install,finishing,pane,For,most,applications,these,simplest,panes,you,need,give,your,user,minimum,flexibility,during,installation,Select,pane,your,install,you,see,properties,for,that,pane,come,right,pane,tree,These,properties,define,actions,look,feel,your,pane,most,common,options,already,chosen,for,you,but,you,can,modify,your,panes,any,way,you,like,Standard,Properties,See,Standard,Properties,Advanced,Properties,advanced,properties,pane,different,for,each,pane,each,theme,Most,self,explanatory,but,you,need,help,you,can,usually,find,brief,description,property,hovering,over,property's,name,for,second,help,balloon,appear,Below,list,some,common,properties,that,appear,throughout,themes,Anchor,property,tells,InstallJammer,where,place,window,when,displaying,coordinates,defined,points,desktop,etc,place,window,bottom,center,screen,Buttons,Defines,buttons,that,available,selected,pane,Each,theme,defines,buttons,that,available,each,pane,sets,default,values,for,each,pane,based,default,settings,Any,button,not,included,list,given,hidden,when,pane,displayed,Disabling,button,usually,better,way,keep,your,installer,uniform,can,achieved,with,Modify,Widget,action,Icon,property,tells,InstallJammer,what,image,use,small,icon,selected,pane,Image,property,tells,InstallJammer,what,image,use,larger,image,selected,pane,Text,Properties,Text,properties,properties,that,directly,relate,text,displayed,pane,They,have,added,option,not,substituting,virtual,text,it's,not,required,you,don't,want,Besides,every,button,wizard,text,properties,also,include,any,widget,pane,whose,text,can,changed,Anytime,you,change,text,property,you,can,preview,pane,see,what,new,text,look,like,during,installation,Panes,Panes`;";
s[56] = "What are Actions?^WhatAreActions.html^Actions are what InstallJammer uses to perform tasks while an installer or uninstaller is running.  ...^What are Actions?^Actions,what,InstallJammer,uses,perform,tasks,while,installer,uninstaller,running,action,can,anything,that,you,might,want,Any,action,can,added,any,pane,install,each,action,checked,run,order,during,installation,Actions,allow,you,great,amount,flexibility,your,installer,While,many,actions,provided,convenience,for,common,tasks,you,might,want,perform,you,also,have,option,script,your,actions,anything,you,like,Each,action,may,also,have,any,number,conditions,What,Conditions,attached,that,checked,before,executing,action,does,not,meet,necessary,conditions,skipped,next,action,checked,Actions,may,also,part,action,group,What,Action,Groups,where,group,itself,has,set,conditions,that,determine,whether,group,executed,new,install,come,setup,with,many,default,actions,Without,actions,installer,nothing,more,than,bunch,panes,move,back,forth,through,actions,what,really,does,work,during,installation,Standard,Properties,See,Standard,Action,Properties,Supported,Platforms,Most,actions,conditions,InstallJammer,supported,all,available,platforms,but,some,platform,specific,only,apply,those,platforms,When,dealing,with,actions,conditions,that,platform,specific,you,don't,need,worry,about,adding,conditions,check,platform,When,documentation,lists,that,only,certain,platforms,supported,for,action,condition,InstallJammer,automatically,skip,those,actions,other,platforms,during,execution,action,still,show,debug,logs,being,exected,though,you,wanted,make,that,clearer,you,could,add,your,own,Platform,Condition,Advanced,Properties,Each,action,has,different,set,advanced,properties,that,further,define,properties,action,Please,see,documentation,for,each,type,action,for,more,information,Actions,actions`;";
s[57] = "What are Action Groups?^WhatAreActionGroups.html^Action groups are a way to group individual actions together under a single set of conditions.  Acti...^What are Action Groups?^Action,groups,way,group,individual,actions,together,under,single,set,conditions,Action,groups,defined,independent,any,particular,pane,can,called,from,anywhere,install,using,Execute,Action,action,When,executing,action,group,conditions,Execute,Action,first,checked,then,any,conditions,action,group,itself,checked,finally,Evaluate,Conditions,property,Execute,Action,true,individual,conditions,each,action,action,group,checked,before,executing,any,conditions,Action,Group,exist,that,executed,Before,Next,Action,these,conditions,checked,after,all,actions,group,executed,conditions,fail,entire,action,group,executed,again,InstallJammer,creates,five,action,groups,for,new,Setup,Actions,Startup,Actions,Install,Actions,Finish,Actions,Cancel,Actions,Setup,Actions,action,group,executed,near,very,beginning,install,uninstall,startup,happens,just,before,command,line,arguments,specified,user,parsed,Since,wizard,exists,yet,some,setup,has,not,been,done,yet,action,group,should,only,used,initialize,virtual,text,alter,command,line,options,before,they,parsed,Startup,Actions,action,group,executed,automatically,during,startup,installer,done,after,some,default,checks,setup,has,been,done,but,before,first,pane,wizard,displayed,Install,Actions,action,group,called,from,within,install,panes,usually,attached,Copy,Files,pane,InstallJammer,does,not,call,action,group,automatically,instead,letting,you,call,wherever,you,want,from,within,installer,Finish,Actions,action,group,executed,automatically,when,install,finished,last,thing,called,before,installer,exits,Cancel,Actions,action,group,executed,automatically,when,install,cancelled,last,thing,called,before,installer,exits,Standard,Properties,See,Standard,Properties,Action,Groups,Action,Groups`;";
s[58] = "Standard Action Properties^ActionStandardProperties.html^IDA unique identifier for this object.  This ID is generated when the object is created and does n...^Standard Action Properties^unique,identifier,for,object,generated,when,object,created,does,not,change,throughout,life,object,Component,property,tells,you,what,action,was,originally,used,create,object,Active,tells,InstallJammer,whether,object,active,not,inactive,object,not,packaged,when,building,installer,Alias,alias,alias,which,call,object,Any,object,InstallJammer,that,has,can,also,have,alias,makes,easier,remember,objects,alias,instead,object,For,example,Install,Actions,group,that,created,for,new,project,aliased,called,Install,Actions,make,easier,call,from,other,actions,Comment,Comments,sometimes,provided,InstallJammer,tell,you,what,object,doing,but,they,usually,set,someone,building,project,Comments,not,used,InstallJammer,for,anything,can,contain,any,text,you,want,Conditions,tells,you,any,conditions,placed,object,that,checked,during,installation,Selecting,property,let,you,bring,Conditions,Editor,see,modify,any,conditions,object,Data,property,used,hold,user,specific,data,Just,like,comments,data,not,used,InstallJammer,safe,for,you,store,anything,you,want,into,can,helpful,for,storing,other,bits,relevant,data,with,object,system,for,use,other,objects,actions,conditions,Execute,Action,tells,InstallJammer,when,execute,given,action,descriptions,when,execute,mean,just,what,they,say,default,After,Pane,Displayed,which,means,execute,action,after,given,pane,has,been,displayed,user,Ignore,Errors,tells,InstallJammer,ignore,any,errors,that,might,occur,while,executing,action,Errors,usually,occur,because,bad,data,but,they,can,result,bugs,option,set,Yes,InstallJammer,keep,moving,next,action,pane,when,encounters,error,instead,stopping,install,Action,Properties[$XTITELEND$][$XKEYS$]Action,Standard,Properties[$XKEYSEND$]`;";
s[59] = "Console Ask Yes or No^ConsoleAskYesOrNo.html^This action is used in a console install to ask the user a question that requires a Yes or No answer...^Console Ask Yes or No^action,used,console,install,ask,user,question,that,requires,Yes,answer,user,required,provide,valid,answer,before,installation,continues,Supported,Platforms,UNIX,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Default,property,specifies,default,value,user,hits,Enter,when,asked,question,default,value,None,means,that,user,must,enter,answer,Prompt,prompt,display,user,when,asking,question,Virtual,Text,virtual,text,variable,without,store,user's,answer,per,rules,boolean,values,virtual,text,result,user,chooses,they,choose,yes,Ask,Yes,No[$XTITELEND$][$XKEYS$]Console,Ask,Yes,No[$XKEYSEND$]`;";
s[60] = "Console Clear Screen^ConsoleClearScreen.html^This action is used in a console install to clear the screen.Supported PlatformsUNIXStan...^Console Clear Screen^action,used,console,install,clear,screen,Supported,Platforms,UNIX,Standard,Properties,See,Standard,Action,Properties,Clear,Screen[$XTITELEND$][$XKEYS$]Console,Clear,Screen[$XKEYSEND$]`;";
s[61] = "Console Get User Input^ConsoleGetUserInput.html^This action is used in a console install to get a string of input from the user.  The string is not ...^Console Get User Input^action,used,console,install,get,string,input,from,user,string,not,checked,for,validity,any,way,you,use,action,check,user's,response,Supported,Platforms,UNIX,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Echo,Input,property,false,input,not,echoed,user,types,useful,for,asking,for,passwords,other,information,that,should,not,seen,screen,Prompt,prompt,display,user,when,asking,question,Require,Response,property,true,user,cannot,enter,empty,data,for,response,action,continue,prompt,for,information,until,response,entered,Trim,Result,property,true,user's,result,trimmed,all,white,spaces,before,set,resulting,virtual,text,Virtual,Text,virtual,text,variable,without,store,user's,answer,per,rules,boolean,values,virtual,text,result,user,chooses,they,choose,yes,Get,User,Input[$XTITELEND$][$XKEYS$]Console,Get,User,Input[$XKEYSEND$]`;";
s[62] = "Console Message^ConsoleMessage.html^This action is used in a console install to display a message to the user.Supported PlatformsU...^Console Message^action,used,console,install,display,message,user,Supported,Platforms,UNIX,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Allow,Quit,property,true,user,allowed,quit,reading,message,long,message,pagination,turned,message,all,fits,screen,without,paging,pagination,turned,off,property,means,nothing,Paginate,Message,property,true,long,message,displayed,user,page,time,allow,read,before,continuing,next,page,Wrap,Text,property,true,text,message,wrapped,word,size,user's,screen,when,displayed,Message[$XTITELEND$][$XKEYS$]Console,Message[$XKEYSEND$]`;";
s[63] = "Console Pause^ConsolePause.html^This action is used in a console install to pause before the next action is executed.  The user is a...^Console Pause^action,used,console,install,pause,before,next,action,executed,user,asked,press,space,bar,continue,Supported,Platforms,UNIX,Standard,Properties,See,Standard,Action,Properties,Pause[$XTITELEND$][$XKEYS$]Console,Pause[$XKEYSEND$]`;";
s[64] = "Execute Action^ExecuteAction.html^This action is used to execute another action or action group.  The Execute Action's conditions are ...^Execute Action^action,used,execute,another,action,action,group,Execute,Action's,conditions,checked,before,executing,action,specified,then,conditions,target,action,can,checked,based,properties,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Action,alias,action,execute,can,either,another,action,installer,action,group,Evaluate,Conditions,true,conditions,target,action,also,checked,before,executing,action,false,only,conditions,Execute,Action,action,checked,any,conditions,target,action,action,group,ignored,Action[$XTITELEND$][$XKEYS$]Execute,Action[$XKEYSEND$]`;";
s[65] = "Execute External Program^ExecuteExternalProgram.html^This action will execute an external program like a shell script or batch file and return the result...^Execute External Program^action,execute,external,program,like,shell,script,batch,file,return,results,specified,virtual,text,can,also,used,show,progressive,output,while,external,program,running,that,user,can,see,what,program,doing,while,runs,You,cannot,execute,console,root,Show,Progressive,Output,true,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Clear,Progressive,Widget,property,true,progressive,text,widget,used,during,Show,Progressive,Output,cleared,before,external,program,executed,Console,Title,UNIX,only,property,not,null,specifies,title,use,console,window,Execute,Console,property,true,Execute,Root,UNIX,only,property,true,InstallJammer,attempt,execute,given,program,root,user,already,root,action,execute,normal,user,not,root,they,prompted,for,root,password,which,then,execute,program,root,Execute,Console,property,true,InstallJammer,execute,external,program,console,window,useful,for,executing,scripts,that,expect,some,kind,input,from,user,command,line,InstallJammer,attempt,locate,best,possible,terminal,based,desktop,environment,KDE,Konsole,Gnome,gnome,terminal,nothing,else,can,found,good,old,xterm,used,Execute,Console,specified,conjunction,with,Execute,Root,user,not,root,console,first,ask,user,for,root,password,same,console,window,before,executing,Include,Stderr,property,true,standard,error,channel,executing,program,included,output,from,program,include,standard,error,result,execution,progressive,output,being,used,Program,Command,Line,command,line,program,execute,command,line,executed,exactly,input,with,all,arguments,included,Virtual,text,automatically,substituted,should,noted,that,arguments,command,line,separated,spaces,each,argument,passed,separately,system,arguments,command,being,executed,Each,argument,parsed,individually,for,virtual,text,rather,than,substituting,string,whole,that,each,argument,properly,appended,list,arguments,execute,Progressive,Output,Widget,property,specifies,textbox,widget,that,updated,with,output,progressive,command,becomes,available,textbox,automatically,scroll,down,keep,with,new,input,widget,can,specified,its,Alias,was,created,with,Add,Widget,action,can,name,widget,current,pane,can,specified,<PANE>,<WIDGET>,Result,Virtual,Text,virtual,text,variable,store,result,external,program,any,data,that,output,standard,out,while,program,running,progressive,output,being,shown,variable,entire,result,that,was,output,when,program,finishes,executing,Show,Progressive,Output,value,true,Progressive,Output,Widget,updated,with,new,data,becomes,available,from,external,program,value,false,all,output,from,external,program,buffered,stored,Result,Virtual,Text,Status,Virtual,Text,virtual,text,variable,that,stores,exit,code,external,program,exit,code,usually,means,that,program,succeeded,without,error,Any,other,exit,code,usually,means,that,program,failed,some,way,Wait,for,Program,tells,InstallJammer,wait,until,external,program,finishes,before,continuing,with,install,value,false,InstallJammer,execute,external,program,background,continue,Watch,Progressive,Output,property,true,Show,Progressive,Output,true,InstallJammer,watch,output,from,external,program,for,cues,that,tell,InstallJammer,set,virtual,text,while,running,text,InstallJammer,looks,for,looks,like,line,surrounded,with,single,word,first,argument,followed,any,other,arguments,Checking,for,file,set,<%Status%>,virtual,text,variable,value,Checking,for,file,then,refresh,screen,allows,external,program,update,status,progres,bars,while,running,keep,GUI,alive,that,user,knows,what,going,while,running,Any,line,that,matches,output,that,InstallJammer,looking,for,not,displayed,output,swallowed,InstallJammer,before,user,sees,Watch,Regular,Expression,property,specifies,regular,expression,use,when,watching,progressive,output,default,looks,for,text,manner,described,for,Watch,Progressive,Output,but,property,can,changed,look,for,any,other,kind,pattern,regular,expression,provides,two,submatch,values,they,used,virtual,text,variable,name,value,set,virtual,text,only,one,submatch,Watch,Virtual,Text,property,used,store,value,that,matches,property,should,only,changed,you,really,know,what,you're,doing,know,enough,about,regular,expressions,Watch,Virtual,Text,Watch,Regular,Expression,does,not,include,two,submatches,virtual,text,used,virtual,text,set,with,result,regular,expression,when,watching,progressive,output,External,Program[$XTITELEND$][$XKEYS$]Execute,External,Program[$XKEYSEND$]`;";
s[66] = "Execute Script^ExecuteScript.html^This action is used to script unique actions in Tcl that allow you to do almost anything with your i...^Execute Script^action,used,script,unique,actions,Tcl,that,allow,you,almost,anything,with,your,installer,Since,Tcl,scripts,don't,have,any,constraints,within,installer,action,can,used,handle,anything,that,not,already,available,another,action,See,What,for,more,information,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Result,Virtual,Text,virtual,text,variable,store,result,script,Tcl,Script,property,holds,Tcl,script,executed,All,virtual,text,substituted,for,script,Script[$XTITELEND$][$XKEYS$]Execute,Script[$XKEYSEND$]`;";
s[67] = "Adjust Line Feeds^AdjustLineFeeds.html^This action is used to adjust the line feeds of the given files.  This can convert text files to eit...^Adjust Line Feeds^action,used,adjust,line,feeds,given,files,can,convert,text,files,either,UNIX,Windows,crlf,line,feeds,specified,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Files,list,files,patterns,separated,Any,pattern,file,that,relative,path,automatically,made,relative,<%InstallDir%>,Line,Feed,type,linefeeds,for,specified,files,following,choices,Auto,choose,linefeeds,based,target,install,platform,Unix,Use,UNIX,linefeeds,Windows,Use,Windows,linefeeds,crlf,Examples,following,values,would,convert,all,txt,files,<%InstallDir%>,UNIX,linefeeds,txt,Line,Unix[$XTITLE$]Adjust,Line,Feeds[$XTITELEND$][$XKEYS$]Adjust,Line,Feeds[$XKEYSEND$]`;";
s[68] = "Backup File^BackupFile.html^This action will take the specified files and back them up to a new file name.  Given the new file e...^Backup File^action,take,specified,files,back,new,file,name,Given,new,file,extension,each,file,copied,new,file,combined,its,own,file,name,plus,new,extension,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Files,list,files,patterns,separated,Any,pattern,file,that,relative,path,automatically,made,relative,<%InstallDir%>,File,Extension,new,extension,append,each,file,being,backed,string,substituted,for,number,extension,number,increment,until,unused,file,name,found,Default,bak%d,Overwrite,Files,property,true,action,overwrite,file,that,already,exists,when,backing,instead,continuing,look,for,new,file,name,that,does,not,exist,Default,Rename,Files,property,true,files,specified,renamed,new,file,instead,just,being,copied,useful,you,want,move,current,file,out,way,Default,Starting,Backup,number,start,when,backing,files,Default,Examples,following,values,would,backup,all,conf,files,directory,conf,foo,conf,would,become,foo,conf,bak1,bar,conf,would,become,bar,conf,bak1,following,values,would,backup,foo,cfg,<%InstallDir%>,foo,cfg,orig,but,file,already,exists,nothing,happen,InstallJammer,throw,error,just,tell,InstallJammer,ignore,error,Ignore,Yes,foo,cfg,File,orig,foo,cfg,would,become,foo,cfg,orig[$XTITLE$]Backup,File[$XTITELEND$][$XKEYS$]Backup,File[$XKEYSEND$]`;";
s[69] = "Change File Ownership^ChangeFileOwnership.html^This action will change the ownership or group of a given list of files on the target system.  The i...^Change File Ownership^action,change,ownership,group,given,list,files,target,system,installing,user,must,have,permission,change,ownership,given,action,fail,Supported,Platforms,All,UNIX,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Files,list,files,patterns,separated,Any,pattern,file,that,relative,path,automatically,made,relative,<%InstallDir%>,Owner,new,owner,can,either,username,UID,target,system,Group,new,group,can,either,group,name,GID,target,system,Examples,following,values,would,change,ownership,every,file,<%InstallDir%>,owner,root,group,wheel,wheel,root[$XTITLE$]Change,File,Ownership[$XTITELEND$][$XKEYS$]Change,File,Ownership[$XKEYSEND$]`;";
s[70] = "Change File Permissions^ChangeFilePermissions.html^This action will change the UNIX file permissions of the files given.Supported PlatformsAll ...^Change File Permissions^action,change,UNIX,file,permissions,files,given,Supported,Platforms,All,UNIX,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Files,list,files,patterns,separated,Any,pattern,file,that,relative,path,automatically,made,relative,<%InstallDir%>,Permissions,UNIX,permissions,mask,octal,format,Examples,following,values,would,make,all,txt,files,<%InstallDir%>,read,only,txt,0444[$XTITLE$]Change,File,Permissions[$XTITELEND$][$XKEYS$]Change,File,Permissions[$XKEYSEND$]`;";
s[71] = "Copy File^CopyFile.html^This action will copy a single file or directory on the target system to another name.Supporte...^Copy File^action,copy,single,file,directory,target,system,another,name,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Source,path,file,directory,copied,path,relative,made,relative,<%InstallDir%>,Destination,new,path,copy,file,directory,path,relative,made,relative,<%InstallDir%>,Examples,following,values,would,copy,file,foo,cfg,bar,cfg,<%InstallDir%>,foo,cfg,bar,cfg[$XTITLE$]Copy,File[$XTITELEND$][$XKEYS$]Copy,File[$XKEYSEND$]`;";
s[72] = "Create File Link^CreateFileLink.html^This action creates a link in the file system to another file.  The link can be a symbolic or a hard...^Create File Link^action,creates,link,file,system,another,file,link,can,symbolic,hard,link,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Link,Name,file,name,link,create,target,system,file,point,another,file,file,system,path,relative,made,relative,<%InstallDir%>,Link,Target,target,file,link,create,new,file,link,point,file,path,relative,made,relative,<%InstallDir%>,Link,Type,type,link,hard,symbolic,Examples,following,values,create,symbolic,link,from,program,executable,into,Link,Link,Link,symbolic[$XTITLE$]Create,File,Link[$XTITELEND$][$XKEYS$]Create,File,Link[$XKEYSEND$]`;";
s[73] = "Create Folder^CreateFolder.html^This action is used to create a new folder or directory on the target system.Standard Properti...^Create Folder^action,used,create,new,folder,directory,target,system,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Folder,Name,name,folder,directory,create,Folder[$XTITELEND$][$XKEYS$]Create,Folder[$XKEYSEND$]`;";
s[74] = "Delete File^DeleteFile.html^This action will delete all of the files specified from the target system.Supported Platforms...^Delete File^action,delete,all,files,specified,from,target,system,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Files,list,files,patterns,separated,Any,pattern,file,that,relative,path,automatically,made,relative,<%InstallDir%>,Examples,following,values,would,delete,directory,all,bak1,files,<%InstallDir%>,bak1[$XTITLE$]Delete,File[$XTITELEND$][$XKEYS$]Delete,File[$XKEYSEND$]`;";
s[75] = "Read File Into Virtual Text^ReadFileIntoVirtualText.html^This action will read a single file on the target system into a virtual text variable.  This is usef...^Read File Into Virtual Text^action,read,single,file,target,system,into,virtual,text,variable,useful,obtain,properties,information,from,file,use,within,InstallJammer,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Encoding,property,specifies,encoding,use,when,reading,file,into,virtual,text,default,use,whatever,system,encoding,utf,would,common,choice,you,unfamiliar,with,character,encodings,it's,probably,best,leave,property,alone,File,path,file,read,path,relative,made,relative,<%InstallDir%>,Trim,String,property,true,data,read,from,file,trimmed,whitespace,either,side,before,virtual,text,set,Virtual,Text,name,virtual,text,variable,read,file,into,without,Examples,following,values,would,read,file,allow,into,virtual,text,<%AllowedHosts%>,allow,Virtual,AllowedHosts[$XTITLE$]Read,File,Into,Virtual,Text[$XTITELEND$][$XKEYS$]Read,File,Into,Virtual,Text[$XKEYSEND$]`;";
s[76] = "Rename File^RenameFile.html^This action will rename a single file or directory on the target system to another name.  This is th...^Rename File^action,rename,single,file,directory,target,system,another,name,same,moving,file,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Source,path,file,directory,renamed,path,relative,made,relative,<%InstallDir%>,Destination,new,path,rename,file,directory,path,relative,made,relative,<%InstallDir%>,Examples,following,values,would,rename,file,foo,cfg,bar,cfg,<%InstallDir%>,foo,cfg,bar,cfg[$XTITLE$]Rename,File[$XTITELEND$][$XKEYS$]Rename,File[$XKEYSEND$]`;";
s[77] = "Replace Text in File^ReplaceTextInFile.html^This action will replace text strings in a file with other strings as based on a string map.  This i...^Replace Text in File^action,replace,text,strings,file,with,other,strings,based,string,map,useful,for,writing,out,configuration,files,with,virtual,text,values,from,InstallJammer,etc,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Encoding,Specifies,language,encoding,use,when,replacing,text,file,Files,list,files,patterns,separated,Any,pattern,file,that,relative,path,automatically,made,relative,<%InstallDir%>,Line,Feed,type,linefeeds,for,specified,files,following,choices,Auto,choose,linefeeds,based,target,install,platform,Unix,Use,UNIX,linefeeds,Windows,Use,Windows,linefeeds,crlf,String,Map,string,map,list,strings,pairs,separated,whitespaces,Each,string,string,map,has,corresponding,string,map,Strings,with,spaces,should,placed,quotes,show,that,they,treated,single,string,See,example,below,for,sample,string,map,Examples,following,values,would,convert,all,instances,@@INSTALL_DIR@@,installation,directory,all,instances,string,replace,string,with,new,string,file,called,config,cfg,also,convert,linefeeds,UNIX,linefeeds,config,cfg,Line,Unix,String,@@INSTALL_DIR@@,<%InstallDir%>,replace,string,new,string,Text,File[$XTITELEND$][$XKEYS$]Replace,Text,File[$XKEYSEND$]`;";
s[78] = "Write Text to File^WriteTextToFile.html^This action will write text out to a text file.  It can either overwrite a file or append text to an...^Write Text to File^action,write,text,out,text,file,can,either,overwrite,file,append,text,existing,file,Any,file,that,does,not,exist,automatically,created,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Add,Uninstall,property,true,any,file,touched,action,added,list,files,removed,during,uninstallation,Append,Newline,property,true,newline,output,end,text,written,file,Encoding,Specifies,language,encoding,use,when,writing,text,file,File,Open,Action,tells,action,how,open,file,for,writing,following,choices,Append,file,Append,text,existing,file,create,new,one,doesn't,exist,Overwrite,existing,file,Write,text,new,file,overwriting,any,file,that,already,exists,Files,list,files,separated,Any,file,that,relative,path,automatically,made,relative,<%InstallDir%>,Line,Feed,type,linefeeds,for,specified,files,following,choices,Auto,choose,linefeeds,based,target,install,platform,Unix,Use,UNIX,linefeeds,Windows,Use,Windows,linefeeds,crlf,Examples,following,values,write,some,install,configuration,out,config,cfg,file,config,cfg,Line,Unix,Text,<%InstallDir%>,<%Installer%>,<%Username%>[$XTITLE$]Write,Text,File[$XTITELEND$][$XKEYS$]Write,Text,File[$XKEYSEND$]`;";
s[79] = "Unzip File^UnzipFile.html^This action will take a given .zip file that is installed on the target system and unzip it to a des...^Unzip File^action,take,given,zip,file,that,installed,target,system,unzip,destination,directory,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Add,Uninstall,property,true,any,directory,file,created,while,unzipping,file,added,uninstall,log,removed,later,during,uninstallation,Destination,new,path,unpack,zip,file,path,relative,made,relative,<%InstallDir%>,Progress,Virtual,Text,not,null,specifies,virtual,text,variable,update,with,percentage,complete,files,unzipped,Status,Virtual,Text,not,null,specifies,virtual,text,variable,update,with,status,files,they,unzipped,virtual,text,set,value,Status,Text,then,updated,Zip,File,path,zip,ile,directory,unpacked,path,relative,made,relative,<%InstallDir%>,Text,Properties,Status,Text,text,string,use,when,showing,status,during,unzip,Examples,following,values,would,unpack,file,foo,zip,into,directory,foo,zip,foo[$XTITLE$]Unzip,File[$XTITELEND$][$XKEYS$]Unzip,File[$XKEYSEND$]`;";
s[80] = "Continue Install^ContinueInstall.html^This action continues file installation if it was previously paused using the Pause Install action....^Continue Install^action,continues,file,installation,was,previously,paused,using,Pause,Install,action,Standard,Properties,See,Standard,Action,Properties,Install[$XTITELEND$][$XKEYS$]Continue,Install[$XKEYSEND$]`;";
s[81] = "Exit^Exit.html^This action will cause the installer to exit.Standard Properties  See Standard Action Proper...^Exit^action,cause,installer,exit,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Exit,Code,property,not,empty,specifies,exit,code,exit,installer,with,default,installer,exit,with,finishes,successfully,install,canceled,Exit,Type,property,tells,InstallJammer,what,kind,exit,Whether,it's,cancel,finish,mostly,affects,what,action,group,InstallJammer,execute,executing`;";
s[82] = "Fetch URL^FetchURL.html^This action will fetch a given URL from the web and store the result into a file on the local system...^Fetch URL^action,fetch,given,URL,from,web,store,result,into,file,local,system,useful,for,downloading,pieces,installer,that,you,don't,want,package,but,want,download,when,user,opts,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Progress,Virtual,Text,name,virtual,text,variable,fill,with,progress,file,downloaded,variable,hold,percent,complete,file,downloaded,You,can,use,pane,with,progress,bar,track,progress,download,Proxy,Host,hostname,proxy,server,use,when,making,request,Proxy,Port,port,proxy,host,use,when,making,request,Save,Specifies,that,you,want,save,fetched,file,file,virtual,text,variable,Target,saving,file,name,file,directory,save,directory,file,name,derived,from,URL,itself,saving,file,property,holds,virtual,text,variable,without,save,file,contents,Timeout,time,microseconds,wait,before,giving,when,trying,connect,download,file,URL,URL,fetch,URL[$XTITELEND$][$XKEYS$]Fetch,URL[$XKEYSEND$]`;";
s[83] = "Generate UID^GenerateUID.html^This action will generate a GUID or UUID and store the result in a virtual text variable.Stand...^Generate UID^action,generate,GUID,UUID,store,result,virtual,text,variable,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,UID,Type,Whether,generate,GUID,UUID,GUID,just,UUID,with,curly,braces,around,Virtual,Text,name,virtual,text,variable,without,store,new,UID,into,UID[$XTITELEND$][$XKEYS$]Generate,UID[$XKEYSEND$]`;";
s[84] = "Launch File^LaunchFile.html^This action will launch the given file on the target system using a default method for the file type...^Launch File^action,launch,given,file,target,system,using,default,method,for,file,type,given,file,InstallJammer,uses,default,method,target,platform,launch,file,based,its,file,type,Files,UNIX,launched,using,xdg,open,xdg,utils,package,that,part,portland,project,freedesktop,org,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Arguments,list,arguments,pass,command,line,when,launching,file,File,Name,name,file,target,system,launch,Wait,for,Program,Whether,InstallJammer,should,wait,for,program,finish,exit,before,continuing,with,rest,install,Working,Directory,property,not,null,InstallJammer,change,directory,directory,before,launching,file,File[$XTITELEND$][$XKEYS$]Launch,File[$XKEYSEND$]`;";
s[85] = "Launch Web Browser^LaunchWebBrowser.html^This action will launch a web browser to the specified URL on the target system.  InstallJammer will...^Launch Web Browser^action,launch,web,browser,specified,URL,target,system,InstallJammer,attempt,use,default,web,browser,for,target,operating,system,fails,find,default,web,browser,InstallJammer,attempt,find,suitable,browser,Windows,URL,launched,using,whatever,default,browser,for,current,user,UNIX,desktop,environment,KDE,Gnome,default,method,for,launching,URL,used,that,method,fails,desktop,some,other,window,manager,action,attempt,find,suitable,web,browser,based,environment,known,browsers,URLs,UNIX,launched,using,xdg,open,from,xdg,utils,package,that,part,portland,project,freedesktop,org,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,URL,URL,point,web,browser,when,launches,Web,Browser[$XTITELEND$][$XKEYS$]Launch,Web,Browser[$XKEYSEND$]`;";
s[86] = "Log Debug Message^LogDebugMessage.html^This action will log a message to the debug log and to the console when an installer is run in debug...^Log Debug Message^action,log,message,debug,log,console,when,installer,run,debug,mode,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Message,message,output,debug,log,Debug,Message[$XTITELEND$][$XKEYS$]Log,Debug,Message[$XKEYSEND$]`;";
s[87] = "Message Box^MessageBox.html^This action will pop up a message box that requires the user's attention.  It can be used simply to ...^Message Box^action,pop,message,box,that,requires,user's,attention,can,used,simply,give,user,notice,something,can,used,ask,user,question,get,answer,Once,posted,InstallJammer,not,continue,with,install,until,user,has,clicked,button,close,message,box,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Default,Button,button,focus,default,default,action,user,simply,hits,Enter,when,message,box,pops,Icon,choice,icon,display,message,box,giving,user,indication,what,type,message,Type,type,message,box,display,several,common,types,choose,from,Each,type,display,with,given,list,buttons,Virtual,Text,Field,virtual,text,variable,hold,result,message,box,variable,contain,name,button,user,clicked,name,button,text,displayed,button,all,lowercase,user,clicks,Yes,virtual,text,set,yes,Box[$XTITELEND$][$XKEYS$]Message,Box[$XKEYSEND$]`;";
s[88] = "Message Panel^MessagePanel.html^A message panel is a borderless, buttonless panel that pops up to display some message to the user. ...^Message Panel^message,panel,borderless,buttonless,panel,that,pops,display,some,message,user,usually,done,when,installer,doing,something,that,may,take,moment,you,want,user,see,what,happening,Once,message,panel,posted,unless,given,timeout,must,destroyed,using,Destroy,Widget,action,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Anchor,position,screen,display,message,panel,Default,center,screen,Grab,Focus,tells,InstallJammer,grab,focus,from,user,that,they,can't,interact,with,anything,else,installer,while,message,panel,screen,Height,height,message,panel,pixels,Image,icon,display,left,side,message,panel,Image,Pad,How,many,pixels,pad,image,left,right,from,rest,panel,single,number,means,pad,image,both,sides,that,amount,Two,numbers,means,pad,image,left,first,number,pixels,pad,right,second,number,pixels,Image,Pad,How,many,pixels,pad,image,top,bottom,from,rest,panel,single,number,means,pad,image,both,sides,that,amount,Two,numbers,means,pad,image,top,first,number,pixels,pad,bottom,second,number,pixels,Label,Anchor,anchor,for,text,label,Label,Pad,How,many,pixels,pad,label,left,right,from,rest,panel,single,number,means,pad,label,both,sides,that,amount,Two,numbers,means,pad,label,left,first,number,pixels,pad,right,second,number,pixels,Label,Pad,How,many,pixels,pad,label,top,bottom,from,rest,panel,single,number,means,pad,label,both,sides,that,amount,Two,numbers,means,pad,label,top,first,number,pixels,pad,bottom,second,number,pixels,Timeout,number,seconds,panel,should,stay,screen,value,panel,stay,screen,until,destroyed,with,Destroy,Widget,action,Width,width,message,panel,pixels,Panel[$XTITELEND$][$XKEYS$]Message,Panel[$XKEYSEND$]`;";
s[89] = "Modify Object^ModifyObject.html^This action is used to modify the properties of any object in an installer.  See Object Types for a ...^Modify Object^action,used,modify,properties,any,object,installer,See,Object,Types,for,description,available,object,types,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Object,State,specified,says,that,given,object,should,Active,Inactive,Object,alias,object,modified,Object[$XTITELEND$][$XKEYS$]Modify,Object[$XKEYSEND$]`;";
s[90] = "Pause Install^PauseInstall.html^This action will pause the file installation that is currently in progress.  Once paused, the instal...^Pause Install^action,pause,file,installation,that,currently,progress,Once,paused,install,must,either,stopped,using,Stop,Install,action,continued,using,Continue,Install,action,Standard,Properties,See,Standard,Action,Properties,Install[$XTITELEND$][$XKEYS$]Pause,Install[$XKEYSEND$]`;";
s[91] = "Set Object Property^SetObjectProperty.html^This action will set the value of any property on a given object.Standard Properties  See St...^Set Object Property^action,set,value,any,property,given,object,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Object,alias,object,set,property,Property,property,set,given,object,Substitute,Value,property,true,Value,substituted,fully,for,virtual,text,before,being,set,new,property,value,Value,value,set,property,object,Object,Property[$XTITELEND$][$XKEYS$]Set,Object,Property[$XKEYSEND$]`;";
s[92] = "Set Virtual Text^SetVirtualText.html^This action will set the value of a virtual text variable.Standard Properties  See Standard ...^Set Virtual Text^action,set,value,virtual,text,variable,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Auto,Update,property,true,virtual,text,being,set,added,list,variables,that,automatically,update,screen,whenever,they,changed,default,InstallJammer,only,updates,screen,during,actions,when,moving,between,panes,make,virtual,text,cause,update,anytime,its,value,changes,Language,property,tells,InstallJammer,what,language,set,virtual,text,value,None,virtual,text,set,non,localized,variable,that,works,for,all,languages,virtual,text,already,exists,language,though,that,value,override,non,localized,value,Value,new,value,set,virtual,text,variable,Virtual,Text,name,virtual,text,variable,set,Virtual,Text[$XTITELEND$][$XKEYS$]Set,Virtual,Text[$XKEYSEND$]`;";
s[93] = "Stop Install^StopInstall.html^This action stops file installation if it was previously paused using the Pause Install action....^Stop Install^action,stops,file,installation,was,previously,paused,using,Pause,Install,action,Standard,Properties,See,Standard,Action,Properties,Install[$XTITELEND$][$XKEYS$]Stop,Install[$XKEYSEND$]`;";
s[94] = "Text Window^TextWindow.html^This action pops up a simple text window to display a long bit of text to the user.  It is useful fo...^Text Window^action,pops,simple,text,window,display,long,bit,text,user,useful,for,posting,text,files,like,READMEs,for,displaying,progressive,output,from,Execute,External,Program,action,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Anchor,position,screen,display,message,panel,Default,center,screen,Grab,Focus,tells,InstallJammer,grab,focus,from,user,that,they,can't,interact,with,anything,else,installer,while,message,panel,screen,Height,height,text,window,pixels,Image,icon,display,left,side,message,panel,Text,File,name,file,target,system,read,display,text,window,Text,Wrap,Tells,textbox,how,wrap,text,Wait,Window,value,true,InstallJammer,wait,for,user,close,window,before,continuing,with,installation,false,text,window,pop,install,continue,Width,width,text,window,pixels,Window[$XTITELEND$][$XKEYS$]Text,Window[$XKEYSEND$]`;";
s[95] = "Wait^Wait.html^This action will cause InstallJammer to wait a specified number of milliseconds before continuing wi...^Wait^action,cause,InstallJammer,wait,specified,number,milliseconds,before,continuing,with,install,works,just,like,sleep,most,systems,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Wait,Time,amount,time,milliseconds,wait,1000,second`;";
s[96] = "Add Install Info^AddInstallInfo.html^This action is used to add your own information to the InstallJammer registry for the installed appl...^Add Install Info^action,used,add,your,own,information,InstallJammer,registry,for,installed,application,information,can,retrieved,later,through,Check,for,Previous,Install,action,just,reading,install,registry,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Key,name,property,store,registry,should,short,key,containing,alpha,numeric,characters,Value,value,store,registry,under,Key,value,automatically,substituted,for,virtual,text,before,stored,registry,Example,following,values,would,record,install,mode,user,used,during,installation,Mode,<%InstallMode%>,Then,when,using,Check,for,Previous,Install,you,would,have,virtual,text,<%PreviousInstallMode%>,that,equals,whatever,mode,user,installed,with,Console,Silent,Standard,etc,Install,Info[$XTITELEND$][$XKEYS$]Add,Install,Info[$XKEYSEND$]`;";
s[97] = "Add Response File Info^AddResponseFileInfo.html^This action is used to add virtual text variables to the list of variables to saved to a response fi...^Add Response File Info^action,used,add,virtual,text,variables,list,variables,saved,response,file,when,writing,user,has,passed,save,response,file,command,line,signifying,that,they,want,save,responses,from,installer,file,exit,only,virtual,text,which,has,been,designated,save,saved,Use,action,add,virtual,text,list,what,save,default,virtual,text,variables,saved,with,every,response,CreateDesktopShortcut,CreateQuickLaunchShortcut,InstallDir,InstallMode,InstallType,LaunchApplication,ProgramFolderName,SelectedComponents,ViewReadme,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Virtual,Text,list,virtual,text,variables,separated,Each,virtual,text,can,also,specified,with,type,that,tell,installer,how,should,saved,file,read,back,current,types,supported,described,below,boolean,virtual,text,saved,Yes,depending,its,current,value,list,virtual,text,considered,valid,Tcl,list,saved,comma,separated,list,When,specifying,your,list,virtual,text,you,can,specify,type,adding,after,virtual,text,name,Example,Virtual,Foo,Bar,list,MyBool,boolean,would,add,three,virtual,text,Foo,Bar,MyBool,list,variables,stored,response,file,Foo,would,stored,with,interpretation,Bar,would,stored,list,which,means,that,<%Bar%>,contains,valid,Tcl,list,stored,comma,separated,list,response,file,MyBool,boolean,installer,take,whatever,value,<%MyBool%>,determine,true,false,convert,it's,value,response,file,Yes,Any,boolean,value,perfectly,valid,within,response,file,but,Yes,used,make,easier,user,read,file,Response,File,Info[$XTITELEND$][$XKEYS$]Add,Response,File,Info[$XKEYSEND$]`;";
s[98] = "Add to Uninstall^AddToUninstall.html^This action will add a directory, file or registry entry to the install log so that InstallJammer wi...^Add to Uninstall^action,add,directory,file,registry,entry,install,log,that,InstallJammer,attempt,uninstall,during,uninstallation,allows,you,add,things,uninstall,that,might,generated,your,application,but,you,don't,want,bother,user,with,deleting,themselves,action,used,during,uninstallation,before,uninstall,actually,begins,directory,file,registry,key,added,list,files,about,uninstalled,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Component,Name,name,component,uninstall,either,name,file,directory,name,Windows,registry,key,uninstall,Component,Type,tells,InstallJammer,what,type,component,being,added,uninstall,Forcefully,Remove,Directory,value,true,InstallJammer,delete,directory,regardless,whether,has,anything,not,default,InstallJammer,not,delete,directory,that,not,empty,Registry,Value,value,non,empty,tells,InstallJammer,remove,value,specified,registry,key,instead,registry,key,itself,value,left,blank,InstallJammer,uninstall,entire,registry,entry,Uninstall[$XTITELEND$][$XKEYS$]Add,Uninstall[$XKEYSEND$]`;";
s[99] = "Check for Previous Install^CheckForPreviousInstall.html^This action checks the target system for a previous install of your application and sets up virtual ...^Check for Previous Install^action,checks,target,system,for,previous,install,your,application,sets,virtual,text,variables,result,When,searching,for,previous,install,InstallJammer,uses,Application,your,project,find,following,virtual,text,variables,set,result,Version,InstallJammer,only,defined,<%PreviousInstallExists%>,<%PreviousInstallDir%>,variables,You,should,use,Virtual,Text,Exists,Condition,you,unsure,whether,previous,install,virtual,text,you,want,exists,<%PreviousInstallExists%>,false,none,rest,virtual,text,set,<%PreviousInstallApplicationID%>,Application,previously,installed,application,should,match,your,own,Application,unless,previous,install,was,upgrade,install,that,case,Upgrade,Install,should,match,your,application,<%PreviousInstallDate%>,install,date,last,install,clock,seconds,can,formatted,using,<%Date%>,virtual,text,<%PreviousInstallCount%>,number,previous,installations,found,target,system,Only,last,install,date,used,for,information,<%PreviousInstallDir%>,installation,directory,last,install,<%PreviousInstallDirExists%>,convenience,value,that,tells,you,whether,not,previous,install,dir,still,exists,target,system,<%PreviousInstallExecutable%>,full,path,previous,install,executable,when,was,run,<%PreviousInstallExists%>,value,true,previous,install,was,found,false,one,was,not,found,<%PreviousInstallID%>,Install,last,install,that,generated,everytime,installer,run,change,with,each,subsequent,install,<%PreviousInstallIDs%>,virtual,text,contains,list,all,previous,install,IDs,that,have,been,installed,for,application,<%PreviousInstallRealUser%>,real,username,person,who,installed,last,real,username,even,user,was,running,root,<%PreviousInstallSource%>,directory,where,previous,installer,was,run,from,<%PreviousInstallUninstaller%>,full,path,uninstaller,last,install,<%PreviousInstallUpgradeID%>,Upgrade,Application,last,install,<%PreviousInstallUser%>,username,person,who,installed,last,<%PreviousInstallVersion%>,install,version,etc,last,install,<%PreviousInstallVersionString%>,install,version,string,0a1,etc,last,install,Other,variables,can,also,set,developer,has,added,information,install,registry,through,Add,Install,Info,action,Any,variable,added,through,that,action,also,appear,virtual,text,result,action,For,Key,Foo,was,added,with,Value,Bar,you,would,get,variable,<%PreviousInstallFoo%>,that,would,equal,Bar,Standard,Properties,See,Standard,Action,Properties,for,Previous,Install[$XTITELEND$][$XKEYS$]Check,for,Previous,Install[$XKEYSEND$]`;";
s[100] = "Get Previous Install Info^GetPreviousInstallInfo.html^This action gets a specific set of install information based on a given Install ID.  Since a single ...^Get Previous Install Info^action,gets,specific,set,install,information,based,given,Install,Since,single,application,can,have,multiple,installations,same,system,action,can,used,get,specific,information,from,specific,install,You,must,first,find,Install,though,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Application,Application,read,previous,install,information,from,defaults,current,installer's,<%ApplicationID%>,but,action,can,also,used,read,install,information,from,other,installations,Install,install,install,whose,information,you,want,get,Virtual,Text,Prefix,string,prefix,beginning,each,piece,information,from,install,registry,prefix,used,for,each,variable,from,registry,add,information,virtual,text,variables,depending,what,information,available,following,virtual,text,variables,set,result,action,assuming,that,your,Virual,Text,Prefix,PreviousInstall,<%PreviousInstallApplicationID%>,Application,previously,installed,application,should,match,your,own,Application,unless,previous,install,was,upgrade,install,that,case,Upgrade,Install,should,match,your,application,<%PreviousInstallDate%>,install,date,last,install,clock,seconds,can,formatted,using,<%Date%>,virtual,text,<%PreviousInstallCount%>,number,previous,installations,found,target,system,Only,last,install,date,used,for,information,<%PreviousInstallDir%>,installation,directory,last,install,<%PreviousInstallDirExists%>,convenience,value,that,tells,you,whether,not,previous,install,dir,still,exists,target,system,<%PreviousInstallExecutable%>,full,path,previous,install,executable,when,was,run,<%PreviousInstallExists%>,value,true,previous,install,was,found,false,one,was,not,found,<%PreviousInstallID%>,Install,last,install,that,generated,everytime,installer,run,change,with,each,subsequent,install,<%PreviousInstallRealUser%>,real,username,person,who,installed,last,real,username,even,user,was,running,root,<%PreviousInstallSource%>,directory,where,previous,installer,was,run,from,<%PreviousInstallUninstaller%>,full,path,uninstaller,last,install,<%PreviousInstallUpgradeID%>,Upgrade,Application,last,install,<%PreviousInstallUser%>,username,person,who,installed,last,<%PreviousInstallVersion%>,install,version,etc,last,install,<%PreviousInstallVersionString%>,install,version,string,0a1,etc,last,install,Other,variables,can,also,set,developer,has,added,information,install,registry,through,Add,Install,Info,action,Any,variable,added,through,that,action,also,appear,virtual,text,result,action,For,Key,Foo,was,added,with,Value,Bar,you,would,get,variable,<%PreviousInstallFoo%>,that,would,equal,Bar,Previous,Install,Info[$XTITELEND$][$XKEYS$]Get,Previous,Install,Info[$XKEYSEND$]`;";
s[101] = "Install Log File^InstallLogFile.html^This action installs a copy of the InstallJammer install log into a target location.  By default, In...^Install Log File^action,installs,copy,InstallJammer,install,log,into,target,location,default,InstallJammer,installs,log,registry,directory,that,uses,for,subsequent,installs,uninstallation,but,action,let,you,create,copy,somewhere,else,system,well,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Log,File,Location,directory,filename,where,you,want,install,log,file,Log,File[$XTITELEND$][$XKEYS$]Install,Log,File[$XKEYSEND$]`;";
s[102] = "Install Selected Files^InstallSelectedFiles.html^This is the main action of the installation process.  This action starts up the actual file installa...^Install Selected Files^main,action,installation,process,action,starts,actual,file,installation,process,handles,installing,all,files,user,has,selected,install,during,process,action,created,Install,Actions,group,default,which,executed,from,Copy,Files,pane,new,install,project,but,you,can,move,anywhere,you,like,remove,all,together,your,installer,not,actually,installing,any,files,action,build,list,groups,files,installed,based,current,Setup,Type,Components,Setup,Type,first,checked,any,Component,that,inactive,skipped,Then,File,Groups,beneath,Component,checked,any,File,Group,that,inactive,skipped,Finally,any,file,contained,File,Groups,that,inactive,skipped,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Show,Console,Progress,property,true,progress,bar,shown,during,console,installs,Update,File,Text,property,true,text,properties,progress,pane,updated,every,time,new,file,begins,installation,default,InstallJammer,shows,what,group,being,installed,not,each,every,file,Updating,window,with,each,file,can,expensive,can,take,longer,than,just,updating,when,new,group,being,installed,Update,File,Percent,should,only,set,true,you,have,two,progress,bars,same,pane,one,tracking,progress,each,individual,file,using,<%FilePercentComplete%>,Again,noted,above,can,very,expensive,take,longer,install,you,updating,every,single,file,change,Selected,Files[$XTITELEND$][$XKEYS$]Install,Selected,Files[$XKEYSEND$]`;";
s[103] = "Install Uninstaller^InstallUninstaller.html^This action creates an uninstaller for the current installation on the target system.  This action m...^Install Uninstaller^action,creates,uninstaller,for,current,installation,target,system,action,must,come,after,Install,Selected,Files,action,that,action,that,builds,list,files,directories,registry,entries,uninstalled,careful,installing,more,than,one,uninstaller,target,system,InstallJammer,register,its,package,information,with,last,uninstaller,installed,that,what,use,during,uninstallation,usually,best,only,install,one,instance,uninstaller,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Message,message,that,used,status,while,uninstall,being,built,Uninstall,Directory,specifies,what,directory,you,want,create,uninstaller,default,created,main,installation,directory,Uninstall,Filename,file,name,use,for,uninstaller,target,system,defaults,uninstall,with,appropriate,extension,Uninstaller[$XTITELEND$][$XKEYS$]Install,Uninstaller[$XKEYSEND$]`;";
s[104] = "Install Wish Binary^InstallWishBinary.html^This action creates a Tcl/Tk Wish binary on the target system.  It is not actually a standard Wish b...^Install Wish Binary^action,creates,Wish,binary,target,system,not,actually,standard,Wish,binary,but,single,file,executable,wish,that,built,from,base,installkit,installkit,stand,alone,WISH,shell,that,contains,Tcl,Tile,Tkpng,Itcl,Thread,Windows,only,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Binary,Name,name,wish,binary,you,wish,create,Windows,Icon,Windows,specifies,ico,file,use,icon,for,binary,Windows,Icon,specified,wish,binary,have,same,icon,original,installer,Wish,Binary[$XTITELEND$][$XKEYS$]Install,Wish,Binary[$XKEYSEND$]`;";
s[105] = "Install Wrapped Script^InstallWrappedScript.html^This action takes a Tcl/Tk script and wraps it into a self-contained binary executable on the target...^Install Wrapped Script^action,takes,script,wraps,into,self,contained,binary,executable,target,system,tcl,script,wrapped,with,same,installkit,that,built,installer,uses,internal,command,wrap,script,into,its,own,executable,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Binary,Name,name,target,binary,target,system,Company,Windows,specifies,Company,name,store,Windows,Resource,information,file,File,Description,Windows,specifies,File,Description,store,Windows,Resource,information,file,File,Version,Windows,specifies,File,Version,store,Windows,Resource,information,file,Include,TWAPI,property,true,TWAPI,included,current,installer,TWAPI,extension,included,wrapped,script,when,built,specified,script,changed,include,some,code,top,script,load,TWAPI,extension,startup,not,necessary,package,require,extension,Installkit,path,installkit,used,wrap,script,left,blank,current,running,installer,used,base,installkit,Product,Name,Windows,specifies,Product,Name,store,Windows,Resource,information,file,Product,Version,Windows,specifies,Product,Version,store,Windows,Resource,information,file,Tcl,Startup,Script,tcl,script,wrap,into,binary,Windows,Icon,Windows,specifies,ico,file,use,icon,for,binary,Windows,Icon,specified,wish,binary,have,same,icon,original,installer,Wrapped,Script[$XTITELEND$][$XKEYS$]Install,Wrapped,Script[$XKEYSEND$]`;";
s[106] = "Unpack Stored File^UnpackStoredFile.html^This action will unpack a file stored in the installer to a specified location on the target system....^Unpack Stored File^action,unpack,file,stored,installer,specified,location,target,system,Since,installer,already,unpack,all,selected,files,during,installation,action,should,only,used,extract,file,special,location,before,actual,installation,performed,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Add,Uninstall,property,true,unpacked,file,added,list,files,for,uninstaller,remove,Files,unpacked,<%Temp%>,directory,never,added,uninstall,File,file,unpack,can,valid,any,file,stored,installer,alias,file,Target,Directory,target,directory,unpack,file,into,Target,Filename,name,file,create,property,left,blank,name,file,same,name,that,was,stored,with,Stored,File[$XTITELEND$][$XKEYS$]Unpack,Stored,File[$XKEYSEND$]`;";
s[107] = "Get Java Property^GetJavaProperty.html^This action will retrieve a specified property value from a standard Java properties file.Stan...^Get Java Property^action,retrieve,specified,property,value,from,standard,Java,properties,file,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Property,name,property,get,from,property,file,Property,File,path,property,file,open,Virtual,Text,name,virtual,text,variable,fill,with,property,found,property,file,property,not,found,property,file,value,virtual,text,blank,Java,Property[$XTITELEND$][$XKEYS$]Get,Java,Property[$XKEYSEND$]`;";
s[108] = "Locate Java Runtime^LocateJavaRuntime.html^This action attempts to locate the most suitable Java Runtime Environment (JRE) available on the tar...^Locate Java Runtime^action,attempts,locate,most,suitable,Java,Runtime,Environment,JRE,available,target,system,does,looking,some,default,paths,environment,variables,system,well,allowing,you,specify,locations,check,action,successfully,finds,suitable,JRE,following,virtual,text,variable,set,<%JavaAvailableVersions%>,list,available,versions,found,target,system,before,finding,correct,one,Once,acceptable,JRE,found,InstallJammer,stops,looking,list,only,include,including,JRE,found,that,matches,needs,<%JavaExecutable%>,full,path,java,executable,usually,<%JavaFound%>,True,Java,runtime,was,found,false,none,was,found,<%JavaHome%>,Java,home,directory,<%JavaVersion%>,version,Java,runtime,found,2_11,etc,<%JavaVersionMajor%>,major,version,Java,runtime,found,etc,<%JavaVersionMinor%>,minor,version,Java,runtime,found,etc,<%JavacExecutable%>,full,path,javac,executable,found,javac,executable,not,found,virtual,text,not,set,<%JavawExecutable%>,full,path,javaw,executable,found,not,found,variable,point,main,java,executable,instead,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Maximum,Version,property,tells,Installjammer,maximum,version,JRE,you,accept,Minimum,Version,property,tells,InstallJammer,minimum,version,JRE,you,accept,Require,JDK,property,true,action,require,that,full,JDK,Java,Development,Kit,installed,not,just,JRE,Java,Runtime,Environment,make,installer,search,for,existence,javac,Java,compiler,that,lacking,JRE,installation,binary,determine,installation,JDK,Search,Path,property,tells,InstallJammer,how,search,for,JRE,value,list,paths,check,for,suitable,java,installation,separated,Default,Search,Path,included,path,InstallJammer,use,defaults,like,environment,variables,user's,PATH,target,system,try,find,JRE,Default,Search,Path,searches,following,JAVA_HOME,environment,variable,JAVAHOME,environment,variable,JDK_HOME,environment,variable,JRE_HOME,environment,variable,JAVA_ROOT,environment,variable,JAVA_BINDIR,environment,variable,PATH,environment,variable,Windows,registry,Windows,only,Program,Windows,only,UNIX,only,UNIX,only,UNIX,only,UNIX,only,UNIX,only,UNIX,only,UNIX,only,UNIX,only,Prompt,User,included,path,InstallJammer,check,all,other,paths,order,upon,reaching,Prompt,User,prompt,user,asking,specify,location,runtime,environment,usually,best,left,last,path,that,all,other,directories,checked,before,finally,prompting,user,when,JRE,has,been,found,Java,Runtime[$XTITELEND$][$XKEYS$]Locate,Java,Runtime[$XKEYSEND$]`;";
s[109] = "Install Desktop Shortcut^InstallDesktopShortcut.html^This action installs a shortcut on the desktop of the target system depending on the system and desk...^Install Desktop Shortcut^action,installs,shortcut,desktop,target,system,depending,system,desktop,environments,found,UNIX,systems,action,looks,for,existence,both,KDE,Gnome,install,shortcut,either,both,desktops,available,user,root,when,they,run,install,shortcut,added,for,all,users,system,they,not,root,shortcuts,only,added,for,user,doing,installation,UNIX,shortcuts,installed,using,xdg,icon,desktop,utility,from,xdg,utils,package,that,part,portland,project,freedesktop,org,Supported,Platforms,All,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Additional,Arguments,property,contains,any,number,lines,added,UNIX,desktop,file,after,standard,properties,that,setup,InstallJammer,Each,line,substituted,for,virtual,text,then,appended,desktop,file,without,any,further,modification,Command,Line,Arguments,property,specifies,arguments,passed,target,filename,Windows,platform,Icon,Path,property,specifies,file,use,for,icon,for,shortcut,Windows,can,ico,exe,any,other,file,containing,icon,information,UNIX,platforms,usually,points,png,file,display,Icon,Path,Index,index,into,file,that,Windows,uses,when,looking,for,icon,Install,for,All,Users,Windows,option,true,desktop,shortcut,installed,for,all,users,not,just,current,user,Shortcut,Name,name,display,for,shortcut,Shortcut,Type,UNIX,specifies,what,type,shortcut,can,shortcut,URL,Link,shortcut,Application,Target,File,Name,name,file,shortcut,points,UNIX,shortcut,that,has,type,Link,URL,point,Working,Directory,Windows,specifies,working,directory,that,target,shortcut,start,Vendor,Vendor,used,group,all,shortcuts,program,folders,together,UNIX,platforms,default,everything,grouped,Application,current,installer,but,setting,common,value,would,allow,for,all,installers,your,company,share,program,folders,for,example,Desktop,Shortcut[$XTITELEND$][$XKEYS$]Install,Desktop,Shortcut[$XKEYSEND$]`;";
s[110] = "Install Program Folder Shortcut^InstallProgramFolderShortcut.html^This action installs a shortcut into the Program Folder for your application on the target system de...^Install Program Folder Shortcut^action,installs,shortcut,into,Program,Folder,for,your,application,target,system,depending,system,desktop,environments,found,UNIX,systems,action,looks,for,existence,both,KDE,Gnome,install,shortcut,under,either,both,menus,available,user,root,when,they,run,install,shortcut,added,for,all,users,system,they,not,root,shortcuts,only,added,for,user,doing,installation,UNIX,shortcuts,installed,using,xdg,icon,menu,utility,from,xdg,utils,package,that,part,portland,project,freedesktop,org,Supported,Platforms,All,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Additional,Arguments,property,contains,any,number,lines,added,UNIX,desktop,file,after,standard,properties,that,setup,InstallJammer,Each,line,substituted,for,virtual,text,then,appended,desktop,file,without,any,further,modification,Command,Line,Arguments,property,specifies,arguments,passed,target,filename,Windows,platform,Icon,Path,property,specifies,file,use,for,icon,for,shortcut,Windows,can,ico,exe,any,other,file,containing,icon,information,UNIX,platforms,usually,points,png,file,display,Icon,Path,Index,index,into,file,that,Windows,uses,when,looking,for,icon,Install,for,All,Users,Windows,option,true,desktop,shortcut,installed,for,all,users,not,just,current,user,Shortcut,Name,name,display,for,shortcut,Shortcut,Type,UNIX,specifies,what,type,shortcut,can,shortcut,URL,Link,shortcut,Application,Target,File,Name,name,file,shortcut,points,UNIX,shortcut,that,has,type,Link,URL,point,Working,Directory,Windows,specifies,working,directory,that,target,shortcut,start,Vendor,Vendor,used,group,all,shortcuts,program,folders,together,UNIX,platforms,default,everything,grouped,Application,current,installer,but,setting,common,value,would,allow,for,all,installers,your,company,share,program,folders,for,example,Program,Folder,Shortcut[$XTITELEND$][$XKEYS$]Install,Program,Folder,Shortcut[$XKEYSEND$]`;";
s[111] = "Install UNIX Program Folder^InstallUNIXProgramFolder.html^his action creates a desktop shortcut file on a UNIX system.If the user is root when they run ...^Install UNIX Program Folder^action,creates,desktop,shortcut,file,UNIX,system,user,root,when,they,run,install,folder,added,for,all,users,system,they,not,root,folder,only,added,for,user,doing,installation,UNIX,program,folders,installed,using,xdg,utils,package,that,part,portland,project,freedesktop,org,Supported,Platforms,FreeBSD,Linux,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Additional,Arguments,property,contains,any,number,lines,added,directory,file,after,standard,properties,that,setup,InstallJammer,Each,line,substituted,for,virtual,text,then,appended,desktop,file,without,any,further,modification,Folder,Directory,directory,install,shortcut,Folder,Location,set,Directory,Folder,Location,Specifies,whether,you,want,create,directory,file,some,directory,your,choosing,under,standard,program,folder,Folder,Name,name,folder,create,target,system,Icon,Path,property,specifies,file,use,for,icon,for,shortcut,usually,points,png,file,display,Vendor,Vendor,used,group,all,shortcuts,program,folders,together,default,everything,grouped,Application,current,installer,but,setting,common,value,would,allow,for,all,installers,your,company,share,program,folders,for,example,UNIX,Program,Folder[$XTITELEND$][$XKEYS$]Install,UNIX,Program,Folder[$XKEYSEND$]`;";
s[112] = "Install UNIX Shortcut^InstallUNIXShortcut.html^his action creates a desktop shortcut file on a UNIX system.If the user is root when they run ...^Install UNIX Shortcut^action,creates,desktop,shortcut,file,UNIX,system,user,root,when,they,run,install,shortcut,added,for,all,users,system,they,not,root,shortcuts,only,added,for,user,doing,installation,UNIX,shortcuts,installed,using,xdg,utils,package,that,part,portland,project,freedesktop,org,Supported,Platforms,FreeBSD,Linux,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Additional,Arguments,property,contains,any,number,lines,added,UNIX,desktop,file,after,standard,properties,that,setup,InstallJammer,Each,line,substituted,for,virtual,text,then,appended,desktop,file,without,any,further,modification,Command,Line,Arguments,property,contains,arguments,that,should,appended,target,filename,form,full,command,line,for,shortcut,differs,from,Additional,Arguments,that,additional,arguments,lines,that,directly,appended,desktop,file,when,created,target,system,command,line,arguments,concatenated,with,target,filename,form,command,line,execute,File,Name,name,desktop,file,target,system,File,Name,property,cannot,empty,Icon,Path,property,specifies,file,use,for,icon,for,shortcut,usually,points,png,file,display,Program,Folder,Name,shortcut,being,installed,going,into,Program,Folder,name,program,folder,put,into,default,uses,program,folder,for,rest,installation,Shortcut,Directory,directory,install,shortcut,Shortcut,Location,Where,install,shortcut,can,either,directory,Desktop,Program,Folder,shortcut,installed,directory,desktop,file,simply,created,shortcut,directory,with,given,values,shortcut,installed,Desktop,Shortcut,Directory,ignored,file,installed,Desktop,shortcut,installed,Program,Folder,installed,program,folder,under,specified,Program,Folder,Name,Shortcut,Name,name,display,for,shortcut,Shortcut,Type,specifies,what,type,shortcut,can,shortcut,URL,Link,shortcut,Application,Target,File,Name,name,file,shortcut,points,shortcut,has,type,Link,URL,point,Vendor,Vendor,used,group,all,shortcuts,program,folders,together,default,everything,grouped,Application,current,installer,but,setting,common,value,would,allow,for,all,installers,your,company,share,program,folders,for,example,UNIX,Shortcut[$XTITELEND$][$XKEYS$]Install,UNIX,Shortcut[$XKEYSEND$]`;";
s[113] = "Install Windows Shortcut^InstallWindowsShortcut.html^This action installs a shortcut on the desktop of the target system depending on the system and desk...^Install Windows Shortcut^action,installs,shortcut,desktop,target,system,depending,system,desktop,environments,found,UNIX,systems,action,looks,for,existence,both,KDE,Gnome,install,shortcut,either,both,desktops,available,Target,File,Name,looks,like,URL,etc,shortcut,URL,shortcut,Target,File,Name,does,not,look,like,URL,assumed,file,target,system,file,must,exist,file,does,not,exist,shortcut,created,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Command,Line,Arguments,property,specifies,arguments,passed,target,filename,These,arguments,appended,Target,File,Name,when,creating,shortcut,that,when,shortcut,executed,Target,File,Name,called,with,given,arguments,Description,property,sets,Comments,property,Windows,shortcut,which,also,tooltip,that,displayed,mouse,hovered,over,shortcut,Icon,Path,property,specifies,file,use,for,icon,for,shortcut,can,ico,exe,any,other,file,containing,icon,information,Icon,Path,Index,index,into,file,that,Windows,uses,when,looking,for,icon,Shortcut,Directory,directory,install,shortcut,Shortcut,Name,name,display,for,shortcut,Target,File,Name,name,file,shortcut,points,Working,Directory,specifies,working,directory,that,target,shortcut,start,Windows,Shortcut[$XTITELEND$][$XKEYS$]Install,Windows,Shortcut[$XKEYSEND$]`;";
s[114] = "Add Directory to Path^AddDirectoryToPath.html^This action is used to add a directory to a path variable of the target system.Supported Platf...^Add Directory to Path^action,used,add,directory,path,variable,target,system,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Add,Uninstall,property,true,added,paths,automatically,removed,from,system,during,uninstallation,Directory,list,directories,separated,added,path,variable,Level,specifies,whether,directory,should,added,path,variable,for,every,user,system,just,current,user,Location,specifies,whether,given,directory,should,prepended,beginning,path,variable,appended,end,Normalize,Paths,property,true,each,path,added,variable,normalized,appropriately,for,current,platform,before,added,makes,sure,that,any,path,that,relative,has,incorrect,directory,separators,made,legal,for,current,platform,Default,Yes,Separator,property,specifies,what,separator,use,between,paths,for,given,variable,Defaults,<%PathSeparator%>,Variable,property,specifies,variable,add,your,path,default,PATH,but,could,easily,something,like,CLASSPATH,add,Java,class,path,target,system,Directory,Path[$XTITELEND$][$XKEYS$]Add,Directory,Path[$XKEYSEND$]`;";
s[115] = "Add Environment Variable^AddEnvironmentVariable.html^This action is used to add a new environment variable to the target system.Supported Platforms...^Add Environment Variable^action,used,add,new,environment,variable,target,system,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Add,Uninstall,property,true,added,paths,automatically,removed,from,system,during,uninstallation,Level,specifies,whether,variable,should,added,for,every,user,system,just,current,user,Restore,Uninstall,Windows,only,property,tells,InstallJammer,remember,value,environment,variable,already,exists,then,restore,during,uninstall,only,valid,for,Windows,because,always,case,UNIX,systems,because,way,variables,added,Value,value,set,new,environment,variable,Variable,property,specifies,name,environment,variable,add,target,system,Environment,Variable[$XTITELEND$][$XKEYS$]Add,Environment,Variable[$XKEYSEND$]`;";
s[116] = "Delete Environment Variable^DeleteEnvironmentVariable.html^This action is used to delete an environment variable from the target system.Supported Platfor...^Delete Environment Variable^action,used,delete,environment,variable,from,target,system,Supported,Platforms,Windows,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Level,specifies,whether,variable,should,deleted,for,every,user,system,just,current,user,Variable,property,specifies,environment,variable,deleted,from,target,system,Environment,Variable[$XTITELEND$][$XKEYS$]Delete,Environment,Variable[$XKEYSEND$]`;";
s[117] = "Reboot or Shutdown System^RebootOrShutdownSystem.html^This action will reboot or shutdown the target system.  On some UNIX systems, this action cannot be ...^Reboot or Shutdown System^action,reboot,shutdown,target,system,some,UNIX,systems,action,cannot,performed,unless,user,root,Supported,Platforms,All,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Execute,Root,property,true,InstallJammer,prompt,user,for,root,password,they,not,already,root,Type,Whether,system,should,rebooted,shutdown,Shutdown,System[$XTITELEND$][$XKEYS$]Reboot,Shutdown,System[$XKEYSEND$]`;";
s[118] = "Register Package^RegisterPackage.html^This action will attempt to register a package with the given package manager on the target system. ...^Register Package^action,attempt,register,package,with,given,package,manager,target,system,action,almost,always,require,root,performed,user,not,already,root,action,attempt,execute,action,root,which,prompt,user,enter,root,password,install,package,information,Currently,supported,package,systems,DPKG,RPM,installer,attempt,build,dummy,package,target,system,using,standard,tools,then,install,Because,limitations,build,tools,action,does,not,register,files,your,installer,with,package,database,does,however,register,uninstaller,with,package,system,that,user,attempts,remove,package,through,system,call,uninstaller,actual,file,removal,InstallJammer,automatically,add,package,removed,from,package,database,during,uninstallation,package,not,being,removed,from,package,manager,itself,requires,root,access,InstallJammer,prompt,user,execute,removal,root,they,not,root,when,they,run,uninstall,Supported,Platforms,Linux,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,DPKG,Changelog,File,file,target,system,use,changelog,file,for,DPKG,database,file,specified,InstallJammer,create,dummy,file,satisfy,DPKG,file,does,not,have,extension,InstallJammer,gzip,file,per,DPKG,requirements,DPKG,Control,Script,script,that,used,control,script,when,DPKG,builds,dummy,package,default,values,information,build,standard,package,based,information,your,installer,Unless,you,familiar,with,building,DPKG,packages,not,recommended,that,you,change,any,values,Control,Script,can,lead,your,package,not,building,not,installing,correctly,DPKG,Copyright,File,file,target,system,use,copyright,file,for,DPKG,database,file,specified,InstallJammer,create,dummy,file,satisfy,DPKG,file,does,not,have,extension,InstallJammer,gzip,file,per,DPKG,requirements,DPKG,Debian,Changelog,File,file,target,system,use,Debian,changelog,file,for,DPKG,database,file,specified,InstallJammer,create,dummy,file,satisfy,DPKG,file,does,not,have,extension,InstallJammer,gzip,file,per,DPKG,requirements,DPKG,Pre,Install,Script,script,execute,before,installation,DPKG,database,Since,InstallJammer,doing,most,work,you,should,probably,leave,blank,unless,you,know,what,you,doing,DPKG,Pre,Uninstall,Script,script,execute,before,uninstallation,DPKG,database,default,script,standard,script,expected,for,all,DPKG,packages,you,should,probably,not,change,unless,you,know,what,you,doing,DPKG,Post,Install,Script,script,execute,after,installation,DPKG,database,default,script,standard,script,expected,for,all,DPKG,packages,you,should,probably,not,change,unless,you,know,what,you,doing,DPKG,Post,Uninstall,Script,script,execute,after,uninstallation,DPKG,database,InstallJammer,automatically,populates,script,with,script,call,uninstaller,Since,DPKG,database,doesn't,really,know,anything,about,files,installer,how,remove,want,DPKG,remove,its,package,then,call,uninstaller,Since,DPKG,attempts,remove,previously,installed,package,before,proceeding,with,new,install,script,checks,see,removal,being,run,from,another,installer,exits,Package,Name,name,package,use,when,storing,package,database,rest,information,stored,different,scripts,that,build,dummy,packages,Package,Databases,Specifies,which,package,database,should,registered,with,target,system,Defaults,all,which,means,both,RPM,DPKG,they,exist,system,RPM,Spec,Script,contents,script,stored,SPEC,file,build,dummy,RPM,from,default,values,information,build,standard,package,based,information,your,installer,Unless,you,familiar,with,building,RPM,packages,not,recommended,that,you,change,any,values,Spec,Script,can,lead,your,package,not,building,not,installing,correctly,Package[$XTITELEND$][$XKEYS$]Register,Package[$XKEYSEND$]`;";
s[119] = "Remove Directory from Path^RemoveDirectoryFromPath.html^This action is used to remove a directory from a path variable on the target system.Supported ...^Remove Directory from Path^action,used,remove,directory,from,path,variable,target,system,Supported,Platforms,Windows,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Directory,directory,removed,from,path,variable,Level,specifies,whether,directory,should,removed,from,path,variable,for,every,user,system,just,current,user,Separator,property,specifies,what,separator,use,between,paths,for,given,variable,Defaults,<%PathSeparator%>,Variable,property,specifies,variable,add,your,path,default,PATH,but,could,easily,something,like,CLASSPATH,add,Java,class,path,target,system,Directory,from,Path[$XTITELEND$][$XKEYS$]Remove,Directory,from,Path[$XKEYSEND$]`;";
s[120] = "Uninstall Leftover Files^UninstallLeftoverFiles.html^This action is just like Uninstall Selected Files except that it will forcefully try to remove any p...^Uninstall Leftover Files^action,just,like,Uninstall,Selected,Files,except,that,forcefully,try,remove,any,pieces,uninstall,that,could,not,removed,first,pass,means,deleting,directories,eventhough,they,not,empty,forcibly,trying,remove,file,that,could,not,deleted,first,time,any,errors,still,occur,while,executing,action,they,appended,<%Errors%>,virtual,text,<%ErrorsOccurred%>,virtual,text,set,true,Standard,Properties,See,Standard,Action,Properties,Leftover,Files[$XTITELEND$][$XKEYS$]Uninstall,Leftover,Files[$XKEYSEND$]`;";
s[121] = "Uninstall Selected Files^UninstallSelectedFiles.html^This is the main action of the uninstall process.  This action will attempt to uninstall everything ...^Uninstall Selected Files^main,action,uninstall,process,action,attempt,uninstall,everything,that,was,installed,target,system,during,installation,includes,all,files,directories,registry,entries,any,piece,cannot,removed,for,some,reason,error,appended,<%Errors%>,virtual,text,<%ErrorsOccurred%>,virtual,text,set,true,Standard,Properties,See,Standard,Action,Properties,Selected,Files[$XTITELEND$][$XKEYS$]Uninstall,Selected,Files[$XKEYSEND$]`;";
s[122] = "Disable Wow64 Redirection^DisableWow64Redirection.html^On 64 bit Windows Vista (and beyond?) systems, installers and setup programs have certain system dir...^Disable Wow64 Redirection^bit,Windows,Vista,beyond,systems,installers,setup,programs,have,certain,system,directories,automatically,redirected,bit,directory,hierarchy,action,disables,that,redirection,that,libraries,can,properly,installed,bit,directories,Disabling,redirection,continue,for,rest,installation,until,Revert,Wow64,Redirection,action,executed,but,redirection,only,applies,current,process,not,continue,once,your,installer,exits,Supported,Platforms,Windows,Standard,Properties,See,Standard,Action,Properties,Wow64,Redirection[$XTITELEND$][$XKEYS$]Disable,Wow64,Redirection[$XKEYSEND$]`;";
s[123] = "Revert Wow64 Redirection^RevertWow64Redirection.html^On 64 bit Windows Vista (and beyond?) systems, installers and setup programs have certain system dir...^Revert Wow64 Redirection^bit,Windows,Vista,beyond,systems,installers,setup,programs,have,certain,system,directories,automatically,redirected,bit,directory,hierarchy,action,reverts,any,previous,redirection,from,Disable,Wow64,Redirection,action,Supported,Platforms,Windows,Standard,Properties,See,Standard,Action,Properties,Wow64,Redirection[$XTITELEND$][$XKEYS$]Revert,Wow64,Redirection[$XKEYSEND$]`;";
s[124] = "Add Windows File Command^AddWindowsFileCommand.html^This action will add a new command to a file type on the target Windows system.  This means that a n...^Add Windows File Command^action,add,new,command,file,type,target,Windows,system,means,that,new,command,appear,right,click,menu,for,file,type,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Command,actual,command,execute,when,someone,clicks,menu,entry,for,command,Command,Name,name,command,added,Usually,something,like,Open,Edit,Print,File,Type,file,type,add,command,target,system,Menu,Name,specified,sets,title,display,menu,for,command,property,empty,Command,Name,used,menu,title,Windows,File,Command[$XTITELEND$][$XKEYS$]Add,Windows,File,Command[$XKEYSEND$]`;";
s[125] = "Add Windows File Extension^AddWindowsFileExtension.html^This action adds a new file extension to the Windows registry and attaches it to a given file type....^Add Windows File Extension^action,adds,new,file,extension,Windows,registry,attaches,given,file,type,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,File,Extension,file,extension,add,should,include,would,something,like,tcl,mpi,File,Type,file,type,add,command,target,system,Windows,File,Extension[$XTITELEND$][$XKEYS$]Add,Windows,File,Extension[$XKEYSEND$]`;";
s[126] = "Add Windows File Type^AddWindowsFileType.html^This action adds a new File Type to the Windows registry of the target system.Standard Propert...^Add Windows File Type^action,adds,new,File,Type,Windows,registry,target,system,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,File,Type,name,file,type,added,Icon,Path,property,specifies,file,use,for,icon,for,all,files,file,type,can,ico,exe,any,other,file,containing,icon,information,Icon,Path,Index,index,into,file,that,Windows,uses,when,looking,for,icon,Show,File,Extensions,Tells,Windows,whether,display,file,extensions,for,all,files,file,type,not,specified,files,type,behave,according,system,folder,defaults,Title,title,file,type,title,displayed,Type,column,Windows,Explorer,for,all,files,matching,file,type,Windows,File,Type[$XTITELEND$][$XKEYS$]Add,Windows,File,Type[$XKEYSEND$]`;";
s[127] = "Add Windows Registry Key^AddWindowsRegistryKey.html^his action adds a new registry key and/or value to the Windows registry on the target system.B...^Add Windows Registry Key^action,adds,new,registry,key,value,Windows,registry,target,system,default,action,add,new,registry,key,uninstall,removed,along,with,files,directories,when,application,uninstalled,can,prevented,setting,Add,Uninstall,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Add,Uninstall,property,tells,InstallJammer,whether,not,add,registry,key,list,things,uninstalled,set,key,not,uninstalled,with,rest,application,Data,Type,property,specifies,type,data,that,stored,registry,key,Key,name,key,create,registry,Name,name,value,add,registry,key,property,empty,value,set,default,value,for,registry,key,Value,actual,value,data,stored,value,being,added,registry,key,Restore,Uninstall,property,true,InstallJammer,check,registry,key,already,exists,system,before,installing,registry,key,value,already,exists,value,remembered,then,restored,during,uninstallation,Root,Key,root,key,registry,add,key,Windows,Registry,Key[$XTITELEND$][$XKEYS$]Add,Windows,Registry,Key[$XKEYSEND$]`;";
s[128] = "Add Windows Uninstall Entry^AddWindowsUninstallEntry.html^This action will add a new entry to the Windows Add or Remove Programs registry.  This can be access...^Add Windows Uninstall Entry^action,add,new,entry,Windows,Add,Remove,Programs,registry,can,accessed,from,Control,Panel,usual,way,for,Windows,users,remove,installed,applications,from,system,InstallJammer,adds,one,these,actions,new,install,default,that,Windows,users,have,way,remove,your,application,way,that,already,familiar,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Comments,property,stores,comments,for,entry,Windows,registry,Contact,property,specifies,contact,information,displayed,user,Display,Name,property,tells,Windows,what,display,Add,Remove,Programs,window,for,applicaiton,Display,Icon,property,specifies,file,use,for,icon,for,entry,can,ico,exe,any,other,file,containing,icon,information,Display,Version,property,tells,Windows,what,version,display,for,program,Help,Link,URL,homepage,your,application,Help,Telephone,Your,contact,telephone,number,for,support,Install,Date,date,installation,format,%Y%m%d,Install,Location,installation,directory,Install,Source,directory,installer,was,originally,run,from,Publisher,name,company,person,publishing,application,Quiet,Uninstall,String,command,execute,quietly,uninstall,your,application,Readme,location,README,file,for,your,application,Registry,Key,Name,key,use,uninstall,registry,using,<%ApplicationID%>,ensures,that,subsequent,installs,your,application,always,use,same,uninstall,registry,entry,instead,adding,new,one,for,every,version,your,software,Uninstall,String,command,execute,uninstall,your,application,URL,Info,About,URL,that,points,information,about,your,application,URL,Update,Info,URL,that,points,information,about,updating,your,application,Windows,Uninstall,Entry[$XTITELEND$][$XKEYS$]Add,Windows,Uninstall,Entry[$XKEYSEND$]`;";
s[129] = "Import Windows Registry File^ImportWindowsRegistryFile.html^This action will import a Windows registry (.reg) file into the Windows registry on the target syste...^Import Windows Registry File^action,import,Windows,registry,reg,file,into,Windows,registry,target,system,action,simply,calls,regedit,with,registry,file,import,registry,file,must,standard,format,Supported,Platforms,Windows,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Prompt,User,property,true,Windows,prompt,user,ask,they,want,import,file,before,beginning,user,can,opt,not,import,registry,file,Registry,File,name,file,target,system,imported,Windows,Registry,File[$XTITELEND$][$XKEYS$]Import,Windows,Registry,File[$XKEYSEND$]`;";
s[130] = "Register Windows Library^RegisterWindowsLibrary.html^his action will register a DLL or other library with the Windows registry.This action simply b...^Register Windows Library^action,register,DLL,other,library,with,Windows,registry,action,simply,builds,arguments,then,calls,regsvr32,exe,that,standard,Windows,systems,Supported,Platforms,Windows,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Call,DLL,Install,property,true,DLLInstall,function,called,for,given,library,when,installed,Call,DLL,Register,Server,property,true,DLLRegisterServer,function,called,for,given,library,when,registered,property,false,then,Call,DLL,Install,must,true,Library,File,path,library,file,register,Windows,Library[$XTITELEND$][$XKEYS$]Register,Windows,Library[$XKEYSEND$]`;";
s[131] = "Remove Windows Registry Key^RemoveWindowsRegistryKey.html^his action will remove a registry key or value from the target system.You do not need to remov...^Remove Windows Registry Key^action,remove,registry,key,value,from,target,system,You,not,need,remove,during,uninstall,any,registry,keys,values,added,during,installation,InstallJammer,automatically,registers,any,keys,added,its,own,installers,adds,list,uninstalled,Supported,Platforms,Windows,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Key,name,key,remove,from,registry,Value,value,removed,from,key,not,null,key,itself,not,removed,only,value,removed,from,key,Root,Key,root,key,registry,Key,already,contains,root,key,property,ignored,Windows,Registry,Key[$XTITELEND$][$XKEYS$]Remove,Windows,Registry,Key[$XKEYSEND$]`;";
s[132] = "Unregister Windows Library^UnregisterWindowsLibrary.html^his action will unregister a DLL or other library with the Windows registry.This action simply...^Unregister Windows Library^action,unregister,DLL,other,library,with,Windows,registry,action,simply,builds,arguments,then,calls,regsvr32,exe,that,standard,Windows,systems,Supported,Platforms,Windows,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Call,DLL,Uninstall,property,true,DLLUninstall,function,called,for,given,library,when,installed,Call,DLL,Unregister,Server,property,true,DLLUnregisterServer,function,called,for,given,library,when,registered,property,false,then,Call,DLL,Uninstall,must,true,Library,File,path,library,file,unregister,Windows,Library[$XTITELEND$][$XKEYS$]Unregister,Windows,Library[$XKEYSEND$]`;";
s[133] = "Continue Windows Service^ContinueWindowsService.html^This action will continue a Windows service that is in a paused state.Standard Properties  S...^Continue Windows Service^action,continue,Windows,service,that,paused,state,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Database,Specifies,service,control,database,operated,default,active,service,control,database,target,system,Service,Name,name,service,perform,action,can,internal,display,name,service,display,name,given,automatically,translated,internal,service,name,for,action,System,Specifies,name,system,which,command,should,invoked,default,local,system,Wait,not,null,specifies,number,milliseconds,wait,for,action,complete,InstallJammer,wait,until,action,completes,for,specified,number,milliseconds,whichever,comes,first,Windows,Service[$XTITELEND$][$XKEYS$]Continue,Windows,Service[$XKEYSEND$]`;";
s[134] = "Create Windows Service^CreateWindowsService.html^This action will continue a Windows service that is in a paused state.Standard Properties  S...^Create Windows Service^action,continue,Windows,service,that,paused,state,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Account,Specifies,account,name,user,account,under,which,service,should,run,account,name,takes,form,account,local,account,account,name,may,specified,username,option,not,specified,service,run,under,LocalSystem,account,When,Service,Type,Kernel,Driver,File,System,Driver,account,name,should,name,driver,object,that,system,uses,load,driver,Command,system,command,executed,start,service,Database,Specifies,service,control,database,operated,default,active,service,control,database,target,system,Dependencies,Specifies,services,service,load,order,groups,that,required,service,that,must,start,before,service,property,contains,list,service,names,load,order,groups,load,order,group,name,must,prefixed,with,character,indicate,that,group,name,not,service,Description,Specifies,long,description,for,service,when,viewed,within,services,console,Display,Name,Specifies,user,visible,name,for,service,name,that,shown,net,start,command,SCM,control,panel,applet,Error,Control,option,specifies,how,errors,during,service,start,handled,Critical,error,message,logged,Windows,event,log,possible,last,known,good,configuration,active,system,startup,aborted,Otherwise,system,restarted,with,last,known,good,configuration,Ignore,error,message,logged,Windows,event,log,system,startup,continue,Normal,error,message,logged,Windows,event,log,popup,displayed,user,system,startup,continue,default,Severe,error,message,logged,Windows,event,log,system,startup,continue,only,last,known,good,configuration,active,Otherwise,system,restarted,with,last,known,good,configuration,Interactive,option,specifies,whether,service,should,allowed,interact,with,desktop,only,valid,when,Service,Type,specified,Own,Process,Shared,Process,Account,option,must,not,used,with,option,since,interactive,services,must,run,under,LocalSystem,account,Load,Order,Group,Specifies,group,name,service,load,order,group,which,service,belongs,option,not,specified,service,assumed,not,belong,any,load,order,group,Password,Specifies,password,corresponding,user,account,specified,Account,option,option,ignored,Account,option,not,specified,Service,Name,name,service,perform,action,can,internal,display,name,service,display,name,given,automatically,translated,internal,service,name,for,action,Service,Type,property,specifies,type,service,create,Own,Process,Service,that,runs,its,own,process,corresponds,SERVICE_WIN32_OWN_PROCESS,Windows,SDK,documentation,default,option,not,specified,Shared,Process,Service,that,runs,inside,process,shared,with,other,services,corresponds,SERVICE_WIN32_SHARED_PROCESS,Windows,SDK,documentation,File,System,Driver,File,system,driver,corresponds,SERVICE_FILE_SYSTEM_DRIVER,Windows,SDK,documentation,Kernel,Driver,Kernel,driver,corresponds,SERVICE_KERNEL_DRIVER,Windows,SDK,documentation,Start,Type,property,specifies,how,service,started,Auto,Start,service,should,automatically,started,service,control,manager,during,system,startup,default,option,not,specified,Boot,Start,service,should,automatically,started,system,loader,during,system,boot,only,valid,when,Service,Type,specified,Kernel,Driver,File,System,Driver,Demand,Start,service,should,started,system,upon,receiving,explicit,program,request,Disabled,service,disabled,cannot,started,even,program,request,System,Start,service,driver,that,started,operating,system,IoInitSystem,function,during,system,initialization,only,valid,when,Service,Type,specified,Kernal,Driver,File,System,Driver,System,Specifies,name,system,which,command,should,invoked,default,local,system,Windows,Service[$XTITELEND$][$XKEYS$]Create,Windows,Service[$XKEYSEND$]`;";
s[135] = "Delete Windows Service^DeleteWindowsService.html^This action will delete a Windows service from the target system.Standard Properties  See St...^Delete Windows Service^action,delete,Windows,service,from,target,system,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Database,Specifies,service,control,database,operated,default,active,service,control,database,target,system,Service,Name,name,service,perform,action,can,internal,display,name,service,display,name,given,automatically,translated,internal,service,name,for,action,System,Specifies,name,system,which,command,should,invoked,default,local,system,Windows,Service[$XTITELEND$][$XKEYS$]Delete,Windows,Service[$XKEYSEND$]`;";
s[136] = "Pause Windows Service^PauseWindowsService.html^This action will pause a Windows service.Standard Properties  See Standard Action Properties...^Pause Windows Service^action,pause,Windows,service,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Database,Specifies,service,control,database,operated,default,active,service,control,database,target,system,Service,Name,name,service,perform,action,can,internal,display,name,service,display,name,given,automatically,translated,internal,service,name,for,action,System,Specifies,name,system,which,command,should,invoked,default,local,system,Wait,not,null,specifies,number,milliseconds,wait,for,action,complete,InstallJammer,wait,until,action,completes,for,specified,number,milliseconds,whichever,comes,first,Windows,Service[$XTITELEND$][$XKEYS$]Pause,Windows,Service[$XKEYSEND$]`;";
s[137] = "Start Windows Service^StartWindowsService.html^This action will start a Windows service.Standard Properties  See Standard Action Properties...^^action,start,Windows,service,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Database,Specifies,service,control,database,operated,default,active,service,control,database,target,system,Service,Name,name,service,perform,action,can,internal,display,name,service,display,name,given,automatically,translated,internal,service,name,for,action,System,Specifies,name,system,which,command,should,invoked,default,local,system,Wait,not,null,specifies,number,milliseconds,wait,for,action,complete,InstallJammer,wait,until,action,completes,for,specified,number,milliseconds,whichever,comes,first,Windows,Service[$XTITELEND$][$XKEYS$]Start,Windows,Service[$XKEYSEND$]`;";
s[138] = "Stop Windows Service^StopWindowsService.html^This action will stop a Windows service.Standard Properties  See Standard Action Properties....^Stop Windows Service^action,stop,Windows,service,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Database,Specifies,service,control,database,operated,default,active,service,control,database,target,system,Service,Name,name,service,perform,action,can,internal,display,name,service,display,name,given,automatically,translated,internal,service,name,for,action,System,Specifies,name,system,which,command,should,invoked,default,local,system,Wait,not,null,specifies,number,milliseconds,wait,for,action,complete,InstallJammer,wait,until,action,completes,for,specified,number,milliseconds,whichever,comes,first,Windows,Service[$XTITELEND$][$XKEYS$]Stop,Windows,Service[$XKEYSEND$]`;";
s[139] = "Add Pane to Order^AddPaneToOrder.html^This action will take the given pane and add it to the wizard's back order at the given index.  This...^Add Pane to Order^action,take,given,pane,add,wizard's,back,order,given,index,useful,for,controlling,how,wizad,behaves,tricky,installs,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Index,property,specifies,where,current,back,order,wizard,pane,should,added,can,number,word,end,another,pane,index,number,means,that,given,pane,should,inserted,just,before,that,index,order,index,word,end,means,append,pane,end,order,index,another,pane,means,that,given,pane,should,inserted,just,before,that,pane,current,order,Pane,alias,pane,added,back,order,wizard,Pane,Order[$XTITELEND$][$XKEYS$]Add,Pane,Order[$XKEYSEND$]`;";
s[140] = "Add Widget^AddWidget.html^This action will add a new widget to an install pane.  Widgets are any type of control that is drawn...^Add Widget^action,add,new,widget,install,pane,Widgets,any,type,control,that,drawn,pane,which,buttons,checkbuttons,labels,radiobuttons,more,Setting,Text,any,widget,type,other,than,label,cause,label,drawn,combination,with,specified,widget,easiest,way,add,label,with,widget,rather,than,having,add,separate,label,widget,Supported,Platforms,All,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Action,property,specifies,action,that,should,executed,user,clicks,button,modifies,value,checkbutton,radiobutton,action,also,applies,entry,browse,entry,password,entry,widgets,when,Validate,Entry,property,set,Background,background,color,new,widget,most,common,system,which,main,system,color,for,background,windows,white,Browse,Type,widget,browse,entry,property,specifies,what,you,browsing,for,directory,use,choose,directory,dialog,open,file,use,file,dialog,that,expecting,file,that,already,exists,save,file,use,file,dialog,that,tell,user,file,overwritten,already,exists,Checked,When,adding,radiobutton,checkbutton,property,tells,InstallJammer,that,button,should,checked,default,when,displayed,property,left,blank,status,button,depend,virtual,text,property,attached,case,checkbutton,virtual,text,property,true,checkbutton,checked,case,radiobutton,radiobutton,whose,value,matches,current,value,virtual,text,checked,Editable,widget,type,combobox,property,specifies,whether,value,entry,combobox,should,editable,not,value,not,editable,user,may,only,choose,from,given,list,values,combobox,editable,user,can,either,choose,from,given,values,type,own,value,File,Types,widget,type,browse,entry,for,choosing,files,property,tells,file,chooser,popup,what,file,types,allow,File,Types,property,must,contain,list,pairs,containing,description,file,type,list,extensions,include,with,file,type,Source,Files,cpp,hpp,Text,Files,txt,All,Files,Foreground,foreground,color,new,widget,most,common,system,which,main,system,color,for,foreground,text,windows,black,Height,height,widget,Usually,option,should,left,blank,InstallJammer,make,widget,tall,needs,Label,Side,any,widget,that,not,label,setting,Text,property,cause,label,drawn,with,corresponding,widget,property,tells,InstallJammer,where,you,want,label,appear,relation,widget,choices,top,left,Label,Width,property,specifies,width,text,label,when,present,next,another,widget,Using,property,with,your,label,left,side,you,can,make,all,your,labels,line,evenly,giving,all,same,width,Off,Value,value,virtual,text,set,when,checkbutton,off,only,valid,for,checkbuttons,Value,value,virtual,text,set,when,checkbutton,only,valid,for,checkbuttons,Text,widget,type,label,text,property,specifies,what,should,displayed,label,widget,not,label,setting,text,property,any,string,cause,label,drawn,with,given,widget,Type,type,widget,add,list,currently,browse,entry,button,checkbutton,combobox,entry,label,label,frame,password,entry,radiobutton,text,Validate,Entry,property,tells,InstallJammer,when,validate,contents,entry,widget,when,type,widget,added,entry,action,property,not,empty,following,values,acceptable,either,single,value,list,values,separated,Create,Focus,FocusIn,FocusOut,Key,Create,means,that,value,validated,when,widget,created,Focus,FocusIn,FocusOut,mean,entry,validated,when,focus,entry,changes,Key,means,entry,validated,anytime,key,pressed,inside,entry,Value,For,radiobutton,value,stored,virtual,text,when,radiobutton,selected,Please,read,section,titled,Boolean,Values,Virtual,Text,What,Virtual,Text,for,information,using,boolean,type,values,value,for,radiobutton,Setting,value,entry,browse,entry,set,default,value,virtual,text,given,value,which,make,value,appear,entry,box,Values,widget,type,combobox,property,specifies,list,values,display,dropdown,menu,combobox,must,valid,list,with,each,item,quoted,Item,Item,Item,Item,Virtual,Text,virtual,text,variable,store,result,Radiobuttons,grouped,together,all,sharing,same,virtual,text,variable,selected,radiobutton,set,value,virtual,text,Width,width,widget,option,left,blank,InstallJammer,make,widget,wide,needs,coordinate,pane,place,widget,coordinate,pane,place,widget,Widget[$XTITELEND$][$XKEYS$]Add,Widget[$XKEYSEND$]`;";
s[141] = "Append Text to Widget^AppendTextToWidget.html^This action will append text to a text widget in the current pane displayed.Supported Platforms...^Append Text to Widget^action,append,text,text,widget,current,pane,displayed,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Auto,Scroll,property,true,text,widget,automatically,scroll,bottom,after,text,appended,Clear,Widget,property,true,text,widget,cleared,any,text,before,adding,new,text,Widget,name,text,widget,append,Text,Widget[$XTITELEND$][$XKEYS$]Append,Text,Widget[$XKEYSEND$]`;";
s[142] = "Create Install Panes^CreateInstallPanes.html^This action will create all of the install panes for the installer.  This is usually done at the fro...^Create Install Panes^action,create,all,install,panes,for,installer,usually,done,front,install,create,all,panes,once,that,they,display,more,quickly,user,moves,through,panes,not,created,front,they,created,each,one,displayed,for,first,time,action,placed,pane,with,progress,bar,increment,progress,bar,each,pane,created,Standard,Properties,See,Standard,Action,Properties,Install,Panes[$XTITELEND$][$XKEYS$]Create,Install,Panes[$XKEYSEND$]`;";
s[143] = "Destroy Widget^DestroyWidget.html^This action will permanently destroy a widget.  A widget can either be a single widget on a pane cre...^Destroy Widget^action,permanently,destroy,widget,widget,can,either,single,widget,pane,created,with,Add,Widget,action,can,specify,message,panel,another,pane,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Widget,list,Widget,IDs,Aliases,separated,widget,can,also,specified,<PANE>,<WIDGET>,where,<PANE>,Alias,specific,pane,<WIDGET>,Alias,widget,that,pane,Widget[$XTITELEND$][$XKEYS$]Destroy,Widget[$XKEYSEND$]`;";
s[144] = "Focus On Widget^FocusOnWidget.html^This action will draw the keyboard focus to a widget.Standard Properties  See Standard Actio...^Focus On Widget^action,draw,keyboard,focus,widget,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Widget,alias,widget,destroyed,Widget[$XTITELEND$][$XKEYS$]Focus,Widget[$XKEYSEND$]`;";
s[145] = "Modify Widget^ModifyWidget.html^This action will modify the text or state of a given widget or list of widgets on the current pane....^Modify Widget^action,modify,text,state,given,widget,list,widgets,current,pane,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,State,state,modified,widget,should,Normal,means,that,widget,active,user,can,interact,with,Disabled,means,that,widget,inactive,user,cannot,manipulate,Disabled,widgets,usually,shown,greyed,out,reflect,that,they,disabled,Hidden,means,that,widget,should,removed,from,pane,entirely,hidden,widget,can,restored,modifying,its,state,back,normal,Readonly,state,that,can,applied,entry,text,widgets,means,that,widget,appear,normal,but,user,not,able,enter,any,data,Text,text,modified,widget,should,display,modify,all,listed,widgets,change,text,given,value,left,blank,text,not,modified,Widget,property,specifies,single,widget,current,pane,list,widgets,separated,semicolon,Widget[$XTITELEND$][$XKEYS$]Modify,Widget[$XKEYSEND$]`;";
s[146] = "Move Forward^MoveForward.html^This action causes InstallJammer to move forward to the next pane in the install.  If there are no m...^Move Forward^action,causes,InstallJammer,move,forward,next,pane,install,more,panes,displayed,cause,InstallJammer,exit,with,Finish,condition,Standard,Properties,See,Standard,Action,Properties,Forward[$XTITELEND$][$XKEYS$]Move,Forward[$XKEYSEND$]`;";
s[147] = "Move to Pane^MoveToPane.html^This action causes InstallJammer to jump forward or backward through the installer to the specified ...^Move to Pane^action,causes,InstallJammer,jump,forward,backward,through,installer,specified,pane,When,action,moves,given,pane,that,pane,automatically,added,backwards,order,wizard,that,user,see,they,back,through,wizard,pane,being,moved,current,pane,actions,pane,executed,from,start,effectively,reloading,current,pane,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Pane,alias,pane,jump,Pane[$XTITELEND$][$XKEYS$]Move,Pane[$XKEYSEND$]`;";
s[148] = "Populate Components^PopulateComponents.html^When placed on a Choose Components pane, this action will populate the tree with a list of component...^Populate Components^When,placed,Choose,Components,pane,action,populate,tree,with,list,components,for,currently,selected,setup,type,Anytime,setup,type,changes,like,user,moves,back,tree,cleared,populated,Supported,Platforms,All,Standard,Properties,See,Standard,Action,Properties,Components[$XTITELEND$][$XKEYS$]Populate,Components[$XKEYSEND$]`;";
s[149] = "Populate Setup Types^PopulateSetupTypes.html^When placed on a Setup Type pane, this action will populate the setup type list with the setup types...^Populate Setup Types^When,placed,Setup,Type,pane,action,populate,setup,type,list,with,setup,types,included,current,installer,Supported,Platforms,All,Standard,Properties,See,Standard,Action,Properties,Setup,Types[$XTITELEND$][$XKEYS$]Populate,Setup,Types[$XKEYSEND$]`;";
s[150] = "Remove Pane from Order^RemovePaneFromOrder.html^This action will take the given pane and remove it from the wizard's back order.  This means that wh...^Remove Pane from Order^action,take,given,pane,remove,from,wizard's,back,order,means,that,when,user,moves,back,with,Back,button,pane,longer,shown,useful,for,controlling,how,wizad,behaves,tricky,installs,Supported,Platforms,All,Platforms,Standard,Properties,See,Standard,Action,Properties,Advanced,Properties,Pane,alias,pane,added,back,order,wizard,Pane,from,Order[$XTITELEND$][$XKEYS$]Remove,Pane,from,Order[$XKEYSEND$]`;";
s[151] = "What are Conditions?^WhatAreConditions.html^Conditions are a way to tell InstallJammer how and when it should do certain things within an instal...^What are Conditions?^Conditions,way,tell,InstallJammer,how,when,should,certain,things,within,installer,Most,objects,InstallJammer,can,have,conditions,attached,that,control,whether,not,action,taken,that,object,When,conditions,checked,they,checked,with,explicit,which,means,that,first,false,condition,that,found,stop,rest,not,checked,Script,Condition,can,used,cases,where,more,complicated,conditions,needed,Conditions,Conditions`;";
s[152] = "Standard Condition Properties^ConditionStandardProperties.html^IDA unique identifier for this object.  This ID is generated when the object is created and does n...^Standard Condition Properties^unique,identifier,for,object,generated,when,object,created,does,not,change,throughout,life,object,Component,property,tells,you,what,condition,was,originally,used,create,object,Active,tells,InstallJammer,whether,object,active,not,inactive,object,not,packaged,when,building,installer,Alias,alias,alias,which,call,object,Any,object,InstallJammer,that,has,can,also,have,alias,makes,easier,remember,objects,alias,instead,object,For,example,Install,Actions,group,that,created,for,new,project,aliased,called,Install,Actions,make,easier,call,from,other,actions,Check,Condition,property,tells,InstallJammer,when,check,condition,property,only,valid,for,panes,actions,does,not,appear,for,conditions,applied,other,object,types,possible,choices,different,depending,you,currently,modifying,pane,action,When,Check,Condition,property,Action,set,Before,Next,Action,Executed,cause,current,action,executed,again,condition,fails,mostly,useful,during,Console,installations,where,you,want,action,execute,again,display,its,message,prompt,user,for,input,user,cannot,continue,next,action,until,condition,satisfied,Comment,Comments,sometimes,provided,InstallJammer,tell,you,what,object,doing,but,they,usually,set,someone,building,project,Comments,not,used,InstallJammer,for,anything,can,contain,any,text,you,want,Data,property,used,hold,user,specific,data,Just,like,comments,data,not,used,InstallJammer,safe,for,you,store,anything,you,want,into,can,helpful,for,storing,other,bits,relevant,data,with,object,system,for,use,other,objects,actions,conditions,Failure,Focus,widget,move,focus,condition,fails,Failure,Message,not,empty,message,displayed,then,focus,moved,Failure,Focus,widget,message,displayed,focus,simply,move,Failure,Focus,widget,Failure,Message,message,display,user,condition,checked,fails,property,left,blank,message,displayed,user,Condition,Properties[$XTITELEND$][$XKEYS$]Condition,Standard,Properties[$XKEYSEND$]`;";
s[153] = "File Exists Condition^FileExistsCondition.html^This condition checks to see if a file exists or does not exist on the target system.Standard ...^File Exists Condition^condition,checks,see,file,exists,does,not,exist,target,system,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Filename,name,file,target,system,Operator,exists,True,file,does,exist,does,not,exists,True,file,does,not,exist,Exists,Condition[$XTITELEND$][$XKEYS$]File,Exists,Condition[$XKEYSEND$]`;";
s[154] = "File Name Test Condition^FileNameTestCondition.html^This condition checks a filename to see if it contains any invalid characters and determines if the ...^File Name Test Condition^condition,checks,filename,see,contains,any,invalid,characters,determines,filename,legal,name,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Filename,name,file,target,system,Operator,name,valid,True,filename,legal,name,name,not,valid,True,filename,not,legal,name,path,valid,True,each,directory,filename,path,legal,name,path,not,valid,True,any,directory,filename,path,not,legal,name,Name,Test,Condition[$XTITELEND$][$XKEYS$]File,Name,Test,Condition[$XKEYSEND$]`;";
s[155] = "File Permission Condition^FilePermissionCondition.html^This condition checks the permissions of a file on the target system.Standard Properties  Se...^File Permission Condition^condition,checks,permissions,file,target,system,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Filename,name,file,target,system,Permission,can,create,True,file,directory,can,created,target,system,cannot,create,True,file,directory,cannot,created,target,system,readable,True,file,exists,readable,not,readable,True,file,does,not,exist,not,readable,writable,True,file,exists,writable,not,writable,True,file,does,not,exist,not,writable,Permission,Condition[$XTITELEND$][$XKEYS$]File,Permission,Condition[$XKEYSEND$]`;";
s[156] = "Command Line Test Condition^CommandLineTestCondition.html^This condition can check values passed by the user on the command lineStandard Properties  S...^Command Line Test Condition^condition,can,check,values,passed,user,command,line,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Operator,exists,True,command,line,option,exists,does,not,exist,True,command,line,option,does,not,exist,was,passed,command,line,True,option,was,passed,command,line,was,not,passed,command,line,True,option,was,not,passed,command,line,Option,name,option,test,Note,that,any,leading,characters,removed,before,checking,Line,Test,Condition[$XTITELEND$][$XKEYS$]Command,Line,Test,Condition[$XKEYSEND$]`;";
s[157] = "Execute Script Condition^ExecuteScriptCondition.html^This condition is a Tcl script that must return true if the condition passes or false if the conditi...^Execute Script Condition^condition,Tcl,script,that,must,return,true,condition,passes,false,condition,does,not,pass,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Script,Tcl,script,evaluate,All,virtual,text,substituted,when,evaluating,script,Your,script,should,always,end,with,return,command,that,returns,either,true,false,Anything,that,returned,that,looks,true,true,Anything,that,does,not,look,true,including,empty,string,other,text,considered,false,cause,condition,return,false,Example,following,script,example,that,returns,true,running,patch,installer,false,{[string,true,<%RunningInstaller%>],true,<%UpgradeInstall%>]},return,return,Note,that,script,always,returns,true,false,answer,safest,way,ensure,that,your,condition,always,return,something,valid,installer,Script,Condition[$XTITELEND$][$XKEYS$]Execute,Script,Condition[$XKEYSEND$]`;";
s[158] = "Object Test Condition^ObjectIsActiveCondition.html^This condition checks to see if an object in the (un)install is currently active.Standard Prop...^Object Test Condition^condition,checks,see,object,install,currently,active,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Object,alias,object,you,checking,Operator,exists,True,object,exists,does,not,exist,True,object,does,not,exist,active,True,object,active,not,active,True,object,inactive,Test,Condition[$XTITELEND$][$XKEYS$]Object,Active,Condition[$XKEYSEND$]`;";
s[159] = "Script Condition^ScriptCondition.html^This condition is a Tcl script that is substituted and then evaluated by Tcl's expression parser.  T...^Script Condition^condition,Tcl,script,that,substituted,then,evaluated,Tcl's,expression,parser,not,condition,that,used,for,full,scripts,used,for,combination,expressions,that,combined,together,use,actual,Tcl,script,condition,use,Execute,Script,Condition,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Script,Tcl,expression,evaluate,entire,expression,substituted,for,virtual,text,before,being,evaluated,Example,following,example,valid,Tcl,true,<%RunningInstaller%>],true,<%UpgradeInstall%>],Note,that,expression,not,full,Tcl,script,expression,multiple,commands,that,strung,together,using,expression,operators,like,following,not,valid,set,test1,true,<%RunningInstaller%>],set,test2,true,<%UpgradeInstall%>],return,{$test1,$test2}],full,Tcl,script,evaluated,not,expression,type,script,can,used,Execute,Script,Condition,but,not,Script,Condition,Condition[$XTITELEND$][$XKEYS$]Script,Condition[$XKEYSEND$]`;";
s[160] = "Virtual Text Test Condition^VirtualTextTestCondition.html^This condition checks to see if a virtual text variable exists or not.Standard Properties  S...^Virtual Text Test Condition^condition,checks,see,virtual,text,variable,exists,not,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Language,language,virtual,text,you,checking,None,means,check,virtual,text,without,language,Operator,exists,True,virtual,text,exists,does,not,exist,True,virtual,text,does,not,exist,was,set,from,command,line,True,virtual,text,was,set,modified,result,option,passed,command,line,Virtual,Text,virtual,text,without,check,Text,Test,Condition[$XTITELEND$][$XKEYS$]Virtual,Text,Exists,Condition[$XKEYSEND$]`;";
s[161] = "Platform Condition^PlatformCondition.html^This condition checks to see if a file exists or does not exist on the target system.Standard ...^Platform Condition^condition,checks,see,file,exists,does,not,exist,target,system,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Operator,True,platform,current,install,platform,not,True,platform,not,current,install,platform,matches,True,platform,matches,given,wildcard,pattern,Linux*,would,match,all,Linux,platforms,does,not,match,True,platform,does,not,match,given,wildcard,pattern,Platform,name,platform,pattern,match,Condition[$XTITELEND$][$XKEYS$]Platform,Condition[$XKEYSEND$]`;";
s[162] = "String Equal Condition^StringEqualCondition.html^This condition checks to see if two given strings equal each other.  Each string is substituted for ...^String Equal Condition^condition,checks,see,two,given,strings,equal,each,other,Each,string,substituted,for,virtual,text,before,comparison,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Operator,equals,True,two,strings,equal,each,other,does,not,equal,True,two,strings,not,equal,each,other,String,first,string,compare,String,second,string,compare,Equal,Condition[$XTITELEND$][$XKEYS$]String,Equal,Condition[$XKEYSEND$]`;";
s[163] = "String Is Condition^StringIsCondition.html^This condition checks the type of a given string to see if it is or is not of the correct type....^String Is Condition^condition,checks,type,given,string,see,not,correct,type,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Operator,true,True,sting,true,true,yes,false,True,string,false,false,off,empty,True,string,empty,meaning,contains,real,data,not,empty,True,string,has,any,data,String,string,check,value,string,substituted,for,virtual,text,before,comparison,Condition[$XTITELEND$][$XKEYS$]String,Condition[$XKEYSEND$]`;";
s[164] = "String Match Condition^StringMatchCondition.html^This condition checks to see if a given string matches a given pattern using standard glob-style mat...^String Match Condition^condition,checks,see,given,string,matches,given,pattern,using,standard,glob,style,matching,Each,string,substituted,for,virtual,text,before,comparison,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Operator,matches,True,string,matches,pattern,does,not,match,True,string,does,not,match,pattern,Pattern,pattern,match,string,against,pattern,argument,may,contain,any,following,special,Matches,any,single,character,Matches,any,sequence,zero,more,characters,Matches,any,single,character,chars,chars,contains,sequence,form,then,any,character,between,inclusive,match,Matches,character,Matches,any,strings,etc,String,string,match,against,pattern,Match,Condition[$XTITELEND$][$XKEYS$]String,Match,Condition[$XKEYSEND$]`;";
s[165] = "Env Variable Test Condition^EnvironmentVariableTestCondition.html^This condition checks to see if an environment variable exists or not.Standard Properties  S...^Env Variable Test Condition^condition,checks,see,environment,variable,exists,not,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Operator,exists,True,virtual,text,exists,does,not,exist,True,virtual,text,does,not,exist,Variable,name,environment,variable,check,Variable,Test,Condition[$XTITELEND$][$XKEYS$]Environment,Variable,Test,Condition[$XKEYSEND$]`;";
s[166] = "Package Test Condition^PackageTestCondition.html^This condition checks to see if a package is installed in the target system's default package manage...^Package Test Condition^condition,checks,see,package,installed,target,system's,default,package,manager,condition,determine,what,default,package,manager,for,target,system,then,attempt,determine,given,package,installed,querying,package,manager,Currently,supported,package,systems,DPKG,RPM,RPM,use,'rpm,$package',DPKG,use,'dpkg,$package',then,check,exit,code,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Operator,installed,True,package,installed,not,installed,True,package,not,installed,Package,name,package,check,Test,Condition[$XTITELEND$][$XKEYS$]Package,Test,Condition[$XKEYSEND$]`;";
s[167] = "Port Test Condition^PortTestCondition.html^This condition checks to see if a given port number on the target system is currently bound and in u...^Port Test Condition^condition,checks,see,given,port,number,target,system,currently,bound,use,does,not,make,any,checks,see,what,running,that,port,only,that,port,bound,answering,not,action,attempt,open,socket,127,local,host,given,port,see,anything,answers,connection,attempt,then,closes,port,without,ever,sending,receiving,any,data,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Operator,can,bind,True,port,not,currently,bound,can,bound,cannot,bind,True,port,currently,bound,cannot,bound,Port,port,number,check,Test,Condition[$XTITELEND$][$XKEYS$]Port,Test,Condition[$XKEYSEND$]`;";
s[168] = "Ask Yes or No^AskYesOrNo.html^This condition posts a message box that asks the user a question and expects a yes or no response....^Ask Yes or No^condition,posts,message,box,that,asks,user,question,expects,yes,response,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Default,Button,button,highlight,default,when,message,box,posts,button,clicked,user,hits,Return,Icon,standard,icon,use,for,message,box,Result,Virtual,Text,virtual,text,variable,hold,result,message,box,True,Value,Specifies,which,value,message,box,return,true,value,for,condition,user,clicks,Yes,Yes,true,value,condition,pass,etc,Yes,No[$XTITELEND$][$XKEYS$]Ask,Yes,No[$XKEYSEND$]`;";
s[169] = "File Extension Test Condition^FileExtensionExistsCondition.html^This condition checks to see if a given file extension exists in the Windows registry.Standard...^File Extension Test Condition^condition,checks,see,given,file,extension,exists,Windows,registry,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,File,Extension,extension,check,Operator,exists,True,extension,exists,does,not,exist,True,extension,does,not,exist,Extension,Test,Condition[$XTITELEND$][$XKEYS$]File,Extension,Exists,Condition[$XKEYSEND$]`;";
s[170] = "File Type Test Condition^FileTypeExistsCondition.html^This condition checks to see if a given file type exists in the Windows registry.Standard Prop...^File Type Test Condition^condition,checks,see,given,file,type,exists,Windows,registry,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,File,Type,file,type,check,Operator,exists,True,file,type,exists,does,not,exist,True,file,type,does,not,exist,Type,Test,Condition[$XTITELEND$][$XKEYS$]File,Type,Exists,Condition[$XKEYSEND$]`;";
s[171] = "Registry Test Condition^RegistryEntryExistsCondition.html^This condition checks to see if a given registry key or value exists in Windows registry.Stand...^Registry Test Condition^condition,checks,see,given,registry,key,value,exists,Windows,registry,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Operator,exists,True,key,value,exists,does,not,exist,True,key,value,does,not,exist,Registry,Key,registry,key,check,Registry,Value,registry,value,check,property,null,only,check,see,key,exists,Test,Condition[$XTITELEND$][$XKEYS$]Registry,Entry,Exists,Condition[$XKEYSEND$]`;";
s[172] = "Windows Service Test Condition^WindowsServiceTestCondition.html^This condition tests certain properties of a Windows service.Standard Properties  See Standa...^^condition,tests,certain,properties,Windows,service,Standard,Properties,See,Standard,Condition,Properties,Advanced,Properties,Advanced,Properties,Database,Specifies,service,control,database,operated,default,active,service,control,database,target,system,Operator,exists,True,service,exists,does,not,exist,True,service,does,not,exist,paused,True,service,paused,state,running,True,service,currently,running,stopped,True,service,not,currently,running,Service,Name,name,service,perform,action,can,internal,display,name,service,display,name,given,automatically,translated,internal,service,name,for,action,System,Specifies,name,system,which,command,should,invoked,default,local,system,Service,Test,Condition[$XTITELEND$][$XKEYS$]Windows,Service,Test,Condition[$XKEYSEND$]`;";
s[173] = "What is Virtual Text?^WhatIsVirtualText.html^Virtual text is used throughout InstallJammer as a way to define variables within an install and som...^What is Virtual Text?^Virtual,text,used,throughout,InstallJammer,way,define,variables,within,install,sometimes,within,install,builder,itself,You,see,virtual,text,throughout,your,use,InstallJammer,text,that,between,Some,virtual,text,defined,you,when,you,create,your,project,other,virtual,text,defined,InstallJammer,when,builds,your,project,example,virtual,text,that,you,define,<%AppName%>,virtual,text,which,represents,Application,Name,you,filled,when,you,created,your,project,example,virtual,text,defined,InstallJammer,would,<%InstallMode%>,which,during,installation,can,tell,you,whether,user,chose,Standard,Default,Silent,install,Virtual,text,easy,way,for,InstallJammer,represent,variable,data,within,install,since,can,nested,virtual,text,can,contain,other,virtual,text,that,all,represented,when,used,within,install,Using,Virtual,Text,Virtual,text,can,used,almost,anywhere,install,InstallJammer,automatically,substitute,virtual,text,for,its,value,when,needed,use,virtual,text,simply,use,one,available,Virtual,Text,Definitions,between,For,example,<%AppName%>,when,used,project,substituted,for,your,Application,Name,during,installation,<%Platform%>,substituted,for,name,current,platform,you're,installing,Windows,Linux,x86,etc,Virtual,text,can,nested,inside,another,virtual,text,definition,InstallJammer,automatically,substitute,all,values,recursively,means,that,your,Application,Name,contains,Application,<%Version%>,InstallJammer,substitute,<%Version%>,recursively,inside,virtual,text,value,your,application's,version,you,would,get,Application,whatever,your,version,Arguments,Virtual,Text,Some,virtual,text,fields,can,also,receive,arguments,that,modify,value,virtual,text,case,virtual,text,not,single,word,surrounded,but,instead,first,word,virtual,text,along,with,arguments,passed,after,word,example,<%Date%>,virtual,text,which,can,passed,with,argument,that,specifies,format,date,string,<%Date,tells,InstallJammer,return,today's,date,format,digit,year,argument,passed,Date,virtual,text,Another,<%Dir,forwardslash%>,would,return,Boolean,Values,Virtual,Text,InstallJammer,automatically,converts,any,virtual,text,value,that,looks,like,boolean,into,mostly,make,dealing,with,booleans,simpler,but,it's,also,that,checkbuttons,respond,accurately,virtual,text,since,checkbuttons,expect,for,value,not,various,boolean,values,that,acceptable,Acceptable,boolean,values,false,off,true,yes,any,abbreviated,uppercase,spellings,You,should,always,check,virtual,text,variables,that,boolean,checking,see,string,true,false,not,specific,string,like,yes,String,Condition,better,than,String,Equal,Condition,for,boolean,values,Virtual,Text,Virtual,Text`;";
s[174] = "Virtual Text Definitions^VirtualTextDefinitions.html^The following virtual text definitions are currently available in InstallJammer.  Anytime you see ?s...^Virtual Text Definitions^following,virtual,text,definitions,currently,available,InstallJammer,Anytime,you,see,something,inside,virtual,text,field,means,that,that,virtual,text,can,must,have,argument,passed,<%AllowLanguageSelection%>,true,user,prompted,select,language,beginning,install,<%AppName%>,name,application,set,during,build,time,Application,Information,tab,<%ApplicationID%>,unique,identifier,for,application,set,when,install,project,first,created,never,changes,through,life,project,can,used,identify,previous,installs,same,application,target,system,InstallJammer,uses,during,uninstallation,<%BuildVersion%>,build,version,fourth,value,<%InstallVersion%>,<%CancelledInstallAction%>,Contains,text,describing,action,InstallJammer,take,install,cancelled,mid,process,virtual,text,defined,under,Install,Features,Application,Information,tab,<%CleanupCancelledInstall%>,Tells,InstallJammer,whether,needs,cleanup,cancelled,install,not,<%Company%>,company,name,set,during,build,time,Application,Information,tab,<%ConsoleMode%>,True,install,currently,being,run,console,mode,<%CurrentAction%>,current,action,being,executed,<%CurrentCondition%>,current,condition,being,executed,<%CurrentObject%>,current,object,being,used,system,can,pane,action,condition,<%CurrentPane%>,Pane,current,pane,displayed,user,<%Date,dateFormat,formatted,string,today's,date,based,<%DateFormat%>,Date,virtual,text,can,receive,optional,argument,format,use,for,date,Defaults,<%Date,<%DateFormat%>%>,<%DateFormat%>,default,format,use,for,<%Date%>,when,format,argument,specified,Defaults,%Y%m%d,which,looks,like,20051201,<%Debugging%>,true,InstallJammer,run,debugging,mode,Debug,mode,outputs,debug,messages,log,file,saves,temporary,directory,used,during,installation,for,later,debugging,<%DefaultLanguage%>,default,language,none,specified,user,not,allowed,choose,language,<%DefaultMode%>,True,user,selected,run,install,Default,mode,<%Dir,directory,filename,platform,Take,given,directory,normalize,that,matches,format,current,platform,Windows,use,path,separator,UNIX,path,separator,any,drive,lettering,etc,stripped,off,second,argument,specified,can,one,backslash,forwardslash,platform,unix,windows,Backslash,forwardslash,specifies,which,path,separator,use,but,other,modifications,done,directory,Unix,Windows,behave,described,above,for,given,platform,<%Dirname,directory,filename,Given,directory,filename,return,parent,directory,<%Dirname,would,return,<%DiskSpace,disk,space,Returns,pretty,text,string,describing,space,disk,space,Depending,size,where,size,<%DOSName,directory,filename,Given,directory,filename,return,short,DOS,name,Windows,return,something,like,using,Windows,native,short,name,<%Env,variable,return,value,environment,variable,exists,<%Env,PATH%>,would,return,user's,current,PATH,variable,<%ErrorDirs%>,set,Uninstall,Selected,Files,<%ErrorsOccurred%>,true,virtual,text,may,contain,list,directories,that,uninstaller,failed,remove,<%ErrorFiles%>,set,Uninstall,Selected,Files,<%ErrorsOccurred%>,true,virtual,text,may,contain,list,files,that,uninstaller,failed,remove,<%Errors%>,set,Uninstall,Selected,Files,<%ErrorsOccurred%>,true,virtual,text,contain,string,representation,errors,that,occurred,during,uninstall,usually,displayed,user,uninstall,details,<%ErrorsOccurred%>,set,Uninstall,Selected,Files,set,during,Uninstall,Selected,Files,action,false,errors,occurred,during,uninstall,true,some,error,happened,while,doing,uninstall,<%Ext%>,Return,executable,extension,for,current,platform,exe,Windows,empty,UNIX,<%ExtractSolidArchivesOnStartup%>,True,developer,has,opted,extract,any,solid,archives,when,installer,first,starts,<%FileBeingInstalled%>,file,currently,being,installed,only,valid,during,file,installation,<%FileBeingInstalledText%>,pretty,text,describing,current,file,being,installed,Defaults,Copying,<%FileBeingInstalled%>,<%FileGroup,file,group,Given,name,file,group,return,full,directory,path,for,that,file,group,<%GroupBeingInstalled%>,name,current,file,group,being,installed,only,valid,during,file,installation,<%GroupBeingInstalledText%>,pretty,text,describing,current,group,being,installed,Defaults,Installing,<%GroupBeingInstalled%>,<%GUID%>,Generates,new,globally,unique,identifier,GUID,<%GuiMode%>,True,install,currently,running,mode,that,requires,GUI,<%IncludeDebugging%>,Whether,not,debugging,options,were,included,installer,<%InstallDirSuffix%>,virtual,text,variable,exists,your,project,its,value,automatically,appended,<%InstallDir%>,anytime,changed,<%InstallDir%>'s,tail,directory,does,not,already,match,value,InstallDirSuffix,were,set,<%AppName%>,for,example,installer,would,always,append,name,your,application,installation,directory,path,matter,where,user,chooses,install,unless,InstallDir,already,has,<%AppName%>,end,<%InstallDrive%>,Windows,only,virtual,text,holds,drive,letter,that,installation,targeted,for,<%InstallDir%>,<%InstallDrive%>,would,virtual,text,automatically,updated,anytime,<%InstallDir%>,value,changed,<%InstallFinished%>,Whether,not,InstallJammer,completed,file,installation,only,true,file,installation,was,begun,completed,without,user,cancelling,<%InstallHasSolidArchives%>,True,installer,has,any,solid,archives,<%InstallID%>,unique,identifier,for,instance,running,installer,set,when,installer,first,starts,new,one,generated,every,time,installer,run,<%InstallMode%>,current,mode,installation,chosen,user,Can,Console,Default,Silent,Standard,<%InstallPassword%>,virtual,text,used,default,Install,Password,pane,most,themes,empty,default,contain,password,user,enters,one,usually,matched,against,<%InstallPasswordEncrypted%>,virtual,text,see,password,correct,<%InstallPasswordEncrypted%>,project,was,defined,with,install,password,for,installer,virtual,text,contain,encrypted,form,that,password,plain,text,form,install,password,never,stored,installer,itself,virtual,text,usually,compared,against,password,user,enters,using,Password,Test,Condition,see,they,match,<%InstallPercentComplete%>,current,percentage,complete,file,installation,only,valid,during,file,installation,<%InstallRegistryInfo%>,virtual,text,set,false,your,project,InstallJammer,not,attempt,create,registry,directory,separate,from,your,installation,hold,its,install,information,Instead,all,install,information,stored,inside,uninstaller,that,can,properly,uninstall,<%InstallSource%>,full,path,source,directory,installation,executable,was,started,from,<%InstallStarted%>,True,file,installation,portion,install,was,started,whether,completed,not,<%InstallStopped%>,True,user,cancelled,file,installation,before,had,chance,complete,<%InstallType%>,setup,type,installation,user,has,chosen,install,user,not,given,option,select,setup,type,that,pane,has,not,been,shown,yet,variable,default,Default,Setup,Type,set,during,build,time,<%InstallVersion%>,install,version,your,application,version,represented,also,used,InstallJammer,when,determining,whether,install,files,based,version,numbers,<%Installer%>,full,path,installation,executable,when,was,started,<%InstallerID%>,unique,identifier,for,installer,set,when,installer,built,remains,same,matter,how,many,times,install,run,changes,with,each,build,installer,<%Installing%>,True,file,installation,currently,progress,<%Language%>,current,language,installer,expressed,language,code,optional,country,code,optional,system,specific,code,each,separated,country,language,code,specified,standards,ISO,639,ISO,3166,For,example,locale,specified,English,en_US,specifies,english,<%LastGUID%>,Contains,value,last,GUID,generated,using,<%GUID%>,virtual,text,<%LastUUID%>,Contains,value,last,UUID,generated,using,<%UUID%>,virtual,text,<%LicenseAccepted%>,True,user,has,seen,accepted,license,agreement,for,application,<%MajorVersion%>,major,version,first,value,<%InstallVersion%>,<%MinorVersion%>,minor,version,second,value,<%InstallVersion%>,<%PackageDescription%>,package,description,defined,project,<%PackageLicense%>,package,license,defined,project,<%PackageMaintainer%>,package,maintainer,defined,project,<%PackageName%>,package,name,defined,project,<%PackagePackager%>,package,packager,defined,project,<%PackageRelease%>,package,release,version,defined,project,<%PackageSummary%>,package,summary,defined,project,<%PackageVersion%>,package,version,defined,project,<%PatchVersion%>,patch,version,third,value,<%InstallVersion%>,<%PathSeparator%>,character,used,separate,paths,variables,target,system,for,Windows,for,UNIX,<%Platform%>,name,current,platform,being,installed,variable,only,exists,during,installation,time,<%ProgramExecutable%>,specified,user,during,build,time,variable,contains,path,executable,that,start,installed,program,upon,completion,installation,<%ProgramFolderName%>,name,Program,Folder,user,has,chosen,user,not,given,option,select,program,folder,that,pane,has,not,been,shown,yet,variable,default,Default,Program,Folder,set,during,build,time,<%ProgramLicense%>,location,application's,LICENSE,file,specified,project,<%ProgramReadme%>,location,application's,README,file,specified,project,<%PromptForRoot%>,True,developer,has,opted,prompt,for,root,password,when,root,password,required,run,install,<%Property,object,property,return,value,property,given,object,object,specified,property,value,for,that,object,returned,object,specified,property,returned,for,currently,active,object,can,whatever,action,condition,currently,being,executed,<%RealUsername%>,name,real,user,running,install,user,running,root,through,sudo,<%Username%>,show,root,instead,real,user,name,value,always,reflects,real,user,<%RegValue,registry,key,value,current,value,registry,key,Windows,only,key,passed,default,value,for,that,key,returned,value,passed,that,value,within,specified,key,returned,<%RequireRoot%>,True,installer,requires,root,run,<%RunningInstaller%>,True,currently,running,program,installer,<%RunningUninstaller%>,True,currently,running,program,uninstaller,<%ScriptExt%>,file,extension,for,common,script,each,platform,set,bat,Windows,UNIX,platforms,<%SelectedComponents%>,list,components,that,currently,selected,for,installation,should,treated,Tcl,list,<%SelectedFileGroups%>,list,file,groups,that,currently,selected,for,installation,should,treated,Tcl,list,<%ShortAppName%>,shortened,version,your,application,name,usually,used,UNIX,systems,directory,for,your,application,should,usually,all,lowercase,contain,spaces,<%ShowConsole%>,true,InstallJammer,show,debugging,console,startup,<%SilentMode%>,True,user,selected,run,install,Silent,mode,<%SolidArchivesExtracted%>,True,installer,has,any,solid,archives,that,have,been,extracted,already,<%SpaceAvailable,directory,Returns,disk,space,available,current,drive,directory,specified,returns,disk,space,available,for,that,drive,<%SpaceAvailableText%>,Returns,pretty,text,description,disk,space,available,current,drive,Equivalent,<%DiskSpace,<%SpaceAvailable%>%>,<%SpaceRequired%>,current,amount,space,required,target,system,install,selected,components,<%SpaceRequiredText%>,pretty,text,describing,amount,space,required,install,Equivalent,<%DiskSpace,<%SpaceRequired%>%>,<%Status%>,variable,used,current,status,what,InstallJammer,doing,During,file,installation,usually,set,<%FileBeingInstalledText%>,but,can,reflect,many,other,actions,InstallJammer,taking,<%Tail,directory,filename,Given,directory,filename,return,tail,end,path,<%Tail,would,return,bar,<%Testing%>,true,InstallJammer,run,test,mode,which,means,files,installed,uninstalled,does,not,stop,other,actions,that,create,shortcuts,etc,<%UninstallMode%>,current,uninstall,Console,Silent,Standard,<%UninstallPercentComplete%>,current,percentage,complete,file,uninstallation,only,valid,during,uninstall,<%UpgradeApplicationID%>,Upgrade,Application,specified,developer,<%UpgradeInstall%>,Upgrade,Application,not,null,value,true,telling,InstallJammer,that,upgrade,install,certain,actions,should,not,performed,<%UserIsRoot%>,True,user,currently,installing,root,<%UserMovedBack%>,True,user,has,reached,current,pane,clicking,Back,button,<%UserMovedNext%>,True,user,has,reached,current,pane,clicking,Next,button,<%Username%>,username,current,system,user,executing,install,user,currently,root,value,show,'root',you,want,know,user,who,currently,running,root,you,can,use,<%RealUsername%>,<%Version%>,version,set,during,build,time,Application,Information,tab,<%WindowsPlatform%>,string,specifying,exact,version,Windows,currently,being,installed,Possible,versions,Win95,Win98,WinNT,WinME,Win2k,WinXP,Win2003,Vista,Windows7,<%WizardCancelled%>,True,wizard,started,user,cancelled,wizard,before,completed,<%WizardFinished%>,True,wizard,was,started,actually,completed,successfully,without,user,cancelling,<%WizardFirstStep%>,True,pane,currently,displayed,first,step,wizard,<%WizardLastStep%>,True,pane,currently,displayed,last,step,wizard,<%WizardStarted%>,True,wizard,started,successfully,virtual,text,always,false,for,silent,console,installs,since,wizard,ever,started,Text,Definitions[$XTITELEND$][$XKEYS$]Virtual,Text,Definitions[$XKEYSEND$]`;";
s[175] = "Virtual Directory Definitions^VirtualDirectoryDefinitions.html^The following Virtual Directories are currently available in InstallJammer.<%Desktop%>The dire...^Virtual Directory Definitions^following,Virtual,Directories,currently,available,InstallJammer,<%Desktop%>,directory,location,user's,desktop,Windows,user's,desktop,UNIX,value,dependant,upon,which,window,manager,user,running,during,installation,<%GnomeDesktop%>,Gnome,desktop,directory,where,Gnome,stores,all,shortcuts,that,appear,desktop,directory,empty,user,does,not,have,Gnome,Desktop,<%Home%>,user's,home,directory,Windows,InstallJammer,attempts,find,best,possible,option,for,user's,home,directory,they,have,not,specified,location,for,<%InstallDir%>,destination,directory,user,has,chosen,install,user,not,given,option,select,destination,directory,that,pane,has,not,been,shown,yet,variable,default,Default,Destination,Directory,set,during,build,time,<%InstallInfoDir%>,directory,where,InstallJammer,store,all,its,registry,information,for,install,where,check,for,registry,information,during,uninstallation,<%InstallJammerRegistryDir%>,root,directory,that,InstallJammer,using,store,registry,information,about,your,installs,does,not,include,subdirectory,for,current,install,directory,where,directories,for,each,install,stored,<%InstallSource%>,directory,installer,executable,was,when,was,started,<%KDEDesktop%>,KDE,desktop,directory,where,KDE,stores,all,shortcuts,that,appear,desktop,directory,empty,user,does,not,have,KDE,Desktop,<%ProgramFolder%>,full,path,Program,Folder,user,has,selected,usually,combination,Programs,folder,ProgramFolderName,<%RootInstallDir%>,root,install,dir,not,null,user,root,<%InstallDir%>,set,value,startup,<%Temp%>,temporary,directory,used,InstallJammer,during,installation,Once,InstallJammer,has,finished,directory,all,its,contents,deleted,useful,for,creating,temporary,files,during,installation,<%TempRoot%>,root,temporary,directory,being,used,InstallJammer,InstallJammer,always,create,subdirectory,<%TempRoot%>,all,its,work,but,<%TempRoot%>,actual,temporary,directory,user's,system,user,can,specify,directory,command,line,with,temp,option,Temp,Root,determined,looking,TEMP,environment,variable,TMP,environment,variable,Windows,only,Windows,only,Windows,only,Windows,only,UNIX,only,UNIX,only,UNIX,only,Windows,Virtual,Directories,following,Virtual,Directories,also,available,Windows,platform,Virtual,text,all,uppercase,letters,treated,specially,InstallJammer,Windows,directory,<%ADMINTOOLS%>,<%ALTSTARTUP%>,File,system,directory,that,corresponds,user's,nonlocalized,Startup,program,group,<%APPDATA%>,File,system,directory,that,serves,common,repository,for,application,specific,data,typical,path,Data,<%BITBUCKET%>,Virtual,folder,containing,objects,user's,Recycle,Bin,<%CDBURN_AREA%>,<%COMMON_ADMINTOOLS%>,<%COMMON_ALTSTARTUP%>,File,system,directory,that,corresponds,nonlocalized,Startup,program,group,for,all,users,Valid,only,for,Microsoft,Windows,NT®,systems,<%COMMON_APPDATA%>,<%COMMON_DESKTOPDIRECTORY%>,File,system,directory,that,contains,files,folders,that,appear,desktop,for,all,users,typical,path,Valid,only,for,Windows,systems,<%COMMON_DOCUMENTS%>,<%COMMON_FAVORITES%>,File,system,directory,that,serves,common,repository,for,all,users',favorite,items,Valid,only,for,Windows,systems,<%COMMON_MUSIC%>,<%COMMON_OEM_LINKS%>,<%COMMON_PICTURES%>,<%COMMON_PROGRAMS%>,File,system,directory,that,contains,directories,for,common,program,groups,that,appear,Start,menu,for,all,users,typical,path,Valid,only,for,Windows,systems,<%COMMON_QUICK_LAUNCH%>,quick,launch,directory,common,all,users,system,Adding,shortcut,cause,appear,every,user's,quick,launch,bar,<%COMMON_STARTMENU%>,File,system,directory,that,contains,programs,folders,that,appear,Start,menu,for,all,users,typical,path,Menu,Valid,only,for,Windows,systems,<%COMMON_STARTUP%>,File,system,directory,that,contains,programs,that,appear,Startup,folder,for,all,users,typical,path,Valid,only,for,Windows,systems,<%COMMON_TEMPLATES%>,<%COMMON_VIDEO%>,<%COMPUTERSNEARME%>,<%CONNECTIONS%>,<%CONTROLS%>,Virtual,folder,containing,icons,for,Control,Panel,applications,<%COOKIES%>,File,system,directory,that,serves,common,repository,for,Internet,cookies,typical,path,<%DESKTOP%>,Windows,Desktop,virtual,folder,that,root,namespace,<%DESKTOPDIRECTORY%>,File,system,directory,used,physically,store,file,objects,desktop,not,confused,with,desktop,folder,itself,typical,path,<%DRIVES%>,Computer,virtual,folder,containing,everything,local,storage,devices,printers,Control,Panel,folder,may,also,contain,mapped,network,drives,<%FAVORITES%>,File,system,directory,that,serves,common,repository,for,user's,favorite,items,typical,path,<%FONTS%>,Virtual,folder,containing,fonts,typical,path,<%HISTORY%>,File,system,directory,that,serves,common,repository,for,Internet,history,items,<%INTERNET%>,Virtual,folder,representing,Internet,<%INTERNET_CACHE%>,File,system,directory,that,serves,common,repository,for,temporary,Internet,files,typical,path,Internet,Files,<%LOCAL_APPDATA%>,<%MYDOCUMENTS%>,<%MYMUSIC%>,<%MYPICTURES%>,<%MYVIDEO%>,<%NETHOOD%>,file,system,folder,containing,link,objects,that,may,exist,Network,Places,virtual,folder,not,same,NETWORK,which,represents,network,namespace,root,typical,path,<%NETWORK%>,Network,Neighborhood,virtual,folder,representing,root,network,namespace,hierarchy,<%PERSONAL%>,File,system,directory,that,serves,common,repository,for,documents,typical,path,Documents,should,distinguished,from,virtual,Documents,folder,namespace,<%PRINTERS%>,Virtual,folder,containing,installed,printers,<%PRINTHOOD%>,File,system,directory,that,contains,link,objects,that,may,exist,Printers,virtual,folder,typical,path,<%PROFILE%>,<%PROGRAM_FILES%>,folder,for,components,that,shared,across,applications,typical,path,Files,<%PROGRAM_FILESX86%>,<%PROGRAM_FILES_COMMON%>,<%PROGRAM_FILES_COMMONX86%>,<%PROGRAMS%>,File,system,directory,that,contains,user's,program,groups,which,also,file,system,directories,typical,path,<%QUICK_LAUNCH%>,File,system,directory,that,contains,Windows,shortcuts,that,appear,user's,Quick,Launch,toolbar,Not,valid,Windows,<%RECENT%>,File,system,directory,that,contains,user's,most,recently,used,documents,typical,path,<%RESOURCES%>,<%RESOURCES_LOCALIZED%>,<%SENDTO%>,File,system,directory,that,contains,Send,menu,items,typical,path,<%STARTMENU%>,File,system,directory,containing,Start,menu,items,typical,path,Menu,<%STARTUP%>,File,system,directory,that,corresponds,user's,Startup,program,group,system,starts,these,programs,whenever,any,user,logs,onto,Windows,starts,Windows,typical,path,<%SYSTEM%>,System,folder,typical,path,<%SYSTEM32%>,System,folder,typical,path,<%SYSTEMX86%>,<%TEMPLATES%>,File,system,directory,that,serves,common,repository,for,document,templates,<%WINDOWS%>,Windows,directory,SYSROOT,corresponds,%windir%,%SYSTEMROOT%,environment,variables,typical,path,Directory,Definitions[$XTITELEND$][$XKEYS$]Virtual,Directory,Definitions[$XKEYSEND$]`;";
s[176] = "Debugging an Install^DebuggingAnInstall.html^InstallJammer provides several different ways and helpful tools to help debug installs.  Most instal...^Debugging an Install^InstallJammer,provides,several,different,ways,helpful,tools,help,debug,installs,Most,installs,fairly,simple,don't,really,require,complex,debugging,but,some,installs,can,get,very,elaborate,require,ability,peek,into,what,InstallJammer,really,doing,background,Commands,for,debugging,InstallJammer,provides,two,commands,assist,with,debug,debugging,debug,command,output,debug,message,can,used,scripts,console,output,debugging,information,debugging,command,command,that,controls,what,debugging,taking,place,during,installation,following,usage,for,debugging,debugging,level,command,sets,level,debugging,output,show,means,output,means,very,verbose,output,default,level,when,not,specified,debugging,<on,off>,command,simply,turn,debugging,off,debugging,<file,console>,<on,off>,filename,command,turn,debugging,off,specifically,for,outputing,debug,information,file,console,filename,given,file,output,directed,that,file,filename,given,debug,output,file,turned,file,log,used,any,case,when,you,use,debugging,command,tell,you,exactly,what,how,logging,Calling,debugging,command,with,arguments,tell,you,current,state,debugging,installer,Debug,output,console,controlled,variable,Debug,output,file,controlled,Debugging,variable,variable,open,file,pointer,debug,log,file,open,variable,empty,string,file,logging,turned,off,Install[$XTITELEND$][$XKEYS$]Debugging,Install[$XKEYSEND$]`;";
s[177] = "What is the Builder API?^WhatIsTheBuilderAPI.html^The Builder API is a set of functions that can be used in control scripts when executing the builder...^What is the Builder API?^Builder,API,set,functions,that,can,used,control,scripts,when,executing,builder,from,command,line,allows,you,create,scripts,that,can,passed,command,line,that,modify,your,installer,based,criteria,Calling,Builder,API,proc,All,procs,Builder,API,namespace,call,proc,Builder,API,simply,use,fully,qualified,name,proc,your,code,All,arguments,passed,Builder,API,proc,non,positional,key,value,pairs,That,means,that,doesn't,matter,what,order,you,pass,arguments,since,each,argument,specified,option,with,value,For,example,let's,say,wanted,change,name,installer,produced,for,Windows,platform,certain,case,You,would,add,something,like,control,platform,Windows,property,Executable,value,setup,exe,example,call,proc,with,three,platform,property,value,Each,property,must,have,value,after,Finding,arguments,API,call,All,API,calls,loaded,into,install,builder,when,loads,you,can,easily,into,console,through,Help,>Show,Debug,Console,menu,type,Builder,API,call,see,what,can,see,usage,for,API,call,type,name,call,argument,into,console,Like,dump,usage,information,including,all,possible,arguments,for,API,call,course,you,can,always,read,documentation,for,each,call,well,but,might,quicker,for,some,people,Builder,API,Builder,API`;";
s[178] = "GetAction^GetAction.html^::BuilderAPI::GetActionFind an action object by its alias and setup.Supported PlatformsA...^GetAction^Find,action,object,its,alias,setup,Supported,Platforms,All,Returns,Object,empty,string,Options,alias,alias,action,locate,setup,Can,one,install,uninstall,look,for,given,action,within,install,tree,uninstall,tree`;";
s[179] = "GetActionGroup^GetActionGroup.html^::BuilderAPI::GetActionGroupFind an action group object by its alias and setup.Supported P...^GetActionGroup^Find,action,group,object,its,alias,setup,Supported,Platforms,All,Returns,Object,empty,string,Options,alias,alias,action,group,locate,setup,Can,one,install,uninstall,look,for,given,action,group,within,install,tree,uninstall,tree`;";
s[180] = "ModifyObject^ModifyObject1.html^::BuilderAPI::ModifyObjectMark an object as active or inactive.Supported PlatformsAll...^ModifyObject^Mark,object,active,inactive,Supported,Platforms,All,Returns,Empty,string,Options,active,property,true,given,object,made,active,false,object,deactivated,object,alias,object,object,modify`;";
s[181] = "SetPlatformProperty^SetPlatformProperty.html^::BuilderAPI::SetPlatformPropertySet a platform-specific property for a given platformSupp...^SetPlatformProperty^Set,platform,specific,property,for,given,platform,Supported,Platforms,All,Returns,Empty,string,Options,platform,platform,set,property,for,can,any,platform,supported,current,installation,can,word,all,mean,all,plaforms,word,unix,mean,all,unix,platforms,word,active,mean,active,platforms,property,Specfies,property,set,for,given,platform,current,properties,for,platforms,Active,BuildSeparateArchives,DefaultFilePermission,DefaultDirectoryPermission,Executable,FallBackToConsole,FileDescription,InstallDir,InstallMode,InstallType,ProgramName,ProgramReadme,ProgramLicense,ProgramFolderName,ProgramExecutable,ProgramFolderAllUsers,PromptForRoot,RequireAdministrator,RequireRoot,RootInstallDir,UseUncompressedBinaries,WindowsIcon,value,value,set,given,property`;";
s[182] = "What is the Install API?^WhatIsTheInstallAPI.html^The Install API is a set of functions that can be used in your installer to create more complex inst...^What is the Install API?^Install,API,set,functions,that,can,used,your,installer,create,more,complex,installers,than,normally,available,through,standard,actions,conditions,Some,actions,conditions,InstallJammer,even,use,pieces,Install,API,real,work,Install,API,loaded,with,procs,that,you,can,call,from,Execute,Script,actions,Script,Condition,conditions,that,give,you,program,level,access,inner,workings,InstallJammer,important,know,that,Install,API,built,fly,your,installer,packaged,Only,procs,that,you,actually,use,your,installer,included,packaged,installer,really,only,means,that,you,cannot,make,API,calls,from,running,console,unless,you,already,using,that,API,somewhere,your,installer,since,API,call,would,not,have,been,built,into,your,installer,Calling,Install,API,proc,All,procs,Install,API,namespace,call,proc,Install,API,simply,use,fully,qualified,name,proc,your,code,All,arguments,passed,Install,API,proc,non,positional,key,value,pairs,That,means,that,doesn't,matter,what,order,you,pass,arguments,since,each,argument,specified,option,with,value,For,example,let's,say,had,Execute,Script,action,where,wanted,some,checking,then,set,virtual,text,variable,might,look,something,like,virtualtext,Foo]},virtualText,Foo,value,Bar,you,can,see,from,example,make,two,calls,procs,namespace,code,uses,check,see,virtual,text,Foo,exists,doesn't,already,exist,we're,going,use,set,Bar,arguments,virtualtext,Foo,passed,tells,call,that,want,check,virtual,text,variable,Foo,exists,arguments,virtualtext,Foo,value,Bar,tell,that,want,set,virtual,text,variable,Foo,value,Bar,Finding,arguments,API,call,All,API,calls,loaded,into,install,builder,when,loads,you,can,easily,into,console,through,Help,>Show,Debug,Console,menu,type,Install,API,call,see,what,can,see,usage,for,API,call,type,name,call,argument,into,console,Like,dump,usage,information,including,all,possible,arguments,for,API,call,course,you,can,always,read,documentation,for,each,call,well,but,might,quicker,for,some,people,Install,API,Install,API`;";
s[183] = "AddInstallInfo^AddInstallInfo1.html^::InstallAPI::AddInstallInfoAdd information to be stored in the install log for this installatio...^AddInstallInfo^Add,information,stored,install,log,for,installation,InstallJammer,automatically,creates,log,file,for,every,installation,that,contains,default,set,values,for,each,installation,API,lets,you,add,information,that,log,that,can,fetched,subsequent,installs,Supported,Platforms,All,Returns,Empty,String,Options,key,<key>,required,key,store,value,under,value,<value>,required,value,store,with,key,Example,following,example,adds,Spanish,language,key,Foo,value,bar,would,add,key,Foo,with,value,bar,install,log,When,using,Check,for,Previous,Install,action,subsequent,installations,you,would,get,new,virtual,text,called,<%PreviousInstallFoo%>,that,contains,bar`;";
s[184] = "AddLanguage^AddLanguage.html^::InstallAPI::AddLanguageAdd a language and language code to the list of available languages in ...^^Add,language,language,code,list,available,languages,current,installer,Supported,Platforms,All,Returns,Empty,String,Options,language,<language,name>,required,name,language,displayed,user,languagecode,<language,code>,required,language,code,for,given,language,Example,following,example,adds,Spanish,language,language,Spanish,languagecode,es[$XTITLE$]AddLanguage[$XTITELEND$][$XKEYS$]Add,Language[$XKEYSEND$]`;";
s[185] = "CommandLineAPI^CommandLineAPI.html^::InstallAPI::CommandLineAPIThis API is used to manipulate and query command line options in an ...^CommandLineAPI^API,used,manipulate,query,command,line,options,installer,uninstaller,Supported,Platforms,All,Returns,See,options,Options,Specifies,action,API,should,take,Possible,values,check,Check,see,option,given,option,was,passed,command,line,Returns,option,was,passed,was,not,exists,Check,see,option,given,option,exists,possible,option,Returns,option,exists,does,not,option,command,line,option,check,Any,stripped,from,left,side,option,before,checked`;";
s[186] = "ComponentAPI^ComponentAPI.html^::InstallAPI::ComponentAPIThis API is used to manipulate and query components within an installe...^ComponentAPI^API,used,manipulate,query,components,within,installer,Supported,Platforms,All,Returns,See,options,Options,active,option,specified,active,state,each,given,components,made,active,inactive,components,list,components,act,word,all,can,passed,signify,that,all,components,install,should,acted,updateinfo,option,true,tells,installer,update,all,information,relating,selected,components,default,Example,following,example,would,deactivate,all,components,current,installer,components,all,active,example,would,activate,component,called,Component,components,Component,active,Notice,that,because,components,expects,list,components,use,command,make,proper,list,before,passing,arguments,API,case,list,with,single,element`;";
s[187] = "ConfigAPI^ConfigAPI.html^::InstallAPI::ConfigAPIThis API is used to manipulate and query internal configuration options i...^ConfigAPI^API,used,manipulate,query,internal,configuration,options,installer,uninstaller,Supported,Platforms,All,Returns,See,options,Options,usenativedirectorydialog,option,turned,installer,use,native,dialog,when,choosing,directory,only,applies,Windows,where,native,dialogs,exist,usenativefiledialog,option,turned,installer,use,native,dialog,when,choosing,file,from,system,only,applies,Windows,where,native,dialogs,exist,usenativemessagebox,option,turned,installer,use,native,dialog,when,displaying,messages,user,only,applies,Windows,where,native,dialogs,exist`;";
s[188] = "CopyObject^CopyObject.html^::InstallAPI::CopyObjectMake a copy of an existing object in the current environment.Suppo...^CopyObject^Make,copy,existing,object,current,environment,Supported,Platforms,All,Returns,Name,new,object,Options,object,<object,alias>,required,Object,Alias,object,copied,newobject,<object,name>,name,give,new,object,option,not,specified,new,object,created,with,unique`;";
s[189] = "ErrorMessage^ErrorMessage.html^::InstallAPI::ErrorMessageDisplay an error message to the user using standard tools.Suppor...^ErrorMessage^Display,error,message,user,using,standard,tools,Supported,Platforms,All,Returns,Empty,String,Options,message,<error,message>,required,body,message,display,user,dialog,box,console,title,<dialog,title>,window,title,dialog,box,when,pops,not,specified,default,Install,Error`;";
s[190] = "DestroyWidget^DestroyWidget1.html^::InstallAPI::DestroyWidgetCompletely destroys a widget or list of widgets.Supported Platf...^DestroyWidget^Completely,destroys,widget,list,widgets,Supported,Platforms,All,Returns,Empty,string,Options,widgets,list,widget,IDs,aliases,Each,widget,can,specified,its,alias,form,<PANE>,<WIDGET>,where,<PANE>,Alias,pane,<WIDGET>,Alias,widget,that,pane`;";
s[191] = "Exit^Exit1.html^::InstallAPI::ExitExit the running program as either a canceled or finished install.Suppor...^Exit^Exit,running,program,either,canceled,finished,install,Supported,Platforms,All,Returns,Empty,string,Options,exitcode,<exit,code>,option,specified,set,exit,code,running,installer,before,exits,exittype,<cancel,finish>,Tell,installer,whether,exit,canceled,install,finished,install,affects,whether,Cancel,Finish,actions,executed,installer,exits`;";
s[192] = "Fetch URL^FetchURL1.html^::InstallAPI::FetchURLFetch the given URL and store its contents into virtual text or in a file....^Fetch URL^Fetch,given,URL,store,its,contents,into,virtual,text,file,Supported,Platforms,All,Returns,Empty,string,error,Options,blocksize,<size>,block,size,use,when,downloading,smaller,block,size,finer,progress,bar,but,usually,slower,because,more,calls,made,download,full,file,size,file,<filename>,name,file,store,downloaded,file,can,also,list,files,separated,that,corresponds,list,URLs,separated,Each,URL,relates,one,file,list,progressvirtualtext,<virtual,text>,name,virtual,text,variable,without,update,progress,download,usually,attached,progress,bar,proxyhost,<hostname>,host,name,proxy,server,use,for,request,proxyport,<port,number>,port,number,proxy,server,use,for,request,statusvirtualtext,<virtual,text>,name,virtual,text,variable,without,update,with,status,files,downloaded,set,status,virtual,text,<%DownloadVirtualText%>,files,downloaded,more,than,one,file,specified,status,also,contain,current,total,file,count,url,<URL>,URL,list,URLs,separated,download,virtualtext,<virtual,text>,virtual,text,variable,list,virtual,text,variables,separated,without,store,downloaded,files,into,Each,URL,relates,single,virtual,text,variable,URL[$XTITELEND$][$XKEYS$]Fetch,URL[$XKEYSEND$]`;";
s[193] = "PropertyFileAPI^PropertyFileAPI.html^::InstallAPI::PropertyFileAPIThis API provides the necessary functions for reading, manipulating...^PropertyFileAPI^API,provides,necessary,functions,for,reading,manipulating,writing,common,properties,files,properties,file,follows,standard,convention,for,Java,properties,files,but,basically,matches,almost,universal,format,for,simple,properties,within,file,Supported,Platforms,All,Returns,See,options,Options,array,<arrayName>,required,name,array,store,values,required,Specifies,action,API,should,take,Possible,values,append,Add,line,given,array,that,should,written,properties,file,data,Return,string,data,that,written,file,written,data,current,contents,properties,file,keys,Return,list,keys,properties,array,read,Read,given,properties,file,into,array,set,Set,value,given,key,value,key,already,exists,overwritten,when,saved,file,replace,original,line,that,set,key,same,place,within,file,unset,Unset,value,given,key,remove,key,from,array,well,delete,any,reference,value,when,file,written,out,write,Write,property,array,file,file,action,read,write,property,specifies,name,file,read,from,write,key,action,set,unset,property,specifies,key,array,operate,line,action,append,property,specifies,line,multiline,string,append,directly,given,array,separator,Specifies,separator,character,use,between,keys,values,default,value,action,set,unset,property,specifies,value,set,for,given,key,Example,following,example,shows,sample,properties,file,how,API,uses,Sample,properties,file,Set,foo,foo=bar,Set,bar,bar=foo,read,sample,properties,array,props,set,array,props,key,foo,value,NEW,FOO,append,array,props,line,New,value,set,array,props,key,newvalue,value,NEW,VALUE,new,properties,file,look,like,Sample,properties,file,Set,foo,foo=NEW,FOO,Set,bar,bar=foo,New,value,newvalue=NEW,VALUE[$XTITLE$]PropertyFileAPI[$XTITELEND$][$XKEYS$]PropertyFileAPI[$XKEYSEND$]`;";
s[194] = "FindProcesses^FindProcesses.html^:InstallAPI::FindProcessesFind a list of processes on the target system.The API uses the s...^FindProcesses^Find,list,processes,target,system,API,uses,system,'ps',command,find,processes,arguments,manipulated,based,version,what,options,supports,Supported,Platforms,All,Returns,list,process,IDs,pids,that,match,given,criteria,Passing,arguments,return,list,all,pids,processes,found,empty,string,returned,Options,glob,<yes,no>,Windows,only,option,specified,name,option,matched,glob,pattern,instead,exact,match,group,<group,name,ID>,Find,list,processes,running,for,given,group,name,option,does,nothing,Windows,platforms,name,<command,name>,Find,list,processes,that,match,given,command,name,does,not,include,paths,only,actual,command,name,pid,<process,id>,Find,explicit,process,given,useful,you,want,find,out,given,process,running,pid,not,found,FindProcesses,return,empty,string,user,<user,name,ID>,Find,list,processes,running,for,given,user,name,Example,following,example,would,find,running,process,for,gnome,panel,name,gnome,panel,example,would,find,all,processes,being,run,root,user,user,root[$XTITLE$]FindProcesses[$XTITELEND$][$XKEYS$]Find,Processes[$XKEYSEND$]`;";
s[195] = "GetComponentsForSetupType^GetComponentsForSetupType.html^::InstallAPI::GetComponentsForSetupTypeReturn a list of all the components that are included in ...^GetComponentsForSetupType^Return,list,all,components,that,included,given,Setup,Type,Supported,Platforms,All,Returns,List,components,empty,list,Options,setuptype,<setup,type,name,ID>,required,setup,type,can,either,name,setup,type,like,Typical,Custom,can,setup,type,API,call,figure,out,what,you,mean`;";
s[196] = "GetInstallSize^GetInstallSize.html^::InstallAPI::GetInstallSizeGet the required install size for a given object.  The object can be...^GetInstallSize^Get,required,install,size,for,given,object,object,can,Setup,Type,Component,File,Group,With,options,all,API,returns,size,that,required,for,currently,selected,components,install,Supported,Platforms,All,Returns,install,size,required,for,given,object,Options,activeonly,<boolean>,option,true,only,active,objects,added,total,install,size,option,true,default,object,<object,alias>,object,can,Setup,Type,Component,File,Group,return,size,object,specified,install,size,currently,selected,options,user,returned`;";
s[197] = "GetSelectedFiles^GetSelectedFiles.html^::InstallAPI::GetSelectedFilesGet a list of the currently-selected files to be installed.  This ...^GetSelectedFiles^Get,list,currently,selected,files,installed,return,list,all,files,that,currently,selected,installed,when,InstallJammer,reaches,Install,Selected,Files,action,API,automatically,exclude,any,components,file,groups,files,that,inactive,since,they,would,not,installed,Install,Selected,Files,selected,files,also,based,currently,selected,Setup,Type,Supported,Platforms,All,Returns,list,file,object,IDs,list,file,names,depending,options,Options,fileids,<boolean>,option,true,return,value,list,file,object,IDs,instead,list,file,names,default,API,returns,list,target,file,names,installed,Selected,Files[$XKEYSEND$]`;";
s[198] = "GetSystemPackageManager^GetSystemPackageManager.html^::InstallAPI::GetSystemPackageManagerReturns a string describing the package manager used by the...^GetSystemPackageManager^Returns,string,describing,package,manager,used,target,system,API,call,checks,see,dpkg,rpm,command,exists,system,system,were,have,both,dpkg,rpm,same,system,API,return,dpkg,since,first,one,checked,Supported,Platforms,UNIX,Returns,DPKG,system,uses,DPKG,package,database,RPM,system,uses,RPM,package,database,Empty,string,neither,found,used,System,Package,Manager[$XKEYSEND$]`;";
s[199] = "GetWidgetChildren^GetWidgetChildren.html^::InstallAPI::GetWidgetChildrenReturn all the children of a given widget.Supported Platfor...^GetWidgetChildren^Return,all,children,given,widget,Supported,Platforms,All,Returns,list,child,widgets,Options,includeparent,<yes,no>,option,true,returned,list,also,include,given,parent,widget,widget,<widget>,required,Object,alias,widget,whose,children,found,window,<window>,Current,Pane,Object,alias,pane,widget,child`;";
s[200] = "GetWidgetPath^GetWidgetPath.html^::InstallAPI::GetWidgetPathReturn the actual widget path of a given widget object or alias....^GetWidgetPath^Return,actual,widget,path,given,widget,object,alias,Supported,Platforms,All,Returns,full,path,widget,Options,widget,<widget>,required,Object,alias,widget,whose,path,returned,window,<window>,Current,Pane,Object,alias,pane,widget,child`;";
s[201] = "EnvironmentVariableExists^EnvironmentVariableExists.html^::InstallAPI::EnvironmentVariableExistsCheck to see if a given environment variable exists or no...^EnvironmentVariableExists^Check,see,given,environment,variable,exists,not,current,system,environment,API,call,just,looks,into,Tcl's,array,see,variable,exists,not,array,built,Tcl,based,user's,environment,Supported,Platforms,All,Returns,True,false,Options,variable,<varName>,required,variable,check,for,existence,Variable,Exists[$XKEYSEND$]`;";
s[202] = "FindObjects^FindObjects.html^::InstallAPI::FindObjectsSearch the system for an object based on the given options.  See Object...^^Search,system,for,object,based,given,options,See,Object,Types,for,types,objects,project,Supported,Platforms,All,Returns,list,matching,objects,empty,string,Options,active,<yes,no>,specified,only,objects,which,state,given,returned,active,yes,means,return,only,objects,which,active,active,means,only,return,objects,which,inactive,alias,<alias,name>,alias,object,find,option,specified,only,single,object,returned,since,more,than,one,object,can,ever,have,alias,object,found,with,given,alias,empty,string,returned,component,<component,name>,specified,only,objects,that,were,created,from,given,component,included,result,glob,<yes,no>,option,specified,with,name,option,name,option,matched,glob,pattern,instead,exact,name,name,<name>,specified,only,objects,which,have,given,name,included,result,glob,option,true,name,matched,against,pattern,instead,exact,match,parent,<parent,alias>,specified,only,objects,which,children,given,parent,included,result,Note,that,while,project,file,files,children,parent,directory,when,files,added,installer,structures,flattened,that,each,file,child,its,file,group,type,<object,type>,specified,only,objects,which,given,type,included,result,Valid,types,file,filegroup,component,setuptype,condition,action,actiongroup,pane,Example,following,example,finds,all,files,Program,Files,group,has,Program,Files,alias,parent,Program,Files,following,example,finds,all,panes,type,pane,following,example,finds,all,actions,Install,Actions,group,type,action,parent,Install,Actions,following,example,gets,object,for,Install,Actions,group,alias,Install,Actions`;";
s[203] = "LanguageAPI^LanguageAPI.html^::InstallAPI::LanguageAPIThis API is used to manipulate and query language options in an install...^LanguageAPI^API,used,manipulate,query,language,options,installer,uninstaller,Supported,Platforms,All,Returns,See,options,Options,Specifies,action,API,should,take,Possible,values,setlanguage,Set,current,language,installer,language,name,code,language,use`;";
s[204] = "LoadMessageCatalog^LoadMessageCatalog.html^::InstallAPI::LoadMessageCatalogLoad a message catalog file into the current installer.  This wi...^^Load,message,catalog,file,into,current,installer,overwrite,text,that,already,stored,message,catalog,create,new,message,catalogs,for,languages,that,not,already,exist,Loading,messages,for,language,that,does,not,exist,not,add,language,installer,Use,AddLanguage,API,for,that,Supported,Platforms,All,Returns,list,language,codes,used,Options,data,<data,string>,data,parsed,just,like,contents,message,catalog,option,can,used,load,messages,that,read,from,some,other,location,instead,loading,from,file,dir,<directory>,option,specifies,directory,searched,for,msg,files,Each,file,directory,must,named,after,its,language,code,each,file,loaded,based,language,code,contents,file,Loading,message,catalog,for,language,that,does,not,exist,not,result,error,but,language,not,added,running,installer,Use,AddLanguage,API,for,that,encoding,<encoding>,option,specifies,encoding,use,when,reading,message,catalog,from,file,from,data,file,<filename>,name,message,catalog,file,load,name,file,<code>,msg,where,<code>,valid,language,code,current,installer,message,catalog,loaded,into,that,language,file,does,not,match,language,installer,you,must,specify,language,option,tell,InstallJammer,which,language,add,messages,language,<language,language,code>,language,load,message,catalog,into,option,specified,override,any,other,option,that,InstallJammer,might,use,determine,language,from,file,name,object,<object,alias>,option,specifies,alias,file,object,contained,within,installer,that,should,loaded,message,catalog,allows,you,package,message,catalogs,into,your,installer,along,with,rest,your,files,then,load,needed,runtime,name,file,does,not,match,language,installer,you,must,specify,language,option,tell,InstallJammer,which,language,add,messages,Example,following,example,loads,message,catalog,packaged,within,installer,with,alias,Messages,File,adds,messages,English,language,language,English,object,Messages,File,following,example,loads,any,msg,file,from,directory,called,msgs,located,same,directory,installer,These,files,would,most,likely,included,with,release,Notice,subst,option,that,tells,API,substitute,options,passed,for,virtual,text,subst,dir,following,example,loads,single,file,located,directory,with,installer,into,Spanish,language,subst,file,msg[$XTITLE$]LoadMessageCatalog[$XTITELEND$][$XKEYS$]LoadMessageCatalog[$XKEYSEND$]`;";
s[205] = "PromptForDirectory^PromptForDirectory.html^::InstallAPI::PromptForDirectoryPop up a window prompting the user to choose a directory on the ...^PromptForDirectory^Pop,window,prompting,user,choose,directory,target,system,Supported,Platforms,All,Returns,full,directory,path,user,selects,one,empty,string,they,cancel,Options,message,<message,string>,message,display,top,dialog,window,normalize,<boolean>,How,normalize,directory,user,chooses,options,backslash,forwardslash,platform,unix,windows,Backslash,replace,all,directory,separators,with,backslashes,Forwardslash,replace,all,directory,separators,with,forward,slashes,Platform,means,whatever,current,platform,does,Unix,means,use,forward,slashes,remove,any,Windows,drive,letter,etc,Windows,means,use,back,slashes,leave,any,drive,letter,place,default,platform,title,<title,string>,title,string,display,title,bar,dialog,variable,<variable,name>,variable,name,store,resulting,directory,virtualtext,<virtual,text,name>,virtual,text,name,without,store,resulting,directory`;";
s[206] = "PromptForFile^PromptForFile.html^::InstallAPI::PromptForDirectoryPop up a window prompting the user to choose a file (or multiple...^PromptForFile^Pop,window,prompting,user,choose,file,multiple,files,target,system,Supported,Platforms,All,Returns,full,directory,path,user,selects,file,list,files,user,allowed,select,multiple,files,empty,string,they,cancel,Options,defaultextension,<file,extension>,default,file,extension,open,dialog,with,well,default,extension,append,user,types,name,file,without,extension,filetypes,<file,type,list>,Tcl,list,lists,that,specifies,valid,file,types,for,dialog,file,types,specified,list,lists,where,each,inner,list,contains,two,text,description,file,extension,{{Text,Files},txt}},{{All,Files},{*}},initialdir,<directory>,initial,directory,start,dialog,initialfile,<filename>,initial,file,files,multiple,mode,select,dialog,when,first,pops,message,<message,string>,message,display,top,dialog,window,multiple,<boolean>,Whether,not,user,should,allowed,select,multiple,files,normalize,<boolean>,How,normalize,directory,user,chooses,options,backslash,forwardslash,platform,unix,windows,Backslash,replace,all,directory,separators,with,backslashes,Forwardslash,replace,all,directory,separators,with,forward,slashes,Platform,means,whatever,current,platform,does,Unix,means,use,forward,slashes,remove,any,Windows,drive,letter,etc,Windows,means,use,back,slashes,leave,any,drive,letter,place,default,platform,title,<title,string>,title,string,display,title,bar,dialog,type,<open,save>,type,dialog,use,open,save,Open,means,that,dialog,expects,file,already,exist,system,opened,Save,means,that,dialog,can,specify,file,that,does,not,already,exist,prompt,user,file,does,exist,variable,<variable,name>,variable,name,store,resulting,directory,virtualtext,<virtual,text,name>,virtual,text,name,without,store,resulting,directory`;";
s[207] = "ReadInstallInfo^ReadInstallInfo.html^::InstallAPI::ReadInstallInfoRead the install information of a previous installation.  This API ...^ReadInstallInfo^Read,install,information,previous,installation,API,read,information,from,given,application,install,store,values,array,Supported,Platforms,All,Returns,Empty,String,Options,applicationid,<Application,ID>,required,Application,read,information,for,can,installer's,own,<%ApplicationID%>,can,another,known,install,project,lets,your,installer,read,install,information,another,installer,you,know,proper,array,<arrayName>,required,name,array,store,values,installid,<Install,ID>,install,read,information,for,given,all,installs,for,given,application,read,stored,array,order,they,were,created,Example,following,example,adds,Spanish,language,applicationid,SomeID,array,tmp,parray,tmp,would,load,all,previous,installations,for,application,SomeID,into,array,tmp,parray,tmp,would,dump,array,console`;";
s[208] = "ResponseFileAPI^ResponseFileAPI.html^::InstallAPI::ResponseFileAPIManipulate options for response files within installers.  This API ...^ResponseFileAPI^Manipulate,options,for,response,files,within,installers,API,can,used,read,write,response,files,well,manipulate,virtual,text,values,that,saved,installer,response,file,Supported,Platforms,All,Returns,Empty,string,Options,required,Specifies,action,API,should,take,Possible,values,add,Add,list,virtual,text,given,virtualtext,list,variables,save,response,file,read,Read,file,given,file,response,file,remove,Remove,list,virtual,text,given,virtualtext,from,list,variables,save,response,file,write,Write,installer,response,file,given,file,file,Specifies,filename,for,read,write,operations,virtualtext,Specifies,list,virtual,text,for,add,remove,operations`;";
s[209] = "RollbackInstall^RollbackInstall.html^::InstallAPI::RollbackInstallRollback any files, directories and registry entries installed on t...^RollbackInstall^Rollback,any,files,directories,registry,entries,installed,system,during,current,installation,Supported,Platforms,All,Returns,Empty,string[$XTITLE$]RollbackInstall[$XTITELEND$][$XKEYS$]RollbackInstall[$XKEYSEND$]`;";
s[210] = "SetActiveSetupType^SetActiveSetupType.html^:InstallAPI::SetActiveSetupTypeSets the active Setup Type in the current installer.This ca...^SetActiveSetupType^Sets,active,Setup,Type,current,installer,call,set,<%InstallType%>,<%InstallTypeID%>,variables,installer,Supported,Platforms,All,Returns,Empty,string,Options,setuptype,<setup,type,name,ID>,required,setup,type,can,either,name,setup,type,like,Typical,Custom,can,setup,type,API,call,figure,out,what,you,mean,Active,Setup,Type[$XKEYSEND$]`;";
s[211] = "SetExitCode^SetExitCode.html^::InstallAPI::SetExitCodeSet the exit code for the current (un)installer.  By default, an (un)in...^SetExitCode^Set,exit,code,for,current,installer,default,installer,exit,with,exit,code,finishes,canceled,setting,exit,code,you,forcing,exit,code,your,choice,Supported,Platforms,All,Returns,Empty,string,Options,exitcode,<exit,code>,required,Set,exit,code,given,number`;";
s[212] = "SetFileTypeEOL^SetFileTypeEOL.html^::InstallAPI::SetFileTypeEOLThe the end-of-line character for a given filetype that is to be use...^SetFileTypeEOL^end,line,character,for,given,filetype,that,used,when,files,that,type,installed,API,modifies,behavior,installer,such,that,each,file,that,matches,given,file,type,installed,with,specified,EOL,characters,instead,platform,default,useful,for,translating,EOL,characters,from,Windows,UNIX,vice,versa,when,installing,files,Supported,Platforms,All,Returns,Empy,string,Options,eol,<eol>,EOL,string,use,Can,auto,binary,crlf,unix,windows,most,cases,value,must,list,two,EOL,character,file,currently,using,character,translate,extension,<file,extension>,file,extension,list,file,extensions,separated,that,translated,with,given,EOL,would,translate,all,txt,files,that,installed,from,Windows,CRLF,EOL,unix,EOL,assumes,that,txt,files,stored,your,installer,already,have,Windows,EOL,eol,{windows,unix},extension,txt,would,translate,all,ini,files,that,installed,from,unix,EOL,Windows,CRLF,EOL,eol,{unix,windows},extension,ini[$XTITLE$]SetFileTypeEOL[$XTITELEND$][$XKEYS$]SetFileTypeEOL[$XKEYSEND$]`;";
s[213] = "SetObjectProperty^SetObjectProperty1.html^::InstallAPI::SetObjectPropertySet the value of a single property on a given object.Suppor...^SetObjectProperty^Set,value,single,property,given,object,Supported,Platforms,All,Returns,new,value,property,Options,object,<object,alias>,required,object,alias,object,set,new,property,property,<property,name>,required,name,property,set,given,object,value,<property,value>,required,new,value,assign,object,property,Example,following,example,would,change,destination,directory,that,Unzip,File,action,supposed,unzip,object,unzip,action,property,Destination,value`;";
s[214] = "SetVirtualText^SetVirtualText1.html^::InstallAPI::SetVirtualTextSet the value of a virtual text variable in a given language.S...^SetVirtualText^Set,value,virtual,text,variable,given,language,Supported,Platforms,All,Returns,new,value,virtual,text,Options,action,<action,alias>,alias,action,that,should,executed,anytime,value,given,virtual,text,changes,command,<Tcl,command>,Tcl,command,proc,that,should,executed,anytime,value,given,virtual,text,changes,language,<Language,None>,language,set,virtual,text,language,None,not,specified,virtual,text,set,without,being,associated,with,language,object,<object,alias>,alias,object,set,virtual,text,option,used,set,text,property,specific,object,like,pane,action,value,<new,value>,value,set,virtual,text,variable,virtualtext,<virtual,text,name>,required,virtual,text,variable,name,set,without,Example,following,example,would,give,you,virtual,text,variable,Foo,that,set,Bar,could,then,accessed,<%Foo%>,from,within,InstallJammer,virtualtext,Foo,value,Bar[$XTITLE$]SetVirtualText[$XTITELEND$][$XKEYS$]Set,Virtual,Text[$XKEYSEND$]`;";
s[215] = "SubstVirtualText^SubstVirtualText.html^::InstallAPI::SubstVirtualTextGiven a string, substitute all virtual text out of the string and ...^SubstVirtualText^Given,string,substitute,all,virtual,text,out,string,return,substituted,string,Supported,Platforms,All,Returns,substituted,string,Options,virtualtext,<virtual,text,string>,required,virtual,text,string,substituted,Example,you,had,your,application,name,Application,Version,you,could,virtualtext,<%AppName%>,<%Version%>,which,would,Application,Virtual,Text[$XKEYSEND$]`;";
s[216] = "URLIsValid^URLIsValid.html^::InstallAPI::URLIsValidValidate whether a given URL is a valid URL that can be fetched.Su...^URLIsValid^Validate,whether,given,URL,valid,URL,that,can,fetched,Supported,Platforms,All,Returns,True,false,Options,proxyhost,<hostname>,host,name,proxy,server,use,for,request,proxyport,<port,number>,port,number,proxy,server,use,for,request,url,<URL>,URL,validate`;";
s[217] = "VirtualTextAPI^VirtualTextAPI.html^::InstallAPI::VirtualTextAPIThis API is used to manipulate and query virtual text in an installe...^VirtualTextAPI^API,used,manipulate,query,virtual,text,installer,uninstaller,Supported,Platforms,All,Returns,See,options,Options,Specifies,action,API,should,take,Possible,values,settype,Set,type,virtual,text,Type,affects,how,some,virtual,text,treated,within,installer,type,Specifies,type,assign,virtual,text,current,available,types,boolean,directory,boolean,type,means,that,value,saved,virtual,text,always,based,what,set,directory,type,means,that,virtual,text,automatically,converted,proper,representation,for,current,platform`;";
s[218] = "VirtualTextExists^VirtualTextExists.html^::InstallAPI::VirtualTextExistsCheck to see if the given virtual text variable exists in the giv...^VirtualTextExists^Check,see,given,virtual,text,variable,exists,given,language,Supported,Platforms,All,Returns,True,false,Options,language,<language,None>,language,passed,API,check,see,virtual,text,exists,that,language,language,passed,language,None,virtual,text,checked,language,neutral,messages,virtualtext,<virtual,text,string>,required,virtual,text,string,substituted`;";
s[219] = "Create a New Install Fast^CreateANewInstallFast.html^OverviewThis tutorial will walk you through the quick and dirty way to get started using Install...^Create a New Install Fast^Overview,tutorial,walk,you,through,quick,dirty,way,get,started,using,InstallJammer,with,new,install,time,flat,When,you're,finished,with,tutorial,you,have,new,install,project,for,your,application,that,built,for,platform,you're,running,install,builder,from,Follow,steps,below,you'll,off,running,Creating,Your,First,Install,Open,New,Project,Wizard,Type,your,Project,Name,InstallJammer,fill,Project,Directory,based,your,Project,Name,preferences,Click,Next,Fill,your,Application,Name,Short,Application,Name,Version,Company,Click,Next,Fill,your,Install,Version,Application,Executable,fields,that,InstallJammer,knows,how,execute,your,application,after,installing,Click,Next,Type,directory,where,your,application,stored,your,system,should,root,directory,your,application,Click,Finish,Done,You,have,just,built,your,install,project,Now,that,you,have,project,built,click,Build,Install,button,toolbar,from,Build,menu,InstallJammer,build,installer,for,your,application,you,entered,your,Application,Directory,properly,you,should,have,your,entire,application,now,packaged,convenient,installer,for,your,current,platform,Click,Test,Install,from,toolbar,from,Build,menu,test,your,new,installer,you,had,any,trouble,any,questions,please,read,through,Create,New,Install,Step,Step,New,Install,Fast[$XTITELEND$][$XKEYS$]Create,New,Install,Fast[$XKEYSEND$]`;";
s[220] = "Create a New Install Step-by-Step^CreateANewInstallStep-by-Step.html^OverviewThis tutorial will walk you, step-by-step, through creating your first installer using t...^Create a New Install Step-by-Step^Overview,tutorial,walk,you,step,step,through,creating,your,first,installer,using,InstallJammer,Install,Builder,process,very,easy,should,take,you,longer,than,few,minutes,You'll,have,your,first,installer,running,time,Creating,Your,First,Install,When,InstallJammer,first,loads,you,presented,with,Start,Page,that,shows,you,list,current,installers,you,have,built,Your,first,time,out,page,have,projects,let's,create,one,New,installs,created,InstallJammer,using,Install,Project,Wizard,You,can,open,wizard,either,clicking,New,Install,button,main,toolbar,opening,File,menu,clicking,New,clicking,either,these,options,you,should,now,presented,with,Install,Project,Wizard,InstallJammer,uses,wizard,guide,you,through,rest,new,install,process,Step,Project,Information,Step,wizard,asks,you,for,some,basic,project,information,information,all,internal,InstallJammer,tells,where,you,want,save,your,project,what,you,want,call,project,Project,Name,what,you,want,call,your,project,does,not,have,name,application,you,installing,but,would,make,sense,Project,Directory,directory,where,you,want,store,project,new,directory,created,store,your,install,InstallJammer,each,project,stored,its,own,directory,that,everything,can,contained,Step,Application,Strings,Step,wizard,asks,you,some,information,about,product,program,that,you,installing,Application,Name,name,your,application,product,Short,Application,Name,shortened,name,for,your,application,name,used,most,UNIX,systems,directory,usually,all,lowercase,with,spaces,Version,version,your,product,value,not,used,InstallJammer,for,anything,representation,your,software,person,installing,Company,name,your,company,organization,Step,Application,Information,Step,wizard,asks,for,few,more,pieces,information,about,your,application,Install,Version,version,used,internally,InstallJammer,way,track,version,your,software,against,future,versions,you,distribute,new,versions,your,software,with,version,incremented,field,InstallJammer,can,based,your,options,install,only,files,that,newer,version,More,later,Windows,Application,Executable,name,main,executable,for,your,application,Windows,entry,point,into,your,program,InstallJammer,uses,make,shortcuts,launch,your,application,from,within,installer,needed,UNIX,Application,Executable,name,main,executable,script,for,your,application,UNIX,environment,entry,point,into,your,program,InstallJammer,uses,make,shortcuts,launch,your,application,from,within,installer,needed,Step,Application,Location,Step,very,simple,step,that,asks,for,directory,that,your,application,adding,your,directory,your,application,start,with,entire,contents,directory,all,its,subdirectories,project,You,not,have,specify,directory,now,You,can,wait,until,you,get,started,building,rest,your,install,add,whatever,files,directories,you,want,later,Step,Theme,Selection,Step,gives,you,list,install,themes,choose,from,default,theme,Modern,Wizard,theme,Step,Platform,Selection,Step,presents,you,with,list,platforms,supported,your,installation,InstallJammer,asks,you,pick,which,ones,you,plan,install,You,need,only,pick,single,platform,for,your,installer,your,software,not,multiplatform,default,only,platform,you,building,selected,Not,selecting,platform,does,not,remove,platform,from,your,installer,only,disables,that,you,decide,add,more,platforms,future,you,can,easily,switch,needed,without,having,rebuild,your,install,project,Step,Additional,Features,Step,lets,you,select,some,additional,features,you,might,like,add,your,installer,Most,features,switched,default,they,common,most,installers,used,today,Allow,users,select,custom,components,your,install,feature,checked,InstallJammer,add,two,panes,your,installer,that,allow,user,select,Custom,install,option,then,select,custom,components,they,wish,install,from,your,product,only,important,you,have,many,components,your,install,you,want,user,able,choose,which,parts,they,install,Include,uninstaller,feature,checked,InstallJammer,add,action,your,install,actions,create,uninstaller,when,your,application,installed,Add,uninstaller,Windows,Programs,register,feature,checked,InstallJammer,add,action,your,install,actions,create,registry,entry,Windows',Programs,registry,means,your,customers,able,uninstall,your,program,from,main,Windows,Control,Panel,Add,Windows,Program,shortcut,action,for,uninstaller,feature,checked,InstallJammer,add,action,your,installer,create,Windows,shortcut,your,application's,Program,Folder,that,points,uninstaller,for,your,application,Add,Windows,Program,shortcut,action,for,application,feature,checked,InstallJammer,add,action,your,installer,create,Windows,shortcut,your,application's,Program,Folder,that,points,your,application,Program,Folder,automatically,created,for,your,application,does,not,already,exist,Add,View,Readme,checkbutton,feature,checked,InstallJammer,add,View,Readme,checkbutton,Setup,Complete,pane,your,installer,allow,user,view,your,README,file,before,exiting,installer,Add,Launch,Application,checkbutton,feature,checked,InstallJammer,add,checkbutton,Setup,Complete,pane,your,installer,allow,user,launch,your,application,before,exiting,installer,Add,Create,Desktop,Shortcut,checkbutton,feature,checked,InstallJammer,add,Create,Desktop,Shortcut,checkbutton,Setup,Complete,pane,your,installer,allow,user,create,shortcut,your,application,desktop,before,exiting,installer,Add,Create,Quick,Launch,checkbutton,feature,checked,InstallJammer,add,Create,Quick,Launch,Shortcut,checkbutton,Setup,Complete,pane,your,installer,allow,user,create,shortcut,your,application,quick,launch,toolbar,before,exiting,installer,Final,Step,Create,Install,Now,that,you,have,gone,through,all,steps,you're,ready,create,your,install,Click,finish,button,InstallJammer,create,your,install,open,get,you,started,Building,Your,Install,Now,you're,ready,build,your,installer,Click,Build,Install,button,toolbar,under,Build,menu,InstallJammer,build,installer,for,your,application,you,entered,all,your,data,correctly,you,should,end,with,installer,that,ready,Testing,Your,Installer,your,installer,built,successfully,you're,ready,give,test,Click,Test,Install,button,toolbar,under,Build,menu,Run,through,installer,your,program,should,install,default,location,Make,sure,you,don't,change,destination,directory,when,testing,your,installer,you,InstallJammer,can't,find,your,installed,application,test,uninstaller,Testing,Your,Uninstaller,Once,you,have,your,application,installed,it's,time,test,your,uninstaller,Click,Test,Uninstall,button,toolbar,under,Build,menu,InstallJammer,execute,uninstaller,that,was,created,when,your,application,was,installed,Run,through,uninstaller,delete,test,run,you,just,installed,New,Install,Step,Step[$XTITELEND$][$XKEYS$]Create,New,Install,Step,Step[$XKEYSEND$]`;";
s[221] = "What is Tcl/Tk?^WhatIsTclTk.html^Tcl (Tool Command Language) is a very powerful but easy to learn dynamic programming language, suita...^What is Tcl/Tk?^Tcl,Tool,Command,Language,very,powerful,but,easy,learn,dynamic,programming,language,suitable,for,very,wide,range,uses,including,web,desktop,applications,networking,administration,testing,many,more,Open,source,business,friendly,Tcl,mature,yet,evolving,language,that,truly,cross,platform,easily,deployed,highly,extensible,graphical,user,interface,toolkit,that,takes,developing,desktop,applications,higher,level,than,conventional,approaches,standard,GUI,not,only,for,Tcl,but,for,many,other,dynamic,languages,can,produce,rich,native,applications,that,run,unchanged,across,Windows,Mac,Linux,more,InstallJammer,written,almost,entirely,with,little,bit,help,from,some,extensions,written,Since,all,scripting,InstallJammer,done,through,might,helpful,for,you,learn,little,about,Tcl,you,plan,doing,any,kind,complex,operations,with,your,installer,Below,some,links,get,you,started,Why,would,choose,over,What,does,code,look,like,Full,Tcl,Tutorial[$XTITLE$]What`;";


var cookies = document.cookie;
var p = cookies.indexOf("d=");
if (p != -1) {
 var st = p + 2;
 var en = cookies.indexOf(";", st);
 if (en == -1) {
   en = cookies.length;
 }
 var d = cookies.substring(st, en);
d = unescape(d);
}
var od = d;
var m = 0;
if (d.charAt(0) == '"' && d.charAt(d.length - 1) == '"') {
 m = 1;
}
var r = new Array();
var co = 0;
if (m == 0) {
 var woin = new Array();
 var w = d.split(" ");
 for (var a = 0; a < w.length; a++) {
   woin[a] = 0;
   if (w[a].charAt(0) == '-') {
     woin[a] = 1;
   }
 }
for (var a = 0; a < w.length; a++) {
 w[a] = w[a].replace(/^\-|^\+/gi, "");
}
a = 0;
for (var c = 0; c < s.length; c++) {
 pa = 0;
 nh = 0;
 for (var i = 0; i < woin.length; i++) {
   if (woin[i] == 0) {
     nh++;
     var pat = new RegExp(w[i], "i");
     var rn = s[c].search(pat);
     if (rn >= 0) {
       pa++;
     } else {
       pa = 0;
     }
   }
     if (woin[i] == 1) {
       var pat = new RegExp(w[i], "i");
       var rn = s[c].search(pat);
       if (rn >= 0) {
         pa = 0;
       }
     }
   }
   if (pa == nh) {
     r[a] = s[c];
     a++;
   }
 }
 co = a;
}
if (m == 1) {
 d = d.replace(/"/gi, "");
 var a = 0;
 var pat = new RegExp(d, "i");
 for (var c = 0; c < s.length; c++) {
   var rn = s[c].search(pat);
   if (rn >= 0) {
     r[a] = s[c];
     a++;
   }
 }co = a;
}
function return_query() {
 document.jse_Form.d.value = od;
}
function num_jse() {
 document.write(co);
}
function out_jse() {
 if (co == 0) {
    document.write('Your search did not match any documents.<br>Please ensure that all keywords are spelled correctly.<br>Or try different or more general keywords. Thank you.');
   return;
   }
   for (var a = 0; a < r.length; a++) {
     var os = r[a].split("^");
     if (bold == 1 && m == 1) {
       var br = "<b>" + d + "</b>";
       os[2] = os[2].replace(pat, br);
     }
     if (include_num == 1) {
       document.write(a + 1, '. <a href="', os[1], '">', os[0], '</a><br>', os[2], '<p>');
     } else {document.write('<a href="', os[1], '">', os[0], '</a><br>', os[2], '<p>');
     }
   }
}
Added docs/html/FHSearchForm.js.
































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

// ---------- script properties ----------


var results_location = "FHSearchResults.html";


// ---------- end of script properties ----------


function search_form(jse_Form) {
	if (jse_Form.d.value.length > 0) {
		document.cookie = "d=" + escape(jse_Form.d.value);
		parent.content.location = results_location;
	}
}
Added docs/html/FHSearchResults.html.


















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- saved from url=(0014)about:internet -->
<html>
<head>
<title>SEARCH RESULTS</title>
<script language="JavaScript1.3" type="text/javascript" src="FHSearchForm.js"></script>
<script language="JavaScript1.3" type="text/javascript" src="FHSearch.js"></script>
<style type="text/css"><!-- body{font-size: 10pt; font-family: "Verdana"; color: #2E2E2E;} --></style></head>
<body bgcolor="#FFFFFF">

<!-- Find -->
<form name="jse_Form" onsubmit="search_form(jse_Form);return false">
<input type="text" name="d">
<input type="button" value="Go" onClick="search_form(jse_Form)">
</form>
<script language="JavaScript1.3" type="text/javascript">return_query()</script>
<!-- Mid -->
<script language="JavaScript1.3" type="text/javascript">num_jse()</script> page(s) found
<hr>
<p>
<script language="JavaScript1.3" type="text/javascript">
out_jse()
</script>
<p>&nbsp;
</body>
</html>
Added docs/html/FHTocParas.js.
































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* These are the parameters to define the appearance of the ToC. */
var
  showNumbers = false, 		// display the ordering strings: yes=true | no=false
  backColor = "#D1D1D1",		// background color of the ToC 
  normalColor = "#2E2E2E",	// text color of the ToC headlines
  lastVisitColor = "#2E2E2E",	// text color of the line last visited
  currentColor = "#FFFFFF",	// text color of the actual line just clicked on
  titleColor = "#2E2E2E",		// text color of the title "Table of Contents"
  mLevel = -1,					// number of levels minus 1 the headlines of which are presentet with large and bold fonts   
  textSizes = new Array(1.0, 0.8, 0.8, 1.0, 0.8),			// font-size factors for: [0] the title "Table of Contents", [1] larger and bold fonts [2] smaller fonts if MS Internet Explorer [3] larger and bold fonts [4] smaller fonts if Netscape Navigator.
  fontTitle = "Verdana", // font-family of the title "Table of Contents"
  fontLines = "Verdana", // font-family of the headings
  tocScroll=false,				// Automatic scrolling of the ToC frame (true) or not(false)
  tocBehaviour = new Array(2,2), // Indicates how the ToC shall change when clicking in the heading symbol (1st arg.) resp. in the heading text (2nd arg). Arg's meaning: 0 = No change, 1 = ToC changes with automatic collapsing, 2 = ToC changes with no automatic collapsing.
  tocLinks = new Array(1,0);	// Indicates wether the content's location shall be changed when clicking in the heading symbol (1st arg.) resp. in the heading text (2nd arg). Arg's meaning: 1 = No, 0 = Yes. 
	
Added docs/html/FHTocTab.js.
























































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
var tocTab = new Array();var ir=0;
tocTab[ir++] = new Array ("Top", "Contents", "Welcome.html", "", "");
tocTab[ir++] = new Array ("0", "InstallJammer 1.2 User Guide", "", "10001", "InstallJammer10UserGuide");
tocTab[ir++] = new Array ("0.0", "Welcome", "Welcome.html", "10002", "Welcome");
tocTab[ir++] = new Array ("0.1", "License", "License.html", "10003", "License");
tocTab[ir++] = new Array ("0.2", "Credits", "Credits.html", "10004", "Credits");
tocTab[ir++] = new Array ("0.3", "Release Notes", "ReleaseNotes.html", "10005", "ReleaseNotes");
tocTab[ir++] = new Array ("0.3.0", "1.2.14", "1214.html", "10283", "1214");
tocTab[ir++] = new Array ("0.3.1", "1.2.13", "1213.html", "10282", "1213");
tocTab[ir++] = new Array ("0.3.2", "1.2.12", "1212.html", "10266", "1212");
tocTab[ir++] = new Array ("0.3.3", "1.2.11", "1211.html", "10265", "1211");
tocTab[ir++] = new Array ("0.3.4", "1.2.10", "1210.html", "10264", "1210");
tocTab[ir++] = new Array ("0.3.5", "1.2.10b1", "1210b1.html", "10259", "1210b1");
tocTab[ir++] = new Array ("0.3.6", "1.2.9", "129.html", "10258", "129");
tocTab[ir++] = new Array ("0.3.7", "1.2.8", "128.html", "10257", "128");
tocTab[ir++] = new Array ("0.3.8", "1.2.7", "127.html", "10256", "127");
tocTab[ir++] = new Array ("0.3.9", "1.2.6", "126.html", "10255", "126");
tocTab[ir++] = new Array ("0.3.10", "1.2.5", "125.html", "10246", "125");
tocTab[ir++] = new Array ("0.3.11", "1.2.4", "124.html", "10243", "124");
tocTab[ir++] = new Array ("0.3.12", "1.2.3", "123.html", "10234", "123");
tocTab[ir++] = new Array ("0.3.13", "1.2.2", "122.html", "10233", "122");
tocTab[ir++] = new Array ("0.3.14", "1.2.1", "121.html", "10232", "121");
tocTab[ir++] = new Array ("0.3.15", "1.2", "12.html", "10231", "12");
tocTab[ir++] = new Array ("0.3.16", "1.2b2", "12b2.html", "10230", "12b2");
tocTab[ir++] = new Array ("0.3.17", "1.2b1", "12b1.html", "10215", "12b1");
tocTab[ir++] = new Array ("0.3.18", "1.1 Releases", "", "10211", "11Releases");
tocTab[ir++] = new Array ("0.3.18.0", "1.1.2", "112.html", "10212", "112");
tocTab[ir++] = new Array ("0.3.18.1", "1.1", "11.html", "10210", "11");
tocTab[ir++] = new Array ("0.3.18.2", "1.1b2", "11b2.html", "10209", "11b2");
tocTab[ir++] = new Array ("0.3.18.3", "1.1b1", "11b1.html", "10208", "11b1");
tocTab[ir++] = new Array ("0.3.19", "1.0 Releases", "", "10185", "10Releases");
tocTab[ir++] = new Array ("0.3.19.0", "1.0.4", "104.html", "10184", "104");
tocTab[ir++] = new Array ("0.3.19.1", "1.0.3", "103.html", "10148", "103");
tocTab[ir++] = new Array ("0.3.19.2", "1.0.2", "102.html", "10133", "102");
tocTab[ir++] = new Array ("0.3.19.3", "1.0.1", "101.html", "10132", "101");
tocTab[ir++] = new Array ("0.3.19.4", "1.0", "10.html", "10131", "10");
tocTab[ir++] = new Array ("0.3.19.5", "1.0rc3", "10rc3.html", "10130", "10rc3");
tocTab[ir++] = new Array ("0.3.19.6", "1.0rc1", "10rc1.html", "10129", "10rc1");
tocTab[ir++] = new Array ("0.3.19.7", "1.0b2", "10b2.html", "10128", "10b2");
tocTab[ir++] = new Array ("0.3.19.8", "1.0b1", "10b1.html", "10127", "10b1");
tocTab[ir++] = new Array ("1", "InstallJammer Help", "", "10006", "InstallJammerHelp");
tocTab[ir++] = new Array ("1.0", "Getting Started", "GettingStarted.html", "10007", "GettingStarted");
tocTab[ir++] = new Array ("1.1", "Frequently Asked Questions", "FrequentlyAskedQuestions.html", "10201", "FrequentlyAskedQuestions");
tocTab[ir++] = new Array ("1.2", "The Install Builder", "", "10008", "TheInstallBuilder");
tocTab[ir++] = new Array ("1.2.0", "Getting to Know the Install Builder", "GettingToKnowTheInstallBuilder.html", "10009", "GettingToKnowTheInstallBuilder");
tocTab[ir++] = new Array ("1.2.1", "Install Builder Preferences", "InstallBuilderPreferences.html", "10010", "InstallBuilderPreferences");
tocTab[ir++] = new Array ("1.2.2", "Install Builder Command Line Options", "Command-LineOptions.html", "10011", "Command-LineOptions");
tocTab[ir++] = new Array ("1.2.3", "General Information", "", "10016", "GeneralInformation");
tocTab[ir++] = new Array ("1.2.3.0", "Application Information", "ApplicationInformation.html", "10017", "ApplicationInformation");
tocTab[ir++] = new Array ("1.2.3.1", "Platform Information", "PlatformInformation.html", "10018", "PlatformInformation");
tocTab[ir++] = new Array ("1.2.3.2", "Package and Archive Information", "PackageAndArchiveInformation.html", "10182", "PackageAndArchiveInformation");
tocTab[ir++] = new Array ("1.2.4", "Components and Files", "", "10019", "ComponentsAndFiles");
tocTab[ir++] = new Array ("1.2.4.0", "Groups and Files", "GroupsAndFiles.html", "10020", "GroupsAndFiles");
tocTab[ir++] = new Array ("1.2.4.1", "Files and Directories", "FilesAndDirectories.html", "10126", "FilesAndDirectories");
tocTab[ir++] = new Array ("1.2.4.2", "Components", "Components.html", "10021", "Components");
tocTab[ir++] = new Array ("1.2.4.3", "Setup Types", "SetupTypes.html", "10022", "SetupTypes");
tocTab[ir++] = new Array ("1.2.5", "User Interface and Events", "", "10023", "UserInterfaceAndEvents");
tocTab[ir++] = new Array ("1.2.5.0", "Panes and Actions", "PanesAndActions.html", "10024", "PanesAndActions");
tocTab[ir++] = new Array ("1.2.5.1", "Command Line Options", "CommandLineOptions.html", "10156", "CommandLineOptions");
tocTab[ir++] = new Array ("1.2.6", "Virtual Definitions", "", "10026", "VirtualDefinitions");
tocTab[ir++] = new Array ("1.2.6.0", "Virtual Text", "VirtualText.html", "10027", "VirtualText");
tocTab[ir++] = new Array ("1.2.7", "Run Disk Builder", "", "10028", "RunDiskBuilder");
tocTab[ir++] = new Array ("1.2.7.0", "Disk Builder", "DiskBuilder.html", "10030", "DiskBuilder");
tocTab[ir++] = new Array ("1.2.8", "Test the Installation", "", "10029", "TestTheInstallation");
tocTab[ir++] = new Array ("1.2.8.0", "Test Installer", "TestRun.html", "10031", "TestRun");
tocTab[ir++] = new Array ("1.2.8.1", "Test Uninstaller", "TestUninstaller.html", "10183", "TestUninstaller");
tocTab[ir++] = new Array ("1.3", "Objects", "", "10012", "Objects");
tocTab[ir++] = new Array ("1.3.0", "Object Types", "ObjectTypes.html", "10013", "ObjectTypes");
tocTab[ir++] = new Array ("1.3.1", "Standard Properties", "StandardProperties.html", "10014", "StandardProperties");
tocTab[ir++] = new Array ("1.4", "Panes", "", "10032", "Panes");
tocTab[ir++] = new Array ("1.4.0", "What are Panes?", "WhatArePanes.html", "10033", "WhatArePanes");
tocTab[ir++] = new Array ("1.5", "Actions", "", "10043", "Actions");
tocTab[ir++] = new Array ("1.5.0", "What are Actions?", "WhatAreActions.html", "10044", "WhatAreActions");
tocTab[ir++] = new Array ("1.5.1", "What are Action Groups?", "WhatAreActionGroups.html", "10059", "WhatAreActionGroups");
tocTab[ir++] = new Array ("1.5.2", "Standard Action Properties", "ActionStandardProperties.html", "10060", "ActionStandardProperties");
tocTab[ir++] = new Array ("1.5.3", "Console Actions", "", "10159", "ConsoleActions");
tocTab[ir++] = new Array ("1.5.3.0", "Console Ask Yes or No", "ConsoleAskYesOrNo.html", "10160", "ConsoleAskYesOrNo");
tocTab[ir++] = new Array ("1.5.3.1", "Console Clear Screen", "ConsoleClearScreen.html", "10161", "ConsoleClearScreen");
tocTab[ir++] = new Array ("1.5.3.2", "Console Get User Input", "ConsoleGetUserInput.html", "10162", "ConsoleGetUserInput");
tocTab[ir++] = new Array ("1.5.3.3", "Console Message", "ConsoleMessage.html", "10163", "ConsoleMessage");
tocTab[ir++] = new Array ("1.5.3.4", "Console Pause", "ConsolePause.html", "10164", "ConsolePause");
tocTab[ir++] = new Array ("1.5.4", "Execute Actions", "", "10061", "ExecuteActions");
tocTab[ir++] = new Array ("1.5.4.0", "Execute Action", "ExecuteAction.html", "10081", "ExecuteAction");
tocTab[ir++] = new Array ("1.5.4.1", "Execute External Program", "ExecuteExternalProgram.html", "10082", "ExecuteExternalProgram");
tocTab[ir++] = new Array ("1.5.4.2", "Execute Script", "ExecuteScript.html", "10083", "ExecuteScript");
tocTab[ir++] = new Array ("1.5.5", "File Actions", "", "10134", "FileActions");
tocTab[ir++] = new Array ("1.5.5.0", "Adjust Line Feeds", "AdjustLineFeeds.html", "10135", "AdjustLineFeeds");
tocTab[ir++] = new Array ("1.5.5.1", "Backup File", "BackupFile.html", "10136", "BackupFile");
tocTab[ir++] = new Array ("1.5.5.2", "Change File Ownership", "ChangeFileOwnership.html", "10137", "ChangeFileOwnership");
tocTab[ir++] = new Array ("1.5.5.3", "Change File Permissions", "ChangeFilePermissions.html", "10138", "ChangeFilePermissions");
tocTab[ir++] = new Array ("1.5.5.4", "Copy File", "CopyFile.html", "10147", "CopyFile");
tocTab[ir++] = new Array ("1.5.5.5", "Create File Link", "CreateFileLink.html", "10139", "CreateFileLink");
tocTab[ir++] = new Array ("1.5.5.6", "Create Folder", "CreateFolder.html", "10085", "CreateFolder");
tocTab[ir++] = new Array ("1.5.5.7", "Delete File", "DeleteFile.html", "10140", "DeleteFile");
tocTab[ir++] = new Array ("1.5.5.8", "Read File Into Virtual Text", "ReadFileIntoVirtualText.html", "10141", "ReadFileIntoVirtualText");
tocTab[ir++] = new Array ("1.5.5.9", "Rename File", "RenameFile.html", "10142", "RenameFile");
tocTab[ir++] = new Array ("1.5.5.10", "Replace Text in File", "ReplaceTextInFile.html", "10143", "ReplaceTextInFile");
tocTab[ir++] = new Array ("1.5.5.11", "Write Text to File", "WriteTextToFile.html", "10144", "WriteTextToFile");
tocTab[ir++] = new Array ("1.5.5.12", "Unzip File", "UnzipFile.html", "10213", "UnzipFile");
tocTab[ir++] = new Array ("1.5.6", "General Actions", "", "10062", "GeneralActions");
tocTab[ir++] = new Array ("1.5.6.0", "Continue Install", "ContinueInstall.html", "10084", "ContinueInstall");
tocTab[ir++] = new Array ("1.5.6.1", "Exit", "Exit.html", "10086", "Exit");
tocTab[ir++] = new Array ("1.5.6.2", "Fetch URL", "FetchURL.html", "10165", "FetchURL");
tocTab[ir++] = new Array ("1.5.6.3", "Generate UID", "GenerateUID.html", "10166", "GenerateUID");
tocTab[ir++] = new Array ("1.5.6.4", "Launch File", "LaunchFile.html", "10167", "LaunchFile");
tocTab[ir++] = new Array ("1.5.6.5", "Launch Web Browser", "LaunchWebBrowser.html", "10112", "LaunchWebBrowser");
tocTab[ir++] = new Array ("1.5.6.6", "Log Debug Message", "LogDebugMessage.html", "10149", "LogDebugMessage");
tocTab[ir++] = new Array ("1.5.6.7", "Message Box", "MessageBox.html", "10087", "MessageBox");
tocTab[ir++] = new Array ("1.5.6.8", "Message Panel", "MessagePanel.html", "10088", "MessagePanel");
tocTab[ir++] = new Array ("1.5.6.9", "Modify Object", "ModifyObject.html", "10150", "ModifyObject");
tocTab[ir++] = new Array ("1.5.6.10", "Pause Install", "PauseInstall.html", "10089", "PauseInstall");
tocTab[ir++] = new Array ("1.5.6.11", "Set Object Property", "SetObjectProperty.html", "10223", "SetObjectProperty");
tocTab[ir++] = new Array ("1.5.6.12", "Set Virtual Text", "SetVirtualText.html", "10121", "SetVirtualText");
tocTab[ir++] = new Array ("1.5.6.13", "Stop Install", "StopInstall.html", "10090", "StopInstall");
tocTab[ir++] = new Array ("1.5.6.14", "Text Window", "TextWindow.html", "10091", "TextWindow");
tocTab[ir++] = new Array ("1.5.6.15", "Wait", "Wait.html", "10124", "Wait");
tocTab[ir++] = new Array ("1.5.7", "Install Actions", "", "10063", "InstallActions");
tocTab[ir++] = new Array ("1.5.7.0", "Add Install Info", "AddInstallInfo.html", "10168", "AddInstallInfo");
tocTab[ir++] = new Array ("1.5.7.1", "Add Response File Info", "AddResponseFileInfo.html", "10277", "AddResponseFileInfo");
tocTab[ir++] = new Array ("1.5.7.2", "Add to Uninstall", "AddToUninstall.html", "10092", "AddToUninstall");
tocTab[ir++] = new Array ("1.5.7.3", "Check for Previous Install", "CheckForPreviousInstall.html", "10113", "CheckForPreviousInstall");
tocTab[ir++] = new Array ("1.5.7.4", "Get Previous Install Info", "GetPreviousInstallInfo.html", "10186", "GetPreviousInstallInfo");
tocTab[ir++] = new Array ("1.5.7.5", "Install Log File", "InstallLogFile.html", "10093", "InstallLogFile");
tocTab[ir++] = new Array ("1.5.7.6", "Install Selected Files", "InstallSelectedFiles.html", "10094", "InstallSelectedFiles");
tocTab[ir++] = new Array ("1.5.7.7", "Install Uninstaller", "InstallUninstaller.html", "10095", "InstallUninstaller");
tocTab[ir++] = new Array ("1.5.7.8", "Install Wish Binary", "InstallWishBinary.html", "10115", "InstallWishBinary");
tocTab[ir++] = new Array ("1.5.7.9", "Install Wrapped Script", "InstallWrappedScript.html", "10116", "InstallWrappedScript");
tocTab[ir++] = new Array ("1.5.7.10", "Unpack Stored File", "UnpackStoredFile.html", "10117", "UnpackStoredFile");
tocTab[ir++] = new Array ("1.5.8", "Java Actions", "", "10118", "JavaActions");
tocTab[ir++] = new Array ("1.5.8.0", "Get Java Property", "GetJavaProperty.html", "10119", "GetJavaProperty");
tocTab[ir++] = new Array ("1.5.8.1", "Locate Java Runtime", "LocateJavaRuntime.html", "10120", "LocateJavaRuntime");
tocTab[ir++] = new Array ("1.5.9", "Shortcut Actions", "", "10157", "ShortcutActions");
tocTab[ir++] = new Array ("1.5.9.0", "Install Desktop Shortcut", "InstallDesktopShortcut.html", "10114", "InstallDesktopShortcut");
tocTab[ir++] = new Array ("1.5.9.1", "Install Program Folder Shortcut", "InstallProgramFolderShortcut.html", "10158", "InstallProgramFolderShortcut");
tocTab[ir++] = new Array ("1.5.9.2", "Install UNIX Program Folder", "InstallUNIXProgramFolder.html", "10278", "InstallUNIXProgramFolder");
tocTab[ir++] = new Array ("1.5.9.3", "Install UNIX Shortcut", "InstallUNIXShortcut.html", "10096", "InstallUNIXShortcut");
tocTab[ir++] = new Array ("1.5.9.4", "Install Windows Shortcut", "InstallWindowsShortcut.html", "10097", "InstallWindowsShortcut");
tocTab[ir++] = new Array ("1.5.10", "System Actions", "", "10151", "SystemActions");
tocTab[ir++] = new Array ("1.5.10.0", "Add Directory to Path", "AddDirectoryToPath.html", "10152", "AddDirectoryToPath");
tocTab[ir++] = new Array ("1.5.10.1", "Add Environment Variable", "AddEnvironmentVariable.html", "10224", "AddEnvironmentVariable");
tocTab[ir++] = new Array ("1.5.10.2", "Delete Environment Variable", "DeleteEnvironmentVariable.html", "10225", "DeleteEnvironmentVariable");
tocTab[ir++] = new Array ("1.5.10.3", "Reboot or Shutdown System", "RebootOrShutdownSystem.html", "10169", "RebootOrShutdownSystem");
tocTab[ir++] = new Array ("1.5.10.4", "Register Package", "RegisterPackage.html", "10170", "RegisterPackage");
tocTab[ir++] = new Array ("1.5.10.5", "Remove Directory from Path", "RemoveDirectoryFromPath.html", "10153", "RemoveDirectoryFromPath");
tocTab[ir++] = new Array ("1.5.11", "Uninstall Actions", "", "10064", "UninstallActions");
tocTab[ir++] = new Array ("1.5.11.0", "Uninstall Leftover Files", "UninstallLeftoverFiles.html", "10098", "UninstallLeftoverFiles");
tocTab[ir++] = new Array ("1.5.11.1", "Uninstall Selected Files", "UninstallSelectedFiles.html", "10099", "UninstallSelectedFiles");
tocTab[ir++] = new Array ("1.5.12", "Windows Actions", "", "10271", "WindowsActions");
tocTab[ir++] = new Array ("1.5.12.0", "Disable Wow64 Redirection", "DisableWow64Redirection.html", "10272", "DisableWow64Redirection");
tocTab[ir++] = new Array ("1.5.12.1", "Revert Wow64 Redirection", "RevertWow64Redirection.html", "10273", "RevertWow64Redirection");
tocTab[ir++] = new Array ("1.5.13", "Windows Registry Actions", "", "10065", "WindowsRegistryActions");
tocTab[ir++] = new Array ("1.5.13.0", "Add Windows File Command", "AddWindowsFileCommand.html", "10100", "AddWindowsFileCommand");
tocTab[ir++] = new Array ("1.5.13.1", "Add Windows File Extension", "AddWindowsFileExtension.html", "10101", "AddWindowsFileExtension");
tocTab[ir++] = new Array ("1.5.13.2", "Add Windows File Type", "AddWindowsFileType.html", "10102", "AddWindowsFileType");
tocTab[ir++] = new Array ("1.5.13.3", "Add Windows Registry Key", "AddWindowsRegistryKey.html", "10103", "AddWindowsRegistryKey");
tocTab[ir++] = new Array ("1.5.13.4", "Add Windows Uninstall Entry", "AddWindowsUninstallEntry.html", "10104", "AddWindowsUninstallEntry");
tocTab[ir++] = new Array ("1.5.13.5", "Import Windows Registry File", "ImportWindowsRegistryFile.html", "10171", "ImportWindowsRegistryFile");
tocTab[ir++] = new Array ("1.5.13.6", "Register Windows Library", "RegisterWindowsLibrary.html", "10244", "RegisterWindowsLibrary");
tocTab[ir++] = new Array ("1.5.13.7", "Remove Windows Registry Key", "RemoveWindowsRegistryKey.html", "10172", "RemoveWindowsRegistryKey");
tocTab[ir++] = new Array ("1.5.13.8", "Unregister Windows Library", "UnregisterWindowsLibrary.html", "10245", "UnregisterWindowsLibrary");
tocTab[ir++] = new Array ("1.5.14", "Windows Service Actions", "", "10235", "WindowsServiceActions");
tocTab[ir++] = new Array ("1.5.14.0", "Continue Windows Service", "ContinueWindowsService.html", "10236", "ContinueWindowsService");
tocTab[ir++] = new Array ("1.5.14.1", "Create Windows Service", "CreateWindowsService.html", "10237", "CreateWindowsService");
tocTab[ir++] = new Array ("1.5.14.2", "Delete Windows Service", "DeleteWindowsService.html", "10238", "DeleteWindowsService");
tocTab[ir++] = new Array ("1.5.14.3", "Pause Windows Service", "PauseWindowsService.html", "10239", "PauseWindowsService");
tocTab[ir++] = new Array ("1.5.14.4", "Start Windows Service", "StartWindowsService.html", "10240", "StartWindowsService");
tocTab[ir++] = new Array ("1.5.14.5", "Stop Windows Service", "StopWindowsService.html", "10241", "StopWindowsService");
tocTab[ir++] = new Array ("1.5.15", "Wizard Actions", "", "10067", "WizardActions");
tocTab[ir++] = new Array ("1.5.15.0", "Add Pane to Order", "AddPaneToOrder.html", "10155", "AddPaneToOrder");
tocTab[ir++] = new Array ("1.5.15.1", "Add Widget", "AddWidget.html", "10105", "AddWidget");
tocTab[ir++] = new Array ("1.5.15.2", "Append Text to Widget", "AppendTextToWidget.html", "10263", "AppendTextToWidget");
tocTab[ir++] = new Array ("1.5.15.3", "Create Install Panes", "CreateInstallPanes.html", "10106", "CreateInstallPanes");
tocTab[ir++] = new Array ("1.5.15.4", "Destroy Widget", "DestroyWidget.html", "10107", "DestroyWidget");
tocTab[ir++] = new Array ("1.5.15.5", "Focus On Widget", "FocusOnWidget.html", "10108", "FocusOnWidget");
tocTab[ir++] = new Array ("1.5.15.6", "Modify Widget", "ModifyWidget.html", "10109", "ModifyWidget");
tocTab[ir++] = new Array ("1.5.15.7", "Move Forward", "MoveForward.html", "10110", "MoveForward");
tocTab[ir++] = new Array ("1.5.15.8", "Move to Pane", "MoveToPane.html", "10111", "MoveToPane");
tocTab[ir++] = new Array ("1.5.15.9", "Populate Components", "PopulateComponents.html", "10199", "PopulateComponents");
tocTab[ir++] = new Array ("1.5.15.10", "Populate Setup Types", "PopulateSetupTypes.html", "10200", "PopulateSetupTypes");
tocTab[ir++] = new Array ("1.5.15.11", "Remove Pane from Order", "RemovePaneFromOrder.html", "10154", "RemovePaneFromOrder");
tocTab[ir++] = new Array ("1.6", "Conditions", "", "10045", "Conditions");
tocTab[ir++] = new Array ("1.6.0", "What are Conditions?", "WhatAreConditions.html", "10049", "WhatAreConditions");
tocTab[ir++] = new Array ("1.6.1", "Standard Condition Properties", "ConditionStandardProperties.html", "10125", "ConditionStandardProperties");
tocTab[ir++] = new Array ("1.6.2", "File Conditions", "", "10068", "FileConditions");
tocTab[ir++] = new Array ("1.6.2.0", "File Exists Condition", "FileExistsCondition.html", "10122", "FileExistsCondition");
tocTab[ir++] = new Array ("1.6.2.1", "File Name Test Condition", "FileNameTestCondition.html", "10250", "FileNameTestCondition");
tocTab[ir++] = new Array ("1.6.2.2", "File Permission Condition", "FilePermissionCondition.html", "10076", "FilePermissionCondition");
tocTab[ir++] = new Array ("1.6.3", "General Conditions", "", "10069", "GeneralConditions");
tocTab[ir++] = new Array ("1.6.3.0", "Command Line Test Condition", "CommandLineTestCondition.html", "10229", "CommandLineTestCondition");
tocTab[ir++] = new Array ("1.6.3.1", "Execute Script Condition", "ExecuteScriptCondition.html", "10207", "ExecuteScriptCondition");
tocTab[ir++] = new Array ("1.6.3.2", "Object Test Condition", "ObjectIsActiveCondition.html", "10177", "ObjectIsActiveCondition");
tocTab[ir++] = new Array ("1.6.3.3", "Script Condition", "ScriptCondition.html", "10077", "ScriptCondition");
tocTab[ir++] = new Array ("1.6.3.4", "Virtual Text Test Condition", "VirtualTextTestCondition.html", "10178", "VirtualTextTestCondition");
tocTab[ir++] = new Array ("1.6.4", "Platform Conditions", "", "10070", "PlatformConditions");
tocTab[ir++] = new Array ("1.6.4.0", "Platform Condition", "PlatformCondition.html", "10078", "PlatformCondition");
tocTab[ir++] = new Array ("1.6.5", "String Conditions", "", "10072", "StringConditions");
tocTab[ir++] = new Array ("1.6.5.0", "String Equal Condition", "StringEqualCondition.html", "10079", "StringEqualCondition");
tocTab[ir++] = new Array ("1.6.5.1", "String Is Condition", "StringIsCondition.html", "10123", "StringIsCondition");
tocTab[ir++] = new Array ("1.6.5.2", "String Match Condition", "StringMatchCondition.html", "10080", "StringMatchCondition");
tocTab[ir++] = new Array ("1.6.6", "System Conditions", "", "10073", "SystemConditions");
tocTab[ir++] = new Array ("1.6.6.0", "Env Variable Test Condition", "EnvironmentVariableTestCondition.html", "10179", "EnvironmentVariableTestCondition");
tocTab[ir++] = new Array ("1.6.6.1", "Package Test Condition", "PackageTestCondition.html", "10180", "PackageTestCondition");
tocTab[ir++] = new Array ("1.6.6.2", "Port Test Condition", "PortTestCondition.html", "10181", "PortTestCondition");
tocTab[ir++] = new Array ("1.6.7", "User Input Conditions", "", "10074", "UserInputConditions");
tocTab[ir++] = new Array ("1.6.7.0", "Ask Yes or No", "AskYesOrNo.html", "10075", "AskYesOrNo");
tocTab[ir++] = new Array ("1.6.8", "Windows Conditions", "", "10173", "WindowsConditions");
tocTab[ir++] = new Array ("1.6.8.0", "File Extension Test Condition", "FileExtensionExistsCondition.html", "10174", "FileExtensionExistsCondition");
tocTab[ir++] = new Array ("1.6.8.1", "File Type Test Condition", "FileTypeExistsCondition.html", "10175", "FileTypeExistsCondition");
tocTab[ir++] = new Array ("1.6.8.2", "Registry Test Condition", "RegistryEntryExistsCondition.html", "10176", "RegistryEntryExistsCondition");
tocTab[ir++] = new Array ("1.6.8.3", "Windows Service Test Condition", "WindowsServiceTestCondition.html", "10242", "WindowsServiceTestCondition");
tocTab[ir++] = new Array ("1.7", "Virtual Text", "", "10047", "VirtualText1");
tocTab[ir++] = new Array ("1.7.0", "What is Virtual Text?", "WhatIsVirtualText.html", "10050", "WhatIsVirtualText");
tocTab[ir++] = new Array ("1.7.1", "Virtual Text Definitions", "VirtualTextDefinitions.html", "10051", "VirtualTextDefinitions");
tocTab[ir++] = new Array ("1.7.2", "Virtual Directory Definitions", "VirtualDirectoryDefinitions.html", "10052", "VirtualDirectoryDefinitions");
tocTab[ir++] = new Array ("2", "Developer's Guide", "", "10187", "DevelopersGuide");
tocTab[ir++] = new Array ("2.0", "Debugging an Install", "DebuggingAnInstall.html", "10188", "DebuggingAnInstall");
tocTab[ir++] = new Array ("2.1", "Builder API", "", "10216", "BuilderAPI");
tocTab[ir++] = new Array ("2.1.0", "What is the Builder API?", "WhatIsTheBuilderAPI.html", "10217", "WhatIsTheBuilderAPI");
tocTab[ir++] = new Array ("2.1.1", "Builder API Calls", "", "10218", "BuilderAPICalls");
tocTab[ir++] = new Array ("2.1.1.0", "GetAction", "GetAction.html", "10219", "GetAction");
tocTab[ir++] = new Array ("2.1.1.1", "GetActionGroup", "GetActionGroup.html", "10220", "GetActionGroup");
tocTab[ir++] = new Array ("2.1.1.2", "ModifyObject", "ModifyObject1.html", "10221", "ModifyObject1");
tocTab[ir++] = new Array ("2.1.1.3", "SetPlatformProperty", "SetPlatformProperty.html", "10222", "SetPlatformProperty");
tocTab[ir++] = new Array ("2.2", "Install API", "", "10189", "TheInstallAPI");
tocTab[ir++] = new Array ("2.2.0", "What is the Install API?", "WhatIsTheInstallAPI.html", "10198", "WhatIsTheInstallAPI");
tocTab[ir++] = new Array ("2.2.1", "Install API Calls", "", "10197", "InstallAPIProcs");
tocTab[ir++] = new Array ("2.2.1.0", "AddInstallInfo", "AddInstallInfo1.html", "10268", "AddInstallInfo1");
tocTab[ir++] = new Array ("2.2.1.1", "AddLanguage", "AddLanguage.html", "10247", "AddLanguage");
tocTab[ir++] = new Array ("2.2.1.2", "CommandLineAPI", "CommandLineAPI.html", "10275", "CommandLineAPI");
tocTab[ir++] = new Array ("2.2.1.3", "ComponentAPI", "ComponentAPI.html", "10276", "ComponentAPI");
tocTab[ir++] = new Array ("2.2.1.4", "ConfigAPI", "ConfigAPI.html", "10281", "ConfigAPI");
tocTab[ir++] = new Array ("2.2.1.5", "CopyObject", "CopyObject.html", "10261", "CopyObject");
tocTab[ir++] = new Array ("2.2.1.6", "ErrorMessage", "ErrorMessage.html", "10226", "ErrorMessage");
tocTab[ir++] = new Array ("2.2.1.7", "DestroyWidget", "DestroyWidget1.html", "10267", "DestroyWidget1");
tocTab[ir++] = new Array ("2.2.1.8", "Exit", "Exit1.html", "10254", "Exit1");
tocTab[ir++] = new Array ("2.2.1.9", "Fetch URL", "FetchURL1.html", "10214", "FetchURL1");
tocTab[ir++] = new Array ("2.2.1.10", "PropertyFileAPI", "PropertyFileAPI.html", "10285", "PropertyFileAPI");
tocTab[ir++] = new Array ("2.2.1.11", "FindProcesses", "FindProcesses.html", "10190", "FindProcesses");
tocTab[ir++] = new Array ("2.2.1.12", "GetComponentsForSetupType", "GetComponentsForSetupType.html", "10203", "GetComponentsForSetupType");
tocTab[ir++] = new Array ("2.2.1.13", "GetInstallSize", "GetInstallSize.html", "10204", "GetInstallSize");
tocTab[ir++] = new Array ("2.2.1.14", "GetSelectedFiles", "GetSelectedFiles.html", "10191", "GetSelectedFiles");
tocTab[ir++] = new Array ("2.2.1.15", "GetSystemPackageManager", "GetSystemPackageManager.html", "10192", "GetSystemPackageManager");
tocTab[ir++] = new Array ("2.2.1.16", "GetWidgetChildren", "GetWidgetChildren.html", "10251", "GetWidgetChildren");
tocTab[ir++] = new Array ("2.2.1.17", "GetWidgetPath", "GetWidgetPath.html", "10252", "GetWidgetPath");
tocTab[ir++] = new Array ("2.2.1.18", "EnvironmentVariableExists", "EnvironmentVariableExists.html", "10193", "EnvironmentVariableExists");
tocTab[ir++] = new Array ("2.2.1.19", "FindObjects", "FindObjects.html", "10249", "FindObjects");
tocTab[ir++] = new Array ("2.2.1.20", "LanguageAPI", "LanguageAPI.html", "10280", "LanguageAPI");
tocTab[ir++] = new Array ("2.2.1.21", "LoadMessageCatalog", "LoadMessageCatalog.html", "10248", "LoadMessageCatalog");
tocTab[ir++] = new Array ("2.2.1.22", "PromptForDirectory", "PromptForDirectory.html", "10205", "PromptForDirectory");
tocTab[ir++] = new Array ("2.2.1.23", "PromptForFile", "PromptForFile.html", "10206", "PromptForFile");
tocTab[ir++] = new Array ("2.2.1.24", "ReadInstallInfo", "ReadInstallInfo.html", "10269", "ReadInstallInfo");
tocTab[ir++] = new Array ("2.2.1.25", "ResponseFileAPI", "ResponseFileAPI.html", "10274", "ResponseFileAPI");
tocTab[ir++] = new Array ("2.2.1.26", "RollbackInstall", "RollbackInstall.html", "10260", "RollbackInstall");
tocTab[ir++] = new Array ("2.2.1.27", "SetActiveSetupType", "SetActiveSetupType.html", "10202", "SetActiveSetupType");
tocTab[ir++] = new Array ("2.2.1.28", "SetExitCode", "SetExitCode.html", "10262", "SetExitCode");
tocTab[ir++] = new Array ("2.2.1.29", "SetFileTypeEOL", "SetFileTypeEOL.html", "10253", "SetFileTypeEOL");
tocTab[ir++] = new Array ("2.2.1.30", "SetObjectProperty", "SetObjectProperty1.html", "10227", "SetObjectProperty1");
tocTab[ir++] = new Array ("2.2.1.31", "SetVirtualText", "SetVirtualText1.html", "10194", "SetVirtualText1");
tocTab[ir++] = new Array ("2.2.1.32", "SubstVirtualText", "SubstVirtualText.html", "10195", "SubstVirtualText");
tocTab[ir++] = new Array ("2.2.1.33", "URLIsValid", "URLIsValid.html", "10228", "URLIsValid");
tocTab[ir++] = new Array ("2.2.1.34", "VirtualTextAPI", "VirtualTextAPI.html", "10279", "VirtualTextAPI");
tocTab[ir++] = new Array ("2.2.1.35", "VirtualTextExists", "VirtualTextExists.html", "10196", "VirtualTextExists");
tocTab[ir++] = new Array ("3", "Tutorials", "", "10055", "Tutorials");
tocTab[ir++] = new Array ("3.0", "Create a New Install Fast", "CreateANewInstallFast.html", "10056", "CreateANewInstallFast");
tocTab[ir++] = new Array ("3.1", "Create a New Install Step-by-Step", "CreateANewInstallStep-by-Step.html", "10057", "CreateANewInstallStep-by-Step");
tocTab[ir++] = new Array ("4", "Tcl/Tk Help", "", "10053", "TclTkHelp");
tocTab[ir++] = new Array ("4.0", "What is Tcl/Tk?", "WhatIsTclTk.html", "10058", "WhatIsTclTk");
var nCols = 9;
Added docs/html/FHTop.html.
















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
<!-- saved from url=(0014)about:internet -->
<html><head><TITLE>Top</TITLE><meta name="generator" content="Fast-Help">
</head>
<body bgcolor="#C0C0C0" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"><div id="Tabs" style="position:absolute; left:0px; top:30px; width:320px; height:16716px; z-index:1"><a href="JavaScript:parent.reDisplay('Top',1,0,0)"><img src="Images/GrayTabContents.gif" alt="Contents" border="0"></a><a href="FHKeywords.html" target="toc"><img src="Images/GrayTabIndex.gif" alt="Index" border="0"></a><a href="FHSearch.html" target="toc"><img src="Images/GrayTabSearch.gif" alt="Search" border="0"></a></div>
<font size=2 color="#000000" face="Arial">
<div align=right><font size=5 color="#333333"><b>InstallJammer 1.2 User Guide&nbsp;&nbsp;&nbsp;&nbsp; </b></font></div>
</font>
</body></html>
Added docs/html/FHUtilities.js.








































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//© DevHost Ltd, 2006 v1.7

function OpenFileRelativeToCHMFolder(stFileName)
{
  var X, Y, sl, a, ra, link;
  ra = /:/;
  a = location.href.search(ra);
  if (a == 2)
    X = 14;
  else
    X = 7;
  sl = "\\";
  Y = location.href.lastIndexOf(sl) + 1;
  link = 'file:///' + location.href.substring(X, Y) + stFileName;
  location.href = link;
}

function FHToggleHiddenParagraphs(iParagraph, iImage, stHidden, stVisible)
{if (iParagraph.style.display=="none")
  {iParagraph.style.display="";
   iImage.src=stVisible;
  }
else 
  {iParagraph.style.display="none";
   iImage.src=stHidden;
  }
}

function extractFileName(stFullPath)
{
  var iLastSlash; // the position of the last slash in the path
  var stFileName;  // the name of the file
  iLastSlash = stFullPath.lastIndexOf("/");
  stFileName = stFullPath.substring(iLastSlash+1,stFullPath.length);
  return stFileName;
}

//This function is used to pass a contextstring, extracted from a file name, to a website url
function extractFileNameWithoutKnownExtension(stFullPath)
{
  var iLastSlash;// the position of the last slash in the path
  var stFileName, stExt;// the name of the file
  var boRemoveExtension=new Boolean();
  var stPage;
  var i;
  iLastSlash = stFullPath.lastIndexOf("/");
  stFileName = stFullPath.substring(iLastSlash+1,stFullPath.length);

  //find the extension
  i = stFileName.lastIndexOf(".");
  stExt = stFileName.substring(i,stFileName.length);
  stExt = stExt.toLowerCase();
  //is this a known extension that we want to remove
  boRemoveExtension = false;
  if (stExt == ".html")
    {boRemoveExtension = true;}
  if (stExt == ".htm")
    {boRemoveExtension = true;}
  if (stExt == ".asp")
    {boRemoveExtension = true;}
  if (stExt == ".php")
    {boRemoveExtension = true;}

  if (boRemoveExtension = true)
    {stFileName = stFileName.substring(0,i);}

  return stFileName;
}
Added docs/html/FetchURL.html.
















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Fetch URL</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Fetch URL">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Fetch URL</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="Exit.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GenerateUID.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will fetch a given URL from the web and store the result into a file on the local system.&nbsp; This is useful for downloading pieces of the installer that you don't want to package up but want to download when the user opts to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Progress Virtual Text</span></p>
<p class=rvps1><span class=rvts2>The name of the virtual text variable to fill in with progress as the file is downloaded.&nbsp; This variable will hold the percent complete as the file is downloaded.&nbsp; You can use this on a pane with a progress bar to track the progress of the download.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Proxy Host</span></p>
<p class=rvps1><span class=rvts2>The hostname of a proxy server to use when making the request.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Proxy Port</span></p>
<p class=rvps1><span class=rvts2>The port on the proxy host to use when making the request.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Save To</span></p>
<p class=rvps1><span class=rvts2>Specifies that you want to save the fetched file to a file or a virtual text variable.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Target</span></p>
<p class=rvps1><span class=rvts2>If saving to a file, this is the name of the file or directory to save to.&nbsp; If this is a directory, the file name will be derived from the URL itself.&nbsp; If saving to a file, this property holds the virtual text variable (without &lt;% and %&gt;) to save the file contents to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Timeout</span></p>
<p class=rvps1><span class=rvts2>The time, in microseconds, to wait before giving up when trying to connect to download the file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>URL</span></p>
<p class=rvps1><span class=rvts2>The URL to fetch.</span></p>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FetchURL1.html.
















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Fetch URL</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Fetch URL">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Fetch URL</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="Exit1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PropertyFileAPI.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::FetchURL</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Fetch the given URL and store its contents into virtual text or in a file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty string or error.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-blocksize &lt;size&gt;</span></p>
<p class=rvps1><span class=rvts2>The block size to use when downloading.&nbsp; The smaller the block size, the finer the progress bar will be, but it will usually be slower because more calls are made to download the full file size.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-file &lt;filename&gt;</span></p>
<p class=rvps1><span class=rvts2>The name of a file to store the downloaded file to.&nbsp; This can also be a list of files separated by ; that corresponds to a list of URLs separated by ;.&nbsp; Each URL relates to one file in the list.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-progressvirtualtext &lt;virtual text&gt;</span></p>
<p class=rvps1><span class=rvts2>The name of a virtual text variable (without &lt;% and %&gt;) to update as the progress of the download.&nbsp; This is usually attached to a progress bar.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-proxyhost &lt;hostname&gt;</span></p>
<p class=rvps1><span class=rvts2>The host name of a proxy server to use for the request.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-proxyport &lt;port number&gt;</span></p>
<p class=rvps1><span class=rvts2>The port number of a proxy server to use for the request.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-statusvirtualtext &lt;virtual text&gt;</span></p>
<p class=rvps1><span class=rvts2>The name of a virtual text variable (without &lt;% and %&gt;) to update with status as the files are downloaded.&nbsp; This will set the status virtual text to &lt;%DownloadVirtualText%&gt; as the files are downloaded.&nbsp; If more than one file is specified, the status will also contain the current and total file count.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-url &lt;URL&gt;</span></p>
<p class=rvps1><span class=rvts2>A URL or a list of URLs separated by ; to download.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-virtualtext &lt;virtual text&gt;</span></p>
<p class=rvps1><span class=rvts2>A virtual text variable or list of virtual text variables separated by ; (without &lt;% and %&gt;) to store the downloaded files into.&nbsp; Each URL relates to a single virtual text variable.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FileExistsCondition.html.






















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>File Exists Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="File Exists Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>File Exists Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ConditionStandardProperties.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FileNameTestCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if a file exists or does not exist on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Filename</span></p>
<p class=rvps1><span class=rvts2>The name of the file on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=156>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; exists</span></p>
</td>
<td width=606>
<p class=rvps1><span class=rvts2>True if the file does exist.</span></p>
</td>
</tr>
<tr valign=top>
<td width=156>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not exists</span></p>
</td>
<td width=606>
<p class=rvps1><span class=rvts2>True if the file does not exist.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FileExtensionExistsCondition.html.






















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>File Extension Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="File Extension Exists Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>File Extension Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AskYesOrNo.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FileTypeExistsCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if a given file extension exists in the Windows registry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Extension</span></p>
<p class=rvps1><span class=rvts2>The extension to check.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=144>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; exists</span></p>
</td>
<td width=618>
<p class=rvps1><span class=rvts2>True if the extension exists.</span></p>
</td>
</tr>
<tr valign=top>
<td width=144>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not exist</span></p>
</td>
<td width=618>
<p class=rvps1><span class=rvts2>True if the extension does not exist.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FileNameTestCondition.html.




















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>File Name Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="File Name Test Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>File Name Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FileExistsCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FilePermissionCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks a filename to see if it contains any invalid characters and determines if the filename is a legal name.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Filename</span></p>
<p class=rvps1><span class=rvts2>The name of the file on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=165>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; name is valid</span></p>
</td>
<td width=597>
<p class=rvps1><span class=rvts2>True if the filename is a legal name.</span></p>
</td>
</tr>
<tr valign=top>
<td width=165>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; name is not valid</span></p>
</td>
<td width=597>
<p class=rvps1><span class=rvts2>True if the filename is not a legal name.</span></p>
</td>
</tr>
<tr valign=top>
<td width=165>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; path is valid</span></p>
</td>
<td width=597>
<p class=rvps1><span class=rvts2>True if the each directory in the filename path is a legal name.</span></p>
</td>
</tr>
<tr valign=top>
<td width=165>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; path is not valid</span></p>
</td>
<td width=597>
<p class=rvps1><span class=rvts2>True if any directory in the filename path is not a legal name.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FilePermissionCondition.html.






















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>File Permission Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="File Permission Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>File Permission Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FileNameTestCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CommandLineTestCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks the permissions of a file on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Filename</span></p>
<p class=rvps1><span class=rvts2>The name of the file on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Permission</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=160>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; </span><span class=rvts3>can create</span></p>
</td>
<td width=602>
<p class=rvps1><span class=rvts2>True if the file or directory can be created on the target system.</span></p>
</td>
</tr>
<tr valign=top>
<td width=160>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; </span><span class=rvts3>cannot create</span></p>
</td>
<td width=602>
<p class=rvps1><span class=rvts2>True if the file or directory cannot be created on the target system.</span></p>
</td>
</tr>
<tr valign=top>
<td width=160>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; </span><span class=rvts3>is readable</span></p>
</td>
<td width=602>
<p class=rvps1><span class=rvts2>True if the file exists and is readable.</span></p>
</td>
</tr>
<tr valign=top>
<td width=160>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; </span><span class=rvts3>is not readable</span></p>
</td>
<td width=602>
<p class=rvps1><span class=rvts2>True if the file does not exist or is not readable.</span></p>
</td>
</tr>
<tr valign=top>
<td width=160>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; </span><span class=rvts3>is writable</span></p>
</td>
<td width=602>
<p class=rvps1><span class=rvts2>True if the file exists and is writable.</span></p>
</td>
</tr>
<tr valign=top>
<td width=160>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; </span><span class=rvts3>is not writable</span></p>
</td>
<td width=602>
<p class=rvps1><span class=rvts2>True if the file does not exist or is not writable.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FileTypeExistsCondition.html.






















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>File Type Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="File Type Exists Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>File Type Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FileExtensionExistsCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="RegistryEntryExistsCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if a given file type exists in the Windows registry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Type</span></p>
<p class=rvps1><span class=rvts2>The file type to check.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=141>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; exists</span></p>
</td>
<td width=621>
<p class=rvps1><span class=rvts2>True if the file type exists.</span></p>
</td>
</tr>
<tr valign=top>
<td width=141>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not exist</span></p>
</td>
<td width=621>
<p class=rvps1><span class=rvts2>True if the file type does not exist.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FilesAndDirectories.html.












































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Files and Directories</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Files and Directories">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
}
span.rvts4
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts5
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts6
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts7, span.rvts7
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts7:hover { color: #0000ff; }
span.rvts8
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts9
{
 font-family: 'Verdana';
 color: #0000ff;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Files and Directories</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GroupsAndFiles.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="Components.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>Files and directories are added to your project in File Groups.&nbsp; Each file or directory in your project has its own set of properties that will override the default values specified in its File Group.&nbsp; By default, a file or directory will inherit the properties of its parents up the tree, going back as far as the File Group.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>When adding files and directories to a file group, they begin with no specific options, which means that they will inherit the properties of the File Group.&nbsp; As you modify the properties of a directory, it will automatically affect the properties of all files and subdirectories in that directory.&nbsp; Modifying the properties of a file will only change that file.&nbsp; You can also select multiple files and directories and change their properties all at once.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts8>It is important to remember that properties on file groups and directories propagate down and affect all files and directories beneath them.&nbsp; Looking at the File or Directory Details will show you what values currently affect the selected file or directory.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts9>Files that have been newly-added to the project since the last time the project was loaded will appear in blue</span><span class=rvts3>.&nbsp; This makes it easy to detect when InstallJammer has modified the current project because it has automatically picked up a new file while recursively searching through directories.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Files that are disabled or "greyed-out" mean that InstallJammer cannot find the file on the local system.&nbsp; The file may have been deleted on the system, or the location of the file may have changed.&nbsp; You can find the file again by changing its Location property or by changing the Location of its containing directory.&nbsp; Files that cannot be found will not be included when the install is built.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts8>Files cannot be deleted from an included directory in the file tree.&nbsp; InstallJammer keeps track of the entire structure of a directory, so deleting a file from the project would only result in InstallJammer finding it again the next time you build.&nbsp; If you don't want to include a file in your installer, just uncheck it or mark it inactive.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Standard Properties</span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts7 href="StandardProperties.html">Standard Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Active</span></p>
<p class=rvps1><span class=rvts2>If a file is marked inactive, that file will not be included when the installer is built.&nbsp; If a directory is marked inactive, that directory and all files and directories beneath it will not be included when the installer is built.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Compression Method</span></p>
<p class=rvps1><span class=rvts2>This property defines the method of compression for the selected file or directory.&nbsp; If specified on a directory, all other files and directories beneath the selected directory will have the same compression method.&nbsp; If the compression method is left blank, the default compression method for the project will be used.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Destination Directory</span></p>
<p class=rvps1><span class=rvts2>This specifies the directory on the target system that this directory or file will install into.&nbsp; Modifying the Destination Directory of a directory will automatically affect the destination of every file and directory in that directory since they inherit properties from their parent.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts8>If the Desination Directory is set on a directory, it means the name of the directory where this directory will be created on the target system.&nbsp; The Destination Directory for a file is the directory the target file will be placed INTO on the target system.&nbsp; See the Install Location under File or Directory Details to know for sure where a given file or directory will be installed.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>File Update Method</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer how to behave when it is installing a file or directory on the target system that already exists.&nbsp; Modifying the File Update Method of a directory will automatically affect the update method of every file and directory in that directory.&nbsp; This does not modify their File Update Method property, but they will inherit from their parent.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Location</span></p>
<p class=rvps1><span class=rvts2>This property specifies the location of the given file or directory on the local system.&nbsp; When changing the location of a file or directory, you can specify that the location provided should be stored in the project file itself or in your local preferences.&nbsp; If the location is stored in your local preferences, it will not affect the location in the project file and will only be used when the project is loaded on the current machine.&nbsp; This allows developers to specify different locations for projects on their own machines without having to change the locations within the project file itself.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If no location is specified, the location of a file or directory will be derived from its parents going up the tree.&nbsp; Looking at the File Details for a particular file or directory will show you the location where InstallJammer has found it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Target Filename</span></p>
<p class=rvps1><span class=rvts2>This file-only property specifies the name that this file should be created as on the target system during installation.&nbsp; The Destination Directory can specify where this file should be installed, but this property specifies what it will be named when it gets there.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Version</span></p>
<p class=rvps1><span class=rvts5>This property tells InstallJammer what Install Version to store for this file or directory on the target system.</span><span class=rvts2>&nbsp; Modifying the Version of a directory will automatically affect the version of every file and directory in that directory.&nbsp; This does not modify their Version property, but they will inherit from their parent.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>File and Directory Details</span></p>
<p class=rvps1><span class=rvts2>This property block will tell you all of the information about the selected file or directory based on its own properties and the properties it has inherited from its parents.&nbsp; This read-only block contains mostly information from the build system about the file or directory, but a few properties are worth noting.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Compression Method</span></p>
<p class=rvps1><span class=rvts2>This is the method that this file will be compressed with.&nbsp; This is derived from its parents or from the default compression method for the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>File Update Method</span></p>
<p class=rvps1><span class=rvts2>This property tells you how the selected file or directory will behave during installation if the target already exists on the target system.&nbsp; If the selected object has no File Update Method of its own, it will inherit up the tree until it finds one.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Install Location</span></p>
<p class=rvps1><span class=rvts2>This property tells you how where the selected file or directory will be installed on the target system.&nbsp; If the selected object has no Destination Directory of its own, it will inherit up the tree until it finds one.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Location</span></p>
<p class=rvps1><span class=rvts2>This is the location on the local system where the file or directory resides.&nbsp; This can be specified in the Location property, or it will be derived from the parents going up the tree.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Version</span></p>
<p class=rvps1><span class=rvts2>This property tells you the Install Version of the selected file or directory when it is installed.&nbsp; This version will be stored for future installations after the install is complete.&nbsp; If the selected object has no Version of its own, it will inherit up the tree until it finds one.&nbsp; If no Version is found in any parent, the global &lt;%InstallVersion%&gt; for the project will be used.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Permissions</span></p>
<p class=rvps1><span class=rvts5>This feature allows you to set the file permissions for the given file or directory.&nbsp; By default, no permissions are set which means that the file or directory will be installed with some default permissions on the target system.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>Permissions for a directory are not inherited by the files and directories underneath it.&nbsp; The permissions only apply to that directory.&nbsp; Multiple files or directories can be selected and their permissions set all at the same time.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>Both Windows attributes and UNIX permissions are provided and will be applied based on the target system.&nbsp; So, if a file has both Windows attributes and UNIX permissions, the Windows attributes will be applied when the file is installed on a Windows system, and the UNIX permissions will be applied when installed on a UNIX system.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts6>Save Files</span></p>
<p class=rvps1><span class=rvts5>If this property is false, all of the files and subdirectories in this directory will not be saved in the project file.&nbsp; When this directory is built, all of its contents will be dynamically generated from whatever is currently in the directory.&nbsp; This allows for adding directories where all of the contents are only stored at build time.&nbsp; This property works like a finer-grained version of the Save Only Toplevel Directories project preference.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FindObjects.html.










































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>FindObjects</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="FindObjects">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts5
{
 font-family: 'Courier New';
 color: #993366;
}
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>FindObjects</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="EnvironmentVariableExists.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="LanguageAPI.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::FindObjects</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Search the system for an object based on the given options.&nbsp; See </span><a class=rvts6 href="ObjectTypes.html">Object Types</a><span class=rvts2> for the types of objects in a project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>A list of matching objects or an empty string.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-active &lt;yes or no&gt;</span></p>
<p class=rvps1><span class=rvts2>If specified, only objects which are in the state given will be returned.&nbsp; -active yes means to return only objects which are active, and -active no means to only return objects which are inactive.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-alias &lt;alias name&gt;</span></p>
<p class=rvps1><span class=rvts2>The alias of an object to find.&nbsp; If this option is specified, only a single object will be returned since no more than one object can ever have an alias.&nbsp; If no object is found with the given alias, an empty string is returned.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-component &lt;component name&gt;</span></p>
<p class=rvps1><span class=rvts2>If specified, only objects that were created from the given component will be included in the result.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-glob &lt;yes or no&gt;</span></p>
<p class=rvps1><span class=rvts2>If this option is specified with the -name option, the -name option is matched as a glob pattern instead of an exact name.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-name &lt;name&gt;</span></p>
<p class=rvps1><span class=rvts2>If specified, only objects which have the given name will be included in the result.&nbsp; If the -glob option is true, the name will be matched against a pattern instead of an exact match.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-parent &lt;parent ID or alias&gt;</span>
<br><span class=rvts2>If specified, only objects which are children of the given parent will be included in the result.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts4>Note that while in a project file, files are children of their parent directory, when files are added to an installer, the structures are flattened so that each file is a child of its file group.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>-type &lt;object type&gt;</span></p>
<p class=rvps1><span class=rvts2>If specified, only objects which are of the given type will be included in the result.&nbsp; Valid types are: file, filegroup, component, setuptype, condition, action, actiongroup and pane.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>The following example finds all the files in the Program Files group (if it has the Program Files alias).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>::InstallAPI::FindObjects -parent "Program Files"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following example finds all the panes.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>::InstallAPI::FindObjects -type pane</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following example finds all the actions in the Install Actions group.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>::InstallAPI::FindObjects -type action -parent "Install Actions"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following example gets the object ID for the Install Actions group.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>::InstallAPI::FindObjects -alias "Install Actions"</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FindProcesses.html.


































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>FindProcesses</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Find Processes">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>FindProcesses</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PropertyFileAPI.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GetComponentsForSetupType.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::FindProcesses</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Find a list of processes on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts5>The API uses the system 'ps' command to find processes.&nbsp; The arguments to ps are manipulated based on the version of ps and what options it supports.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>A list of process IDs (pids) that match the given criteria.&nbsp; Passing no arguments will return a list of all pids.&nbsp; If no processes are found, an empty string is returned.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-glob &lt;yes or no&gt; (Windows only)</span></p>
<p class=rvps1><span class=rvts2>If this option is specified, the -name option will be matched as a glob pattern instead of an exact match.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-group &lt;group name or ID&gt;</span></p>
<p class=rvps1><span class=rvts2>Find a list of processes running for the given group name or ID.&nbsp; This option does nothing on Windows platforms.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-name &lt;command name&gt;</span></p>
<p class=rvps1><span class=rvts2>Find a list of processes that match the given command name.&nbsp; This does not include paths, only the actual command name.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-pid &lt;process id&gt;</span></p>
<p class=rvps1><span class=rvts2>Find the explicit process ID given.&nbsp; This is useful if you want to find out if a given process ID is running.&nbsp; If the pid is not found, FindProcesses will return an empty string.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-user &lt;user name or ID&gt;</span></p>
<p class=rvps1><span class=rvts2>Find a list of processes running for the given user name or ID.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>The following example would find the running process for the gnome-panel.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::FindProcesses -name gnome-panel</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This example would find all processes being run by the root user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::FindProcesses -user root</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FocusOnWidget.html.










































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Focus On Widget</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Focus On Widget">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Focus On Widget</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="DestroyWidget.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ModifyWidget.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will draw the keyboard focus to a widget.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Widget ID</span></p>
<p class=rvps1><span class=rvts2>The ID or alias of the widget to be destroyed.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/FrequentlyAskedQuestions.html.
























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Frequently Asked Questions</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Frequently Asked Questions">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #0000ff;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Frequently Asked Questions</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GettingStarted.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GettingToKnowTheInstallBuilder.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts4>1.&nbsp; How do I save relative paths for the files in my install project?</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Most installers give you the option of a check box that allows you to save all of the files in your project as relative paths.&nbsp; Relative usually being relative to the location of the project file itself.&nbsp; This is an extremely useful feature since most developers don't usually put their work in the same locations on their own machines.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Instead of just a simple check box for saving paths as relative, InstallJammer allows you the ability to completely re-map the location of any file in your project.&nbsp; This is done through the </span><span class=rvts3>Location property for directories and files</span><span class=rvts2>.&nbsp; If you select a file or directory in your project, you will see a standard property called Location.&nbsp; This property tells InstallJammer where to find this file or directory on the local system.&nbsp; If you click the Location property, you see a browse button that opens a popup for specifying the location.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><img border="0" src="Images/locationpopup.PNG" width="408" height="184"></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>InstallJammer lets you specify the location as a directory that can be stored back into the project file itself or one that you can store in your own local copy of your InstallJammer preferences.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If the location is specified for a directory, it is the actual location of that directory, not the directory that contains that directory.&nbsp; If the location is specified for a file, it is the directory that contains that file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Locations can be specified as a full directory path, a relative directory path or virtual text.&nbsp; A relative directory path is relative to the location of the project file itself.&nbsp; Virtual text can contain a full or relative path and will be substituted at build time to get the file location.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>For example, you could specify the Location of your main application directory as &lt;%BaseDir%&gt;.&nbsp; Then, in your Virtual Text Strings table, create a new virtual text variable BaseDir with the location of your application.&nbsp; Then, you can actually build from the command-line with a different location by specifying </span><span class=rvts3>-DBaseDir /path/to/your/application</span><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>2.&nbsp; Where is the best place to put my project file so that it is part of my application directory?</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Many developers wish to put their InstallJammer project files somewhere within their application structure so that the project file can be easily included when packaging the application itself and so that the project file can be maintained in the same source repository as the application itself.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>It's best to put your project file in its own subdirectory because InstallJammer uses the project file location as a base for creating a build/ and output/ subdirectory.&nbsp; So, the best place to put your project file so that it is part of your application directory is in a subdirectory off the main application directory.&nbsp; An installer/ subdirectory would do nicely.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>With this in place, you can easily specify the Location of your main application directory as ".." and have all of your application files be relative to your project file.&nbsp; Since relative Locations are relative to the project file, a Location of .. means that the files are located one directory down.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>3.&nbsp; How do I build from the command-line with a different location for my application?</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This is easily done by giving the directories in your install project a virtual text Location.&nbsp; If the Location of a directory is specified as virtual text, you can then specify a new value for that virtual text on the command-line when you build.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Let's say you have a main application directory, and you specify the Location of that directory as &lt;%BaseDir%&gt;.&nbsp; Then, in your project file, you can create a new virtual text variable called BaseDir with a value of /my/application/is/here.&nbsp; Now, you want to build from the command-line with a different directory location for your application, so you do:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>installjammer -DBaseDir /path/to/my/application /path/to/my/project.mpi</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The -D option lets you specify a virtual text variable and a value that will be overridden in the install project before the installer is built.&nbsp; The last argument on the command-line is always the path to your project file.&nbsp; Using the above command, your project will be built with your application files located in /path/to/my/application.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GenerateUID.html.


















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Generate UID</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Generate UID">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Generate UID</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FetchURL.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="LaunchFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will generate a GUID or UUID and store the result in a virtual text variable.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>UID Type</span></p>
<p class=rvps1><span class=rvts2>Whether to generate a GUID or a UUID.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts4>A GUID is just a UUID with curly braces around it.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text</span></p>
<p class=rvps1><span class=rvts2>The name of a virtual text variable (without &lt;% and %&gt;) to store the new UID into.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GetAction.html.
















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>GetAction</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="GetAction">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>GetAction</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="WhatIsTheBuilderAPI.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GetActionGroup.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::BuilderAPI::GetAction</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Find an action object by its alias and setup.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Object ID or empty string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>-alias</span></p>
<p class=rvps1><span class=rvts2>The alias of the action to locate.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-setup</span></p>
<p class=rvps1><span class=rvts2>Can be one of install or uninstall to look for the given action within the install tree or the uninstall tree.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GetActionGroup.html.














































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>GetActionGroup</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="GetActionGroup">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>GetActionGroup</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GetAction.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ModifyObject1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::BuilderAPI::GetActionGroup</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Find an action group object by its alias and setup.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Object ID or empty string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-alias</span></p>
<p class=rvps1><span class=rvts2>The alias of the action group to locate.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-setup</span></p>
<p class=rvps1><span class=rvts2>Can be one of install or uninstall to look for the given action group within the install tree or the uninstall tree.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GetComponentsForSetupType.html.






































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>GetComponentsForSetupType</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="GetComponentsForSetupType">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>GetComponentsForSetupType</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FindProcesses.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GetInstallSize.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::GetComponentsForSetupType</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Return a list of all the components that are included in the given Setup Type.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>List of components or an empty list.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-setuptype &lt;setup type name or ID&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The setup type can either be the name of the setup type (like Typical or Custom), or it can be the ID of the setup type.&nbsp; The API call will figure out what you mean.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GetInstallSize.html.
















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>GetInstallSize</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="GetInstallSize">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>GetInstallSize</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GetComponentsForSetupType.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GetSelectedFiles.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::GetInstallSize</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Get the required install size for a given object.&nbsp; The object can be a Setup Type, Component or File Group.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts4>With no options at all, this API returns the size that is required for the currently-selected components in the install.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>The install size required for the given object.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-activeonly &lt;boolean&gt;</span></p>
<p class=rvps1><span class=rvts2>If this option is true, only active objects will be added to the total install size.&nbsp; This option is true by default.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-object &lt;object ID or alias&gt;</span></p>
<p class=rvps1><span class=rvts2>The object can be a Setup Type, Component or File Group to return the size of.&nbsp; If no object is specified, the install size of the currently-selected options by the user will be returned.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GetJavaProperty.html.






















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Get Java Property</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Get Java Property">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Get Java Property</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="UnpackStoredFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="LocateJavaRuntime.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will retrieve a specified property value from a standard Java properties file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Property</span></p>
<p class=rvps1><span class=rvts2>The name of the property to get from the property file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Property File</span></p>
<p class=rvps1><span class=rvts2>The path to the property file to open.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text&nbsp; </span></p>
<p class=rvps1><span class=rvts2>The name of the virtual text variable to fill with the property if it is found in the property file.&nbsp; If the property is not found in the property file, the value of the virtual text will be blank.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GetPreviousInstallInfo.html.


























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Get Previous Install Info</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Get Previous Install Info">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Get Previous Install Info</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CheckForPreviousInstall.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallLogFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action gets a specific set of install information based on a given Install ID.&nbsp; Since a single application can have multiple installations on the same system, this action can be used to get specific information from a specific install.&nbsp; You must first find the Install ID though.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Application ID</span></p>
<p class=rvps1><span class=rvts2>The Application ID to read previous install information from.&nbsp; This defaults to the current installer's &lt;%ApplicationID%&gt;, but this action can also be used to read install information from other installations.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Install ID</span></p>
<p class=rvps1><span class=rvts2>The install ID of the install whose information you want to get.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text Prefix</span></p>
<p class=rvps1><span class=rvts2>A string to prefix to the beginning of each piece of information from the install registry.&nbsp; This prefix will be used for each variable from the registry to add information to virtual text variables depending on what information is available.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following virtual text variables are set as a result of this action (assuming that your Virual Text Prefix is PreviousInstall):</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallApplicationID%&gt;</span></p>
<p class=rvps1><span class=rvts2>The Application ID of the previously installed application.&nbsp; This should match your own Application ID unless the previous install was an upgrade install.&nbsp; In that case, the Upgrade Install ID should match your application ID.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallDate%&gt;</span></p>
<p class=rvps1><span class=rvts2>The install date of the last install in clock seconds.&nbsp; This can be formatted using the &lt;%Date%&gt; virtual text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallCount%&gt;</span></p>
<p class=rvps1><span class=rvts2>The number of previous installations found on the target system.&nbsp; Only the last install, by date, will be used for this information.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallDir%&gt;</span></p>
<p class=rvps1><span class=rvts2>The installation directory of the last install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallDirExists%&gt;</span></p>
<p class=rvps1><span class=rvts2>A convenience value that tells you whether or not the previous install dir still exists on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallExecutable%&gt;</span></p>
<p class=rvps1><span class=rvts2>The full path of the previous install executable when it was run.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallExists%&gt;</span></p>
<p class=rvps1><span class=rvts2>This value will be true if a previous install was found, or false if one was not found.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallID%&gt;</span></p>
<p class=rvps1><span class=rvts2>The Install ID of the last install.&nbsp; This is the ID that is generated everytime an installer is run, so this ID will change with each subsequent install.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallRealUser%&gt;</span></p>
<p class=rvps1><span class=rvts2>The real username of the person who installed last.&nbsp; This is the real username even if the user was running as root.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallSource%&gt;</span></p>
<p class=rvps1><span class=rvts2>The directory where the previous installer was run from.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallUninstaller%&gt;</span></p>
<p class=rvps1><span class=rvts2>The full path to the uninstaller of the last install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallUpgradeID%&gt;</span></p>
<p class=rvps1><span class=rvts2>The Upgrade Application ID of the last install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallUser%&gt;</span></p>
<p class=rvps1><span class=rvts2>The username of the person who installed last.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallVersion%&gt;</span></p>
<p class=rvps1><span class=rvts2>The install version (1.0.1.0, etc...) of the last install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PreviousInstallVersionString%&gt;</span></p>
<p class=rvps1><span class=rvts2>The install version string (1.0a1, etc...) of the last install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>Other variables can also be set if a developer has added information to the install registry through the </span><a class=rvts4 href="AddInstallInfo.html">Add Install Info</a><span class=rvts5> action.&nbsp; Any variable added through that action will also appear in virtual text as a result of this action.&nbsp; For example:</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>If the Key Foo was added with the Value Bar, you would get the variable &lt;%PreviousInstallFoo%&gt; that would equal Bar.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GetSelectedFiles.html.


























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>GetSelectedFiles</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Get Selected Files">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--




/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF">

<p class=rvps1><span class=rvts3>::InstallAPI::GetSelectedFiles</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Get a list of the currently-selected files to be installed.&nbsp; This will return a list of all the files that are currently selected to be installed when InstallJammer reaches the </span><a class=rvts5 href="InstallSelectedFiles.html">Install Selected Files</a><span class=rvts2> action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts4>The API will automatically exclude any components, file groups or files that are inactive since they would not be installed by Install Selected Files.&nbsp; The selected files are also based on the currently-selected Setup Type.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>A list of file object IDs or a list of file names depending on options.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-fileids &lt;boolean&gt;</span></p>
<p class=rvps1><span class=rvts2>If this option is true, the return value will be a list of file object IDs instead of a list of file names.&nbsp; By default, this API returns a list of the target file names to be installed.</span><span class=rvts1></span></p>

</body></html>
Added docs/html/GetSystemPackageManager.html.






































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>GetSystemPackageManager</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Get System Package Manager">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>GetSystemPackageManager</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GetSelectedFiles.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GetWidgetChildren.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::GetSystemPackageManager</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Returns a string describing the package manager used by the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts4>This API call checks to see if the dpkg or rpm command exists on the system.&nbsp; If a system were to have both dpkg and rpm on the same system, the API will return dpkg since it is the first one checked.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>UNIX</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts3>DPKG</span><span class=rvts2> if the system uses the DPKG package database.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>RPM</span><span class=rvts2> if the system uses the RPM package database.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Empty string</span><span class=rvts2> if neither is found to be used.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GetWidgetChildren.html.


















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>GetWidgetChildren</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="GetWidgetChildren">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>GetWidgetChildren</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GetSystemPackageManager.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GetWidgetPath.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::GetWidgetChildren</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Return all the children of a given widget.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>A list of child widgets.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-includeparent &lt;yes | no&gt; (Default: no)</span></p>
<p class=rvps1><span class=rvts2>If this option is true, the returned list will also include the given parent widget.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-widget &lt;widget&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The Object ID or alias of the widget whose children are to be found.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-window &lt;window&gt; (Default: Current Pane)</span></p>
<p class=rvps1><span class=rvts2>The Object ID or alias of the pane the widget is a child of.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GetWidgetPath.html.












































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>GetWidgetPath</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="GetWidgetPath">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>GetWidgetPath</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GetWidgetChildren.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="EnvironmentVariableExists.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::GetWidgetPath</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Return the actual widget path of a given widget object or alias.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>The full path to the widget.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-widget &lt;widget&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The Object ID or alias of the widget whose path is to be returned.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-window &lt;window&gt; (Default: Current Pane)</span></p>
<p class=rvps1><span class=rvts2>The Object ID or alias of the pane the widget is a child of.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GettingStarted.html.


















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Getting Started</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Getting Started">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
a.rvts3, span.rvts3
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts3:hover { color: #0000ff; }
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
a.rvts7, span.rvts7
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts7:hover { color: #0000ff; }
a.rvts8, span.rvts8
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts8:hover { color: #0000ff; }
a.rvts9, span.rvts9
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts9:hover { color: #0000ff; }
a.rvts10, span.rvts10
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts10:hover { color: #0000ff; }
a.rvts11, span.rvts11
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts11:hover { color: #0000ff; }
a.rvts12, span.rvts12
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts12:hover { color: #0000ff; }
a.rvts13, span.rvts13
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts13:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Getting Started</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="10b1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FrequentlyAskedQuestions.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>The easiest way to get started using InstallJammer for the first time is to read through some of our tutorials.&nbsp; If you have a good grasp of installers and how they work, you can probably give a quick read through </span><a class=rvts3 href="CreateANewInstallFast.html">Create a New Install Fast</a><span class=rvts2> to get started.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If you want a more detailed look at building a new install, read through the </span><a class=rvts4 href="CreateANewInstallStep-by-Step.html">Create a New Install Step-by-Step</a><span class=rvts2> tutorial.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If you're already familiar with how to use InstallJammer, or you just want to learn something maybe you didn't know already, you can read through our </span><a class=rvts13 href="FrequentlyAskedQuestions.html">Frequently Asked Questions</a><span class=rvts2> to see if maybe what you're looking for is in there.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Once you have your first install project built, read through </span><a class=rvts5 href="GettingToKnowTheInstallBuilder.html">Getting to Know the Install Builder</a><span class=rvts2>.&nbsp; It will give you a good introduction to InstallJammer's install builder and how to use it effectively.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>After you finish learning your way around InstallJammer's install builder, read a little bit more about </span><a class=rvts6 href="VirtualText.html">Virtual Text</a><span class=rvts2> and its use within InstallJammer.&nbsp; You might also want to read through </span><a class=rvts7 href="WhatIsVirtualText.html">What is Virtual Text?</a><span class=rvts2> and the list of </span><a class=rvts8 href="VirtualTextDefinitions.html">Virtual Text Definitions</a><span class=rvts2> or </span><a class=rvts9 href="VirtualDirectoryDefinitions.html">Virtual Directory Definitions</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Once you understand virtual text a little better, it's time to learn about what the customer really sees.&nbsp; The panes of your install.&nbsp; Read up on </span><a class=rvts10 href="WhatArePanes.html">What are Panes?</a><span class=rvts2> to become more familiar with how InstallJammer displays the installer to the user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>When you think you understand the basics of installs and the use of virtual text, you might want to read through </span><a class=rvts11 href="WhatAreActions.html">What are Actions?</a><span class=rvts2> Actions are used throughout the install process, and it's worthwhile to read up on what they are, how you use them and what types of actions are available.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>After reading about actions, you'll probably want to know how to control those actions.&nbsp; Read up on </span><a class=rvts12 href="WhatAreConditions.html">What are Conditions?</a><span class=rvts2> to get a feel for how InstallJammer controls the flow of your installer.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GettingToKnowTheInstallBuilder.html.




























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Getting to Know the Install Builder</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Getting to Know the Install Builder">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Getting to Know the Install Builder</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FrequentlyAskedQuestions.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallBuilderPreferences.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>Read through the following sections to help you get to know the install builder a little better.&nbsp; Each section descibes the different pieces of the install builder and how to use them.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/GroupsAndFiles.html.












































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Groups and Files</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Groups and Files">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
}
span.rvts4
{
 font-family: 'Verdana';
}
span.rvts5
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts6
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts7
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts8, span.rvts8
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts8:hover { color: #ff0000; }
a.rvts9, span.rvts9
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts9:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Groups and Files</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PackageAndArchiveInformation.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FilesAndDirectories.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts4>The file groups tree is used to coordinate the files and directories that will be included in your installer. Files and directories are stored under a file group, and file groups are then made part of a component (or multiple components).</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>When an install is first created, a single file group called "Program Files" is created with the project. If you are only creating a simple installer for your application, this one file group is usually all that you need.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>See </span><a class=rvts9 href="FilesAndDirectories.html">Files and Directories</a><span class=rvts4> for more information about the files and directories that are contained within file groups.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>File Group Properties</span></p>
<p class=rvps1><span class=rvts4>File groups are further defined by their individual properties. When a file group is created, it is setup with a default set of properties that you can alter if you need to. Each file group has a set of standard properties that are properties that are shared by many components in InstallJammer and a set of Advanced Properties that are specific to file groups.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties</span></p>
<p class=rvps1><span class=rvts6>See </span><span class=rvts8>Standard Properties</span><span class=rvts6>.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7>Active</span></p>
<p class=rvps1><span class=rvts6>If a file group is marked inactive, all the files and directories included in that group will not be included in the installer when it is built.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7>Compression Method</span></p>
<p class=rvps1><span class=rvts2>This property defines the method of compression for the given file group.&nbsp; All other files and directories in the given file group will have the same compression method.&nbsp; If the compression method is left blank, the default compression method for the project will be used.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7>Destination Directory</span></p>
<p class=rvps1><span class=rvts6>The directory this file group will be installed to on the target system. The default is &lt;%InstallDir%&gt;, the main installation directory.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7>Display Name</span></p>
<p class=rvps1><span class=rvts6>If this property is set, it specifies the name to display when the name of the file group is shown during installation.&nbsp; If this property is left blank, the actual name of the file group will be used.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7>File Update Method</span></p>
<p class=rvps1><span class=rvts6>This property tells InstallJammer what to do with files when it is updating them on the target system. Updating is when the file already exists, and we need to determine what to do with our file. </span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7>Follow File Links</span></p>
<p class=rvps1><span class=rvts6>If this property is true, any linked files found within the file group will be followed and the file they link to will be stored as an actual file in the installer.&nbsp; If this property is false, any links will be saved as links in the installer and recreated as a link on the target system during installation.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7>Name</span></p>
<p class=rvps1><span class=rvts6>The name of this file group.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7>Save Files</span></p>
<p class=rvps1><span class=rvts6>If this property is false, only the toplevel directories in the file group will be saved.&nbsp; All of the files and subdirectories of the top directories will not be stored in the project file and will be discovered at build time.&nbsp; This is useful when you only want to store a directory but want everything in that directory to be built dynamically.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7>Size</span></p>
<p class=rvps1><span class=rvts6>If the size property is specified, it tells InstallJammer to override what may actually be the size of the files stored in the file group and use the given size instead.&nbsp; The size should be given as an integer only which will automatically be converted to a readable size during installation.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7>Version</span></p>
<p class=rvps1><span class=rvts6>This property tells InstallJammer what Install Version to store for this file group on the target system.&nbsp; If this property is left blank, InstallJammer will use the global &lt;%InstallVersion%&gt; variable for the project.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7><br></span></p>
<p class=rvps1><span class=rvts7>Build Platforms</span></p>
<p class=rvps1><span class=rvts6>This is a list of all the platforms that are supported by InstallJammer and whether or not this file group should be built for each platform. If a platform is marked No, this file group will not be included when the installer for that platform is built.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts6>It is possible to build a file group into multiple platforms and then not install the file group based on parameters during installation, but this option specifically tells InstallJammer to not even include this file group for the given platform.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts7><br></span></p>
<p class=rvps1><span class=rvts7>Permissions</span></p>
<p class=rvps1><span class=rvts6>This feature allows you to set the file permissions for the given file group, file or directory. By default, no permissions are set which means that the file or directory will be installed with some default permissions on the target system.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts6>Permissions on a file group refer to the directory that will be created for the file group and not to all of the files in the file group. Directories and files can be set with their own permissions or be set as group when multiple files and directories are selected.</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts6>Both Windows attributes and UNIX permissions are provided and will be applied based on the target system. So, if a file has both Windows attributes and UNIX permissions, the Windows attributes will be applied when the file is installed on a Windows system, and the UNIX permissions will be applied when installed on a UNIX system.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Creating a new file group</span></p>
<p class=rvps1><span class=rvts4>Click the Add New File Group button on the toolbar to add a new file group to your install.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>A new file group is created with default values that you can change after its creation. Your new file group will be at the bottom of the list.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Deleting a file group</span></p>
<p class=rvps1><span class=rvts4>Click the Delete button on the toolbar to delete the selected nodes from your install. This can also be done through the Delete key on your keyboard.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Any selected nodes in the file group tree will be deleted. This includes files, directories and file groups.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Adding files to a file group</span></p>
<p class=rvps1><span class=rvts4>Click the Add Files to File Group button on the toolbar to add new files to the selected file group. A file dialog will open and ask you to select the files you wish to add to the file group.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Files can also be added to a program folder by dragging and dropping them from your file explorer. Most major window managers are supported.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Adding directories to a file group</span></p>
<p class=rvps1><span class=rvts4>Click the Add Directory to File Group button on the toolbar to add new files to the selected file group. A directory selection dialog will open and ask you to select a directory you wish to add to the file group.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Directories can also be added to a program folder by dragging and dropping them from your file explorer. Most major window managers are supported.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Deleting files from a file group</span></p>
<p class=rvps1><span class=rvts4>Click the Delete button on the toolbar to delete the selected nodes from your install. This can also be done through the Delete key on your keyboard.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Selected nodes in the file group tree, including files and directories directly beneath the file group, will be deleted from the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Only files and directories that are directly beneath a file group can be deleted.&nbsp; Subdirectories and files that are contained within directories cannot be deleted from a project.&nbsp; If you do not wish to include files or directories that are contained in a subdirectory, you simply uncheck them.&nbsp; Files and directories that are unchecked are not included in an install when it is built.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This is done so that once you include a directory in a file group, InstallJammer will maintain the entire directory structure regardless of what is included in the installer.&nbsp; You can always add other subdirectories directly to the file group and have them install anywhere you like based on Destination Directory.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Excluding files and directories from a project</span></p>
<p class=rvps1><span class=rvts2>Files and directories can be excluded from a build by unchecking (or de-activating) them in the file group tree.&nbsp; Any file or directory that does not have a check mark is considered inactive and will be ignored by InstallJammer when building your installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Disabling a directory will automatically disable everything contained in that directory, even if other files and directories in the directory are checked.&nbsp; Once you disable a directory, all of its subdirectories and files are disabled as well.&nbsp; If you wish to disable an entire directory but still include subdirectories beneath it, you will need to add those subdirectories directly to the file group.&nbsp; You can modify their install locations through the Destination Directory property.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>The File Explorer</span></p>
<p class=rvps1><span class=rvts4>The File Explorer button will bring up a directory and file explorer which can be used to drag-and-drop files and directories into file groups. If you did not specify a file explorer in your preferences, InstallJammer will attempt to find the best one based on your window manager.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>On Windows, this defaults to Windows Explorer. You can specify exactly which file explorer you want to use in your preferences. InstallJammer supports drag-and-drop on most major window managers.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/Images/BrowseBlueLeft.png.

cannot compute difference between binary files

Added docs/html/Images/BrowseBlueRight.png.

cannot compute difference between binary files

Added docs/html/Images/GrayTabContents.gif.

cannot compute difference between binary files

Added docs/html/Images/GrayTabIndex.gif.

cannot compute difference between binary files

Added docs/html/Images/GrayTabSearch.gif.

cannot compute difference between binary files

Added docs/html/Images/TabContents.gif.

cannot compute difference between binary files

Added docs/html/Images/TabIndex.gif.

cannot compute difference between binary files

Added docs/html/Images/TabSearch.gif.

cannot compute difference between binary files

Added docs/html/Images/closed.gif.

cannot compute difference between binary files

Added docs/html/Images/closed.png.

cannot compute difference between binary files

Added docs/html/Images/detail.jpg.

cannot compute difference between binary files

Added docs/html/Images/detail.png.

cannot compute difference between binary files

Added docs/html/Images/image1052404295.jpg.

cannot compute difference between binary files

Added docs/html/Images/image132032558.jpg.

cannot compute difference between binary files

Added docs/html/Images/image1502938777.jpg.

cannot compute difference between binary files

Added docs/html/Images/image2023130944.jpg.

cannot compute difference between binary files

Added docs/html/Images/image471894274.jpg.

cannot compute difference between binary files

Added docs/html/Images/image794556172.jpg.

cannot compute difference between binary files

Added docs/html/Images/image797541611.jpg.

cannot compute difference between binary files

Added docs/html/Images/locationpopup.PNG.

cannot compute difference between binary files

Added docs/html/Images/note.jpg.

cannot compute difference between binary files

Added docs/html/Images/note.png.

cannot compute difference between binary files

Added docs/html/Images/open.gif.

cannot compute difference between binary files

Added docs/html/Images/open.png.

cannot compute difference between binary files

Added docs/html/Images/screen2.png.

cannot compute difference between binary files

Added docs/html/Images/screen3.png.

cannot compute difference between binary files

Added docs/html/Images/screen7.png.

cannot compute difference between binary files

Added docs/html/Images/step4.png.

cannot compute difference between binary files

Added docs/html/Images/step5.png.

cannot compute difference between binary files

Added docs/html/Images/step6.png.

cannot compute difference between binary files

Added docs/html/Images/topic.gif.

cannot compute difference between binary files

Added docs/html/Images/topic.png.

cannot compute difference between binary files

Added docs/html/ImportWindowsRegistryFile.html.


























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Import Windows Registry File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Import Windows Registry File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Import Windows Registry File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="AddWindowsUninstallEntry.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="RegisterWindowsLibrary.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will import a Windows registry (.reg) file into the Windows registry on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts5>This action simply calls regedit with the registry file to do the import.&nbsp; The registry file must be in a standard format.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>Windows</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Prompt User</span></p>
<p class=rvps1><span class=rvts2>If this property is true, Windows will prompt the user to ask if they want to import this file before beginning.&nbsp; The user can opt not to import the registry file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Registry File</span></p>
<p class=rvps1><span class=rvts2>The name of the file on the target system to be imported.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallBuilderPreferences.html.






















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install Builder Preferences</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install Builder Preferences">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install Builder Preferences</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GettingToKnowTheInstallBuilder.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="Command-LineOptions.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>Directories</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Project Directory Location</span></p>
<p class=rvps1><span class=rvts2>This preference defines the location of your InstallJammer projects.&nbsp; You can choose to save your projects anywhere, but InstallJammer will use this property by default as a location for new projects when they are created.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Custom Theme Directory Location</span></p>
<p class=rvps1><span class=rvts2>This preference defines where InstallJammer will look for custom themes that you may have for your version of InstallJammer.&nbsp; The directory specified must contain a subdirectory for every theme, and the theme will be added to the list of available themes when creating a new project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Custom Action Directory Location</span></p>
<p class=rvps1><span class=rvts2>This preference defines where InstallJammer will look for custom actions that you may have for your version of InstallJammer.&nbsp; The directory can contain any number of .action files that will then appear in the list of available actions under the category Custom Actions.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Custom Condition Directory Location</span></p>
<p class=rvps1><span class=rvts2>This preference defines where InstallJammer will look for custom actions that you may have for your version of InstallJammer.&nbsp; The directory can contain any number of .condition files that will then appear in the list of available conditions under the category Custom Conditions.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>External Programs</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Explorer</span></p>
<p class=rvps1><span class=rvts2>This preference defines the default file explorer when using the explore features in InstallJammer.&nbsp; If one is not specified, InstallJammer will attempt to use the default file explorer for your system.&nbsp; On Windows, InstallJammer will always use Windows Explorer unless specified.&nbsp; On UNIX systems, InstallJammer will attempt to determine the best file explorer based on your window manager.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Help Browser</span></p>
<p class=rvps1><span class=rvts2>This preference defines the web browser you wish to use when browsing InstallJammer's help documentation.&nbsp; By default, InstallJammer will attempt to find the best browser based on your system environment and a list of acceptable browsers to InstallJammer.&nbsp; Almost any web browser should work properly.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Editor</span></p>
<p class=rvps1><span class=rvts2>This preference defines an external editor program to use when editing long text within the install builder.&nbsp; If an editor is specified, clicking the "..." button to edit a text field will save the text to a temporary file and then launch the external editor on that file.&nbsp; The builder will then watch the file for changes and repopulate the project with the new data.&nbsp; Note that InstallJammer will not create a console window for editing with a text-based editor.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>InstallJammer Update</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Check for updates to InstallJammer on startup</span></p>
<p class=rvps1><span class=rvts2>If this preference is true, InstallJammer will check for new versions of itself everytime it is started.&nbsp; If it is false, you must check for updates by yourself using the Check for Updates Now button on this tab.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Use a proxy server</span></p>
<p class=rvps1><span class=rvts2>If true, InstallJammer will use an HTTP proxy server when checking for its updates.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Proxy Host</span></p>
<p class=rvps1><span class=rvts2>The hostname for the proxy server to use.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Proxy Port</span></p>
<p class=rvps1><span class=rvts2>The port for the proxy server to use.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallDesktopShortcut.html.


































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install Desktop Shortcut</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install Desktop Shortcut">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install Desktop Shortcut</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="LocateJavaRuntime.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallProgramFolderShortcut.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action installs a shortcut on the desktop of the target system depending on the system and desktop environments found.&nbsp; On UNIX systems, this action looks for the existence of both KDE and Gnome and will install the shortcut on either or both desktops if available.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>If the user is root when they run the install, the shortcut will be added for all users on the system.&nbsp; If they are not root, the shortcuts will only be added for the user doing the installation.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts5>UNIX shortcuts are installed using the xdg-icon-desktop utility from the xdg-utils package that is part of the portland project by freedesktop.org.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Additional Arguments</span></p>
<p class=rvps1><span class=rvts2>This property contains any of a number of lines to be added to the UNIX desktop file after the standard properties that are setup by InstallJammer.&nbsp; Each line will be substituted for virtual text and then appended to the desktop file without any further modification.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Command Line Arguments</span></p>
<p class=rvps1><span class=rvts2>This property specifies arguments to be passed to the target filename on the Windows platform.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon Path</span></p>
<p class=rvps1><span class=rvts2>This property specifies the file to use for the icon for this shortcut.&nbsp; On Windows, this can be a .ico, .exe or any other file containing icon information.&nbsp; On UNIX platforms, this usually points to a .png file to display.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon Path Index</span></p>
<p class=rvps1><span class=rvts2>The index into the file that Windows uses when looking for an icon.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Install for All Users</span></p>
<p class=rvps1><span class=rvts2>On Windows, if this option is true, the desktop shortcut will be installed for all users and not just the current user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Shortcut Name</span></p>
<p class=rvps1><span class=rvts2>The name to display for the shortcut.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Shortcut Type</span></p>
<p class=rvps1><span class=rvts2>On UNIX, this specifies what type of shortcut this is.&nbsp; It can be a shortcut to a URL Link, or a shortcut to an Application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Target File Name</span></p>
<p class=rvps1><span class=rvts2>The name of the file this shortcut points to.&nbsp; On a UNIX shortcut that has a type of Link, this is the URL to point to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Working Directory</span></p>
<p class=rvps1><span class=rvts2>On Windows, this specifies the working directory that the target of this shortcut will start in.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Vendor ID</span></p>
<p class=rvps1><span class=rvts2>The Vendor ID is used to group all of the shortcuts and program folders together on UNIX platforms.&nbsp; By default, everything is grouped by the Application ID of the current installer, but setting this to a common value would allow for all of the installers in your company to share program folders, for example.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallLogFile.html.










































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install Log File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install Log File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install Log File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GetPreviousInstallInfo.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallSelectedFiles.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action installs a copy of the InstallJammer install log into a target location.&nbsp; By default, InstallJammer installs this log in a registry directory that it uses for subsequent installs and uninstallation, but this action will let you create a copy of it somewhere else on the system as well.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Log File Location</span></p>
<p class=rvps1><span class=rvts2>This is the directory and filename where you want to install this log file.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallProgramFolderShortcut.html.


































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install Program Folder Shortcut</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install Program Folder Shortcut">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install Program Folder Shortcut</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallDesktopShortcut.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallUNIXProgramFolder.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action installs a shortcut into the Program Folder for your application on the target system depending on the system and desktop environments found.&nbsp; On UNIX systems, this action looks for the existence of both KDE and Gnome and will install the shortcut under either or both menus if available.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>If the user is root when they run the install, the shortcut will be added for all users on the system.&nbsp; If they are not root, the shortcuts will only be added for the user doing the installation.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=20>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=606>
<p class=rvps1><span class=rvts5>UNIX shortcuts are installed using the xdg-icon-menu utility from the xdg-utils package that is part of the portland project by freedesktop.org.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Additional Arguments</span></p>
<p class=rvps1><span class=rvts2>This property contains any of a number of lines to be added to the UNIX desktop file after the standard properties that are setup by InstallJammer.&nbsp; Each line will be substituted for virtual text and then appended to the desktop file without any further modification.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Command Line Arguments</span></p>
<p class=rvps1><span class=rvts2>This property specifies arguments to be passed to the target filename on the Windows platform.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon Path</span></p>
<p class=rvps1><span class=rvts2>This property specifies the file to use for the icon for this shortcut.&nbsp; On Windows, this can be a .ico, .exe or any other file containing icon information.&nbsp; On UNIX platforms, this usually points to a .png file to display.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon Path Index</span></p>
<p class=rvps1><span class=rvts2>The index into the file that Windows uses when looking for an icon.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Install for All Users</span></p>
<p class=rvps1><span class=rvts2>On Windows, if this option is true, the desktop shortcut will be installed for all users and not just the current user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Shortcut Name</span></p>
<p class=rvps1><span class=rvts2>The name to display for the shortcut.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Shortcut Type</span></p>
<p class=rvps1><span class=rvts2>On UNIX, this specifies what type of shortcut this is.&nbsp; It can be a shortcut to a URL Link, or a shortcut to an Application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Target File Name</span></p>
<p class=rvps1><span class=rvts2>The name of the file this shortcut points to.&nbsp; On a UNIX shortcut that has a type of Link, this is the URL to point to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Working Directory</span></p>
<p class=rvps1><span class=rvts2>On Windows, this specifies the working directory that the target of this shortcut will start in.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Vendor ID</span></p>
<p class=rvps1><span class=rvts2>The Vendor ID is used to group all of the shortcuts and program folders together on UNIX platforms.&nbsp; By default, everything is grouped by the Application ID of the current installer, but setting this to a common value would allow for all of the installers in your company to share program folders, for example.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallSelectedFiles.html.


























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install Selected Files</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install Selected Files">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install Selected Files</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallLogFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallUninstaller.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This is the main action of the installation process.&nbsp; This action starts up the actual file installation process and handles installing all of the files the user has selected to install during the process.&nbsp; This action is created in the Install Actions group by default, which is executed from the Copy Files pane of a new install project, but you can move it anywhere you like or remove it all together if your installer is not actually installing any files.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This action will build up a list of groups and files to be installed based on the current Setup Type.&nbsp; The Components of the Setup Type are first checked, and any Component that is inactive will be skipped.&nbsp; Then, the File Groups beneath the Component are checked, and any File Group that is inactive will be skipped.&nbsp; Finally, any file contained in the File Groups that is inactive will be skipped.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Show Console Progress</span></p>
<p class=rvps1><span class=rvts2>If this property is true, a progress bar will be shown during console installs.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Update File Text</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the text properties on the progress pane will be updated every time a new file begins installation.&nbsp; By default, InstallJammer shows what group is being installed and not each and every file.&nbsp; Updating the window with each file can be expensive and can take longer than just updating when a new group is being installed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Update File Percent</span></p>
<p class=rvps1><span class=rvts2>This should only be set to true if you have two progress bars on the same pane and one is tracking the progress of each individual file using &lt;%FilePercentComplete%&gt;.&nbsp; Again, as noted above, it can be very expensive and take longer to install if you are updating on every single file change.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallUNIXProgramFolder.html.










































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install UNIX Program Folder</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install UNIX Program Folder">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install UNIX Program Folder</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallProgramFolderShortcut.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallUNIXShortcut.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action creates a desktop shortcut file on a UNIX system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>If the user is root when they run the install, the folder will be added for all users on the system.&nbsp; If they are not root, the folder will only be added for the user doing the installation.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=20>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=606>
<p class=rvps1><span class=rvts5>UNIX program folders are installed using the xdg-utils package that is part of the portland project by freedesktop.org.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>FreeBSD, Linux</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Additional Arguments</span></p>
<p class=rvps1><span class=rvts2>This property contains any of a number of lines to be added to the .directory file after the standard properties that are setup by InstallJammer.&nbsp; Each line will be substituted for virtual text and then appended to the desktop file without any further modification.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Folder Directory</span></p>
<p class=rvps1><span class=rvts2>This is the directory to install this shortcut in if Folder Location is set to Directory.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Folder Location</span></p>
<p class=rvps1><span class=rvts2>Specifies whether you want to create the .directory file in some directory of your choosing or under the standard program folder.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Folder Name</span></p>
<p class=rvps1><span class=rvts2>The name of the folder to create on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon Path</span></p>
<p class=rvps1><span class=rvts2>This property specifies the file to use for the icon for this shortcut.&nbsp; This usually points to a .png file to display.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Vendor ID</span></p>
<p class=rvps1><span class=rvts2>The Vendor ID is used to group all of the shortcuts and program folders together.&nbsp; By default, everything is grouped by the Application ID of the current installer, but setting this to a common value would allow for all of the installers in your company to share program folders, for example.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallUNIXShortcut.html.
































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install UNIX Shortcut</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install UNIX Shortcut">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install UNIX Shortcut</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallUNIXProgramFolder.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallWindowsShortcut.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action creates a desktop shortcut file on a UNIX system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>If the user is root when they run the install, the shortcut will be added for all users on the system.&nbsp; If they are not root, the shortcuts will only be added for the user doing the installation.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=20>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=606>
<p class=rvps1><span class=rvts5>UNIX shortcuts are installed using the xdg-utils package that is part of the portland project by freedesktop.org.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>FreeBSD, Linux</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Additional Arguments</span></p>
<p class=rvps1><span class=rvts2>This property contains any of a number of lines to be added to the UNIX desktop file after the standard properties that are setup by InstallJammer.&nbsp; Each line will be substituted for virtual text and then appended to the desktop file without any further modification.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Command Line Arguments</span></p>
<p class=rvps1><span class=rvts2>This property contains arguments that should be appended to the target filename to form the full command line for the shortcut.&nbsp; This differs from the Additional Arguments in that the additional arguments are lines that are directly appended to the .desktop file when it is created on the target system.&nbsp; The command line arguments are concatenated with the target filename to form the command line to execute.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Name</span></p>
<p class=rvps1><span class=rvts2>The name of the desktop file on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>The File Name property cannot be empty.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon Path</span></p>
<p class=rvps1><span class=rvts2>This property specifies the file to use for the icon for this shortcut.&nbsp; This usually points to a .png file to display.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Program Folder Name</span></p>
<p class=rvps1><span class=rvts2>If the shortcut being installed is going into the Program Folder, this is the name of the program folder to put it into.&nbsp; By default, it uses the program folder for the rest of the installation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Shortcut Directory</span></p>
<p class=rvps1><span class=rvts2>This is the directory to install this shortcut in.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Shortcut Location</span></p>
<p class=rvps1><span class=rvts2>Where to install the shortcut.&nbsp; This can be either a directory, the Desktop or the Program Folder.&nbsp; If the shortcut is to be installed in a directory, a .desktop file is simply created in the shortcut directory with the given values.&nbsp; If the shortcut is to be installed on the Desktop, the Shortcut Directory is ignored, and the file is installed on the Desktop.&nbsp; If the shortcut is to be installed in the Program Folder, it will be installed in a program folder under the specified Program Folder Name.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Shortcut Name</span></p>
<p class=rvps1><span class=rvts2>The name to display for the shortcut.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Shortcut Type</span></p>
<p class=rvps1><span class=rvts2>This specifies what type of shortcut this is.&nbsp; It can be a shortcut to a URL Link, or a shortcut to an Application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Target File Name</span></p>
<p class=rvps1><span class=rvts2>The name of the file this shortcut points to.&nbsp; If this shortcut has a type of Link, this is the URL to point to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Vendor ID</span></p>
<p class=rvps1><span class=rvts2>The Vendor ID is used to group all of the shortcuts and program folders together.&nbsp; By default, everything is grouped by the Application ID of the current installer, but setting this to a common value would allow for all of the installers in your company to share program folders, for example.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallUninstaller.html.




























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install Uninstaller</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install Uninstaller">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install Uninstaller</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallSelectedFiles.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallWishBinary.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action creates an uninstaller for the current installation on the target system.&nbsp; This action must come after the </span><a class=rvts4 href="InstallSelectedFiles.html">Install Selected Files</a><span class=rvts2> action, as that is the action that builds the list of files, directories and registry entries to be uninstalled.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>Be careful installing more than one uninstaller on the target system.&nbsp; InstallJammer will register its package information with the last uninstaller installed, and that is what it will use during uninstallation.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>It is usually best to only install one instance of an uninstaller.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Message</span></p>
<p class=rvps1><span class=rvts2>This is the message that is used as the status while the uninstall is being built.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Uninstall Directory</span></p>
<p class=rvps1><span class=rvts2>This specifies what directory you want to create the uninstaller in.&nbsp; By default, it is created in the main installation directory.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Uninstall Filename</span></p>
<p class=rvps1><span class=rvts2>The file name to use for the uninstaller on the target system.&nbsp; This defaults to uninstall with the appropriate extension.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallWindowsShortcut.html.






























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install Windows Shortcut</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install Windows Shortcut">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts6
{
 font-family: 'Verdana';
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install Windows Shortcut</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallUNIXShortcut.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddDirectoryToPath.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action installs a shortcut on the desktop of the target system depending on the system and desktop environments found.&nbsp; On UNIX systems, this action looks for the existence of both KDE and Gnome and will install the shortcut on either or both desktops if available.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>If the Target File Name looks like a URL (http://, ftp://, etc...) the shortcut will be a URL shortcut.&nbsp; If the Target File Name does not look like a URL, it is assumed to be a file on the target system, and the file must exist.&nbsp; If the file does not exist, no shortcut will be created.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Command Line Arguments</span></p>
<p class=rvps1><span class=rvts2>This property specifies arguments to be passed to the target filename.&nbsp; These arguments are appended to the Target File Name when creating the shortcut so that when the shortcut is executed, the Target File Name is called with the given arguments.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Description</span></p>
<p class=rvps1><span class=rvts2>This property sets the Comments property of the Windows shortcut, which is also the tooltip that is displayed if the mouse is hovered over the shortcut.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon Path</span></p>
<p class=rvps1><span class=rvts2>This property specifies the file to use for the icon for this shortcut.&nbsp; This can be a .ico, .exe or any other file containing icon information.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon Path Index</span></p>
<p class=rvps1><span class=rvts2>The index into the file that Windows uses when looking for an icon.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Shortcut Directory</span></p>
<p class=rvps1><span class=rvts2>This is the directory to install this shortcut in.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Shortcut Name</span></p>
<p class=rvps1><span class=rvts2>The name to display for the shortcut.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Target File Name</span></p>
<p class=rvps1><span class=rvts2>The name of the file this shortcut points to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Working Directory</span></p>
<p class=rvps1><span class=rvts2>This specifies the working directory that the target of this shortcut will start in.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallWishBinary.html.
































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install Wish Binary</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install Wish Binary">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install Wish Binary</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallUninstaller.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallWrappedScript.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action creates a Tcl/Tk Wish binary on the target system.&nbsp; It is not actually a standard Wish binary but a single-file executable wish that is built from a base installkit.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts5>The installkit is a stand-alone WISH shell that contains the following:</span>
<br><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>Tcl 8.4.14</span></p>
<p class=rvps1><span class=rvts5>Tk 8.4.14</span></p>
<p class=rvps1><span class=rvts5>Tile 0.7.8</span></p>
<p class=rvps1><span class=rvts5>Tkpng 0.7</span></p>
<p class=rvps1><span class=rvts5>Itcl 3.3</span></p>
<p class=rvps1><span class=rvts5>Thread 2.6.4 (Windows only)</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Binary Name</span></p>
<p class=rvps1><span class=rvts2>This is the name of the wish binary you wish to create.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Windows Icon</span></p>
<p class=rvps1><span class=rvts2>On Windows, this specifies a .ico file to use as the icon for this binary.&nbsp; If no Windows Icon is specified, the wish binary will have the same icon as the original installer.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/InstallWrappedScript.html.


































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Install Wrapped Script</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Install Wrapped Script">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Install Wrapped Script</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallWishBinary.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="UnpackStoredFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action takes a Tcl/Tk script and wraps it into a self-contained binary executable on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts5>The .tcl script is wrapped with the same installkit that built the installer.&nbsp; It uses the internal installkit::wrap command to wrap the script into its own executable.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Binary Name</span></p>
<p class=rvps1><span class=rvts2>This is the name of the target binary on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Company</span></p>
<p class=rvps1><span class=rvts2>On Windows, this specifies the Company name to store in the Windows Resource information of the file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Description</span></p>
<p class=rvps1><span class=rvts2>On Windows, this specifies the File Description to store in the Windows Resource information of the file.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>File Version</span></p>
<p class=rvps1><span class=rvts2>On Windows, this specifies the File Version to store in the Windows Resource information of the file.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Include TWAPI</span></p>
<p class=rvps1><span class=rvts2>If this property is true, and TWAPI is included in the current installer, the TWAPI extension will be included in the wrapped script when it is built.&nbsp; The specified script will be changed to include some code at the top of the script to load the TWAPI extension on startup, so it is not necessary to package require the extension.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Installkit</span></p>
<p class=rvps1><span class=rvts2>The path to the installkit to be used to wrap the script.&nbsp; If this is left blank, the current running installer will be used as the base installkit.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Product Name</span></p>
<p class=rvps1><span class=rvts2>On Windows, this specifies the Product Name to store in the Windows Resource information of the file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Product Version</span></p>
<p class=rvps1><span class=rvts2>On Windows, this specifies the Product Version to store in the Windows Resource information of the file.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Tcl Startup Script</span></p>
<p class=rvps1><span class=rvts2>This is the .tcl script to wrap into the binary.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Windows Icon</span></p>
<p class=rvps1><span class=rvts2>On Windows, this specifies a .ico file to use as the icon for this binary.&nbsp; If no Windows Icon is specified, the wish binary will have the same icon as the original installer.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/LanguageAPI.html.






































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>LanguageAPI</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="LanguageAPI">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333399" face="Verdana"><b>LanguageAPI</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FindObjects.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="LoadMessageCatalog.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::LanguageAPI</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This API is used to manipulate and query language options in an installer or uninstaller.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>See options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-do</span></p>
<p class=rvps1><span class=rvts2>Specifies the action the API should take.&nbsp; Possible values are:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=118>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; setlanguage</span></p>
</td>
<td width=644>
<p class=rvps1><span class=rvts2>Set the current language of the installer.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-language</span></p>
<p class=rvps1><span class=rvts2>The name or code of a language to use.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/LaunchFile.html.






























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Launch File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Launch File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Launch File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GenerateUID.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="LaunchWebBrowser.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will launch the given file on the target system using a default method for the file type of the given file.&nbsp; InstallJammer uses a default method on the target platform to launch the file based on its file type.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts4>Files on UNIX are launched using xdg-open in the xdg-utils package that is part of the portland project by freedesktop.org.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Arguments</span></p>
<p class=rvps1><span class=rvts2>A list of arguments to pass on the command line when launching this file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Name</span></p>
<p class=rvps1><span class=rvts2>The name of the file on the target system to launch.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Wait for Program</span></p>
<p class=rvps1><span class=rvts2>Whether InstallJammer should wait for the program to finish and exit before continuing with the rest of the install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Working Directory</span></p>
<p class=rvps1><span class=rvts2>If this property is not null, InstallJammer will change directory to this directory before launching the file.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/LaunchWebBrowser.html.
















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Launch Web Browser</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Launch Web Browser">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Launch Web Browser</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="LaunchFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="LogDebugMessage.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will launch a web browser to the specified URL on the target system.&nbsp; InstallJammer will attempt to use the default web browser for the target operating system.&nbsp; If it fails to find a default web browser, InstallJammer will attempt to find a suitable browser.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>On Windows, the URL is launched using whatever the default browser is for the current user.&nbsp; On UNIX, if the desktop environment is KDE or Gnome, the default method for launching a URL will be used.&nbsp; If that method fails, or if the desktop is some other window manager, this action will attempt to find a suitable web browser based on environment and known browsers.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts4>URLs on UNIX are launched using xdg-open from the xdg-utils package that is part of the portland project by freedesktop.org.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>URL</span></p>
<p class=rvps1><span class=rvts2>The URL to point the web browser to when it launches.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/License.html.


























































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>License</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="License">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>License</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="Welcome.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="Credits.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>InstallJammer is licensed under the GNU General Public License.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>SPECIAL EXCEPTION FOR INSTALLERS</span><span class=rvts2>:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The binary installkit and InstallJammer code that is embedded</span></p>
<p class=rvps1><span class=rvts2>in each installer is built using code from InstallJammer and contains</span></p>
<p class=rvps1><span class=rvts2>code that falls under my copyright.&nbsp; The terms of the GPL still apply</span></p>
<p class=rvps1><span class=rvts2>to the code contained in the installers.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Hereby, Damon Courtney grants you special permission to freely use</span></p>
<p class=rvps1><span class=rvts2>and distribute any installer built with InstallJammer (including commercial</span></p>
<p class=rvps1><span class=rvts2>ones) without having to make available the source code of InstallJammer</span></p>
<p class=rvps1><span class=rvts2>or any code that is contained within your installer.&nbsp; Any changes made to</span></p>
<p class=rvps1><span class=rvts2>the InstallJammer or the installkit source code must still follow the GPL</span></p>
<p class=rvps1><span class=rvts2>license.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; GNU GENERAL PUBLIC LICENSE</span></p>
<p class=rvps1><span class=rvts2> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Version 2, June 1991</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2> Copyright (C) 1989, 1991 Free Software Foundation, Inc.,</span></p>
<p class=rvps1><span class=rvts2> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA</span></p>
<p class=rvps1><span class=rvts2> Everyone is permitted to copy and distribute verbatim copies</span></p>
<p class=rvps1><span class=rvts2> of this license document, but changing it is not allowed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; Preamble</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; The licenses for most software are designed to take away your</span></p>
<p class=rvps1><span class=rvts2>freedom to share and change it.&nbsp; By contrast, the GNU General Public</span></p>
<p class=rvps1><span class=rvts2>License is intended to guarantee your freedom to share and change free</span></p>
<p class=rvps1><span class=rvts2>software--to make sure the software is free for all its users.&nbsp; This</span></p>
<p class=rvps1><span class=rvts2>General Public License applies to most of the Free Software</span></p>
<p class=rvps1><span class=rvts2>Foundation's software and to any other program whose authors commit to</span></p>
<p class=rvps1><span class=rvts2>using it.&nbsp; (Some other Free Software Foundation software is covered by</span></p>
<p class=rvps1><span class=rvts2>the GNU Lesser General Public License instead.)&nbsp; You can apply it to</span></p>
<p class=rvps1><span class=rvts2>your programs, too.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; When we speak of free software, we are referring to freedom, not</span></p>
<p class=rvps1><span class=rvts2>price.&nbsp; Our General Public Licenses are designed to make sure that you</span></p>
<p class=rvps1><span class=rvts2>have the freedom to distribute copies of free software (and charge for</span></p>
<p class=rvps1><span class=rvts2>this service if you wish), that you receive source code or can get it</span></p>
<p class=rvps1><span class=rvts2>if you want it, that you can change the software or use pieces of it</span></p>
<p class=rvps1><span class=rvts2>in new free programs; and that you know you can do these things.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; To protect your rights, we need to make restrictions that forbid</span></p>
<p class=rvps1><span class=rvts2>anyone to deny you these rights or to ask you to surrender the rights.</span></p>
<p class=rvps1><span class=rvts2>These restrictions translate to certain responsibilities for you if you</span></p>
<p class=rvps1><span class=rvts2>distribute copies of the software, or if you modify it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; For example, if you distribute copies of such a program, whether</span></p>
<p class=rvps1><span class=rvts2>gratis or for a fee, you must give the recipients all the rights that</span></p>
<p class=rvps1><span class=rvts2>you have.&nbsp; You must make sure that they, too, receive or can get the</span></p>
<p class=rvps1><span class=rvts2>source code.&nbsp; And you must show them these terms so they know their</span></p>
<p class=rvps1><span class=rvts2>rights.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; We protect your rights with two steps: (1) copyright the software, and</span></p>
<p class=rvps1><span class=rvts2>(2) offer you this license which gives you legal permission to copy,</span></p>
<p class=rvps1><span class=rvts2>distribute and/or modify the software.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; Also, for each author's protection and ours, we want to make certain</span></p>
<p class=rvps1><span class=rvts2>that everyone understands that there is no warranty for this free</span></p>
<p class=rvps1><span class=rvts2>software.&nbsp; If the software is modified by someone else and passed on, we</span></p>
<p class=rvps1><span class=rvts2>want its recipients to know that what they have is not the original, so</span></p>
<p class=rvps1><span class=rvts2>that any problems introduced by others will not reflect on the original</span></p>
<p class=rvps1><span class=rvts2>authors' reputations.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; Finally, any free program is threatened constantly by software</span></p>
<p class=rvps1><span class=rvts2>patents.&nbsp; We wish to avoid the danger that redistributors of a free</span></p>
<p class=rvps1><span class=rvts2>program will individually obtain patent licenses, in effect making the</span></p>
<p class=rvps1><span class=rvts2>program proprietary.&nbsp; To prevent this, we have made it clear that any</span></p>
<p class=rvps1><span class=rvts2>patent must be licensed for everyone's free use or not licensed at all.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; The precise terms and conditions for copying, distribution and</span></p>
<p class=rvps1><span class=rvts2>modification follow.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; GNU GENERAL PUBLIC LICENSE</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp; TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 0. This License applies to any program or other work which contains</span></p>
<p class=rvps1><span class=rvts2>a notice placed by the copyright holder saying it may be distributed</span></p>
<p class=rvps1><span class=rvts2>under the terms of this General Public License.&nbsp; The "Program", below,</span></p>
<p class=rvps1><span class=rvts2>refers to any such program or work, and a "work based on the Program"</span></p>
<p class=rvps1><span class=rvts2>means either the Program or any derivative work under copyright law:</span></p>
<p class=rvps1><span class=rvts2>that is to say, a work containing the Program or a portion of it,</span></p>
<p class=rvps1><span class=rvts2>either verbatim or with modifications and/or translated into another</span></p>
<p class=rvps1><span class=rvts2>language.&nbsp; (Hereinafter, translation is included without limitation in</span></p>
<p class=rvps1><span class=rvts2>the term "modification".)&nbsp; Each licensee is addressed as "you".</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Activities other than copying, distribution and modification are not</span></p>
<p class=rvps1><span class=rvts2>covered by this License; they are outside its scope.&nbsp; The act of</span></p>
<p class=rvps1><span class=rvts2>running the Program is not restricted, and the output from the Program</span></p>
<p class=rvps1><span class=rvts2>is covered only if its contents constitute a work based on the</span></p>
<p class=rvps1><span class=rvts2>Program (independent of having been made by running the Program).</span></p>
<p class=rvps1><span class=rvts2>Whether that is true depends on what the Program does.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 1. You may copy and distribute verbatim copies of the Program's</span></p>
<p class=rvps1><span class=rvts2>source code as you receive it, in any medium, provided that you</span></p>
<p class=rvps1><span class=rvts2>conspicuously and appropriately publish on each copy an appropriate</span></p>
<p class=rvps1><span class=rvts2>copyright notice and disclaimer of warranty; keep intact all the</span></p>
<p class=rvps1><span class=rvts2>notices that refer to this License and to the absence of any warranty;</span></p>
<p class=rvps1><span class=rvts2>and give any other recipients of the Program a copy of this License</span></p>
<p class=rvps1><span class=rvts2>along with the Program.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>You may charge a fee for the physical act of transferring a copy, and</span></p>
<p class=rvps1><span class=rvts2>you may at your option offer warranty protection in exchange for a fee.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 2. You may modify your copy or copies of the Program or any portion</span></p>
<p class=rvps1><span class=rvts2>of it, thus forming a work based on the Program, and copy and</span></p>
<p class=rvps1><span class=rvts2>distribute such modifications or work under the terms of Section 1</span></p>
<p class=rvps1><span class=rvts2>above, provided that you also meet all of these conditions:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; a) You must cause the modified files to carry prominent notices</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; stating that you changed the files and the date of any change.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; b) You must cause any work that you distribute or publish, that in</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; whole or in part contains or is derived from the Program or any</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; part thereof, to be licensed as a whole at no charge to all third</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; parties under the terms of this License.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; c) If the modified program normally reads commands interactively</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; when run, you must cause it, when started running for such</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; interactive use in the most ordinary way, to print or display an</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; announcement including an appropriate copyright notice and a</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; notice that there is no warranty (or else, saying that you provide</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; a warranty) and that users may redistribute the program under</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; these conditions, and telling the user how to view a copy of this</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; License.&nbsp; (Exception: if the Program itself is interactive but</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; does not normally print such an announcement, your work based on</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; the Program is not required to print an announcement.)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>These requirements apply to the modified work as a whole.&nbsp; If</span></p>
<p class=rvps1><span class=rvts2>identifiable sections of that work are not derived from the Program,</span></p>
<p class=rvps1><span class=rvts2>and can be reasonably considered independent and separate works in</span></p>
<p class=rvps1><span class=rvts2>themselves, then this License, and its terms, do not apply to those</span></p>
<p class=rvps1><span class=rvts2>sections when you distribute them as separate works.&nbsp; But when you</span></p>
<p class=rvps1><span class=rvts2>distribute the same sections as part of a whole which is a work based</span></p>
<p class=rvps1><span class=rvts2>on the Program, the distribution of the whole must be on the terms of</span></p>
<p class=rvps1><span class=rvts2>this License, whose permissions for other licensees extend to the</span></p>
<p class=rvps1><span class=rvts2>entire whole, and thus to each and every part regardless of who wrote it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Thus, it is not the intent of this section to claim rights or contest</span></p>
<p class=rvps1><span class=rvts2>your rights to work written entirely by you; rather, the intent is to</span></p>
<p class=rvps1><span class=rvts2>exercise the right to control the distribution of derivative or</span></p>
<p class=rvps1><span class=rvts2>collective works based on the Program.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>In addition, mere aggregation of another work not based on the Program</span></p>
<p class=rvps1><span class=rvts2>with the Program (or with a work based on the Program) on a volume of</span></p>
<p class=rvps1><span class=rvts2>a storage or distribution medium does not bring the other work under</span></p>
<p class=rvps1><span class=rvts2>the scope of this License.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 3. You may copy and distribute the Program (or a work based on it,</span></p>
<p class=rvps1><span class=rvts2>under Section 2) in object code or executable form under the terms of</span></p>
<p class=rvps1><span class=rvts2>Sections 1 and 2 above provided that you also do one of the following:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; a) Accompany it with the complete corresponding machine-readable</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; source code, which must be distributed under the terms of Sections</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; 1 and 2 above on a medium customarily used for software interchange; or,</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; b) Accompany it with a written offer, valid for at least three</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; years, to give any third party, for a charge no more than your</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; cost of physically performing source distribution, a complete</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; machine-readable copy of the corresponding source code, to be</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; distributed under the terms of Sections 1 and 2 above on a medium</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; customarily used for software interchange; or,</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; c) Accompany it with the information you received as to the offer</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; to distribute corresponding source code.&nbsp; (This alternative is</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; allowed only for noncommercial distribution and only if you</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; received the program in object code or executable form with such</span></p>
<p class=rvps1><span class=rvts2>&nbsp;&nbsp;&nbsp; an offer, in accord with Subsection b above.)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The source code for a work means the preferred form of the work for</span></p>
<p class=rvps1><span class=rvts2>making modifications to it.&nbsp; For an executable work, complete source</span></p>
<p class=rvps1><span class=rvts2>code means all the source code for all modules it contains, plus any</span></p>
<p class=rvps1><span class=rvts2>associated interface definition files, plus the scripts used to</span></p>
<p class=rvps1><span class=rvts2>control compilation and installation of the executable.&nbsp; However, as a</span></p>
<p class=rvps1><span class=rvts2>special exception, the source code distributed need not include</span></p>
<p class=rvps1><span class=rvts2>anything that is normally distributed (in either source or binary</span></p>
<p class=rvps1><span class=rvts2>form) with the major components (compiler, kernel, and so on) of the</span></p>
<p class=rvps1><span class=rvts2>operating system on which the executable runs, unless that component</span></p>
<p class=rvps1><span class=rvts2>itself accompanies the executable.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If distribution of executable or object code is made by offering</span></p>
<p class=rvps1><span class=rvts2>access to copy from a designated place, then offering equivalent</span></p>
<p class=rvps1><span class=rvts2>access to copy the source code from the same place counts as</span></p>
<p class=rvps1><span class=rvts2>distribution of the source code, even though third parties are not</span></p>
<p class=rvps1><span class=rvts2>compelled to copy the source along with the object code.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 4. You may not copy, modify, sublicense, or distribute the Program</span></p>
<p class=rvps1><span class=rvts2>except as expressly provided under this License.&nbsp; Any attempt</span></p>
<p class=rvps1><span class=rvts2>otherwise to copy, modify, sublicense or distribute the Program is</span></p>
<p class=rvps1><span class=rvts2>void, and will automatically terminate your rights under this License.</span></p>
<p class=rvps1><span class=rvts2>However, parties who have received copies, or rights, from you under</span></p>
<p class=rvps1><span class=rvts2>this License will not have their licenses terminated so long as such</span></p>
<p class=rvps1><span class=rvts2>parties remain in full compliance.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 5. You are not required to accept this License, since you have not</span></p>
<p class=rvps1><span class=rvts2>signed it.&nbsp; However, nothing else grants you permission to modify or</span></p>
<p class=rvps1><span class=rvts2>distribute the Program or its derivative works.&nbsp; These actions are</span></p>
<p class=rvps1><span class=rvts2>prohibited by law if you do not accept this License.&nbsp; Therefore, by</span></p>
<p class=rvps1><span class=rvts2>modifying or distributing the Program (or any work based on the</span></p>
<p class=rvps1><span class=rvts2>Program), you indicate your acceptance of this License to do so, and</span></p>
<p class=rvps1><span class=rvts2>all its terms and conditions for copying, distributing or modifying</span></p>
<p class=rvps1><span class=rvts2>the Program or works based on it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 6. Each time you redistribute the Program (or any work based on the</span></p>
<p class=rvps1><span class=rvts2>Program), the recipient automatically receives a license from the</span></p>
<p class=rvps1><span class=rvts2>original licensor to copy, distribute or modify the Program subject to</span></p>
<p class=rvps1><span class=rvts2>these terms and conditions.&nbsp; You may not impose any further</span></p>
<p class=rvps1><span class=rvts2>restrictions on the recipients' exercise of the rights granted herein.</span></p>
<p class=rvps1><span class=rvts2>You are not responsible for enforcing compliance by third parties to</span></p>
<p class=rvps1><span class=rvts2>this License.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 7. If, as a consequence of a court judgment or allegation of patent</span></p>
<p class=rvps1><span class=rvts2>infringement or for any other reason (not limited to patent issues),</span></p>
<p class=rvps1><span class=rvts2>conditions are imposed on you (whether by court order, agreement or</span></p>
<p class=rvps1><span class=rvts2>otherwise) that contradict the conditions of this License, they do not</span></p>
<p class=rvps1><span class=rvts2>excuse you from the conditions of this License.&nbsp; If you cannot</span></p>
<p class=rvps1><span class=rvts2>distribute so as to satisfy simultaneously your obligations under this</span></p>
<p class=rvps1><span class=rvts2>License and any other pertinent obligations, then as a consequence you</span></p>
<p class=rvps1><span class=rvts2>may not distribute the Program at all.&nbsp; For example, if a patent</span></p>
<p class=rvps1><span class=rvts2>license would not permit royalty-free redistribution of the Program by</span></p>
<p class=rvps1><span class=rvts2>all those who receive copies directly or indirectly through you, then</span></p>
<p class=rvps1><span class=rvts2>the only way you could satisfy both it and this License would be to</span></p>
<p class=rvps1><span class=rvts2>refrain entirely from distribution of the Program.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If any portion of this section is held invalid or unenforceable under</span></p>
<p class=rvps1><span class=rvts2>any particular circumstance, the balance of the section is intended to</span></p>
<p class=rvps1><span class=rvts2>apply and the section as a whole is intended to apply in other</span></p>
<p class=rvps1><span class=rvts2>circumstances.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>It is not the purpose of this section to induce you to infringe any</span></p>
<p class=rvps1><span class=rvts2>patents or other property right claims or to contest validity of any</span></p>
<p class=rvps1><span class=rvts2>such claims; this section has the sole purpose of protecting the</span></p>
<p class=rvps1><span class=rvts2>integrity of the free software distribution system, which is</span></p>
<p class=rvps1><span class=rvts2>implemented by public license practices.&nbsp; Many people have made</span></p>
<p class=rvps1><span class=rvts2>generous contributions to the wide range of software distributed</span></p>
<p class=rvps1><span class=rvts2>through that system in reliance on consistent application of that</span></p>
<p class=rvps1><span class=rvts2>system; it is up to the author/donor to decide if he or she is willing</span></p>
<p class=rvps1><span class=rvts2>to distribute software through any other system and a licensee cannot</span></p>
<p class=rvps1><span class=rvts2>impose that choice.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This section is intended to make thoroughly clear what is believed to</span></p>
<p class=rvps1><span class=rvts2>be a consequence of the rest of this License.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 8. If the distribution and/or use of the Program is restricted in</span></p>
<p class=rvps1><span class=rvts2>certain countries either by patents or by copyrighted interfaces, the</span></p>
<p class=rvps1><span class=rvts2>original copyright holder who places the Program under this License</span></p>
<p class=rvps1><span class=rvts2>may add an explicit geographical distribution limitation excluding</span></p>
<p class=rvps1><span class=rvts2>those countries, so that distribution is permitted only in or among</span></p>
<p class=rvps1><span class=rvts2>countries not thus excluded.&nbsp; In such case, this License incorporates</span></p>
<p class=rvps1><span class=rvts2>the limitation as if written in the body of this License.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 9. The Free Software Foundation may publish revised and/or new versions</span></p>
<p class=rvps1><span class=rvts2>of the General Public License from time to time.&nbsp; Such new versions will</span></p>
<p class=rvps1><span class=rvts2>be similar in spirit to the present version, but may differ in detail to</span></p>
<p class=rvps1><span class=rvts2>address new problems or concerns.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Each version is given a distinguishing version number.&nbsp; If the Program</span></p>
<p class=rvps1><span class=rvts2>specifies a version number of this License which applies to it and "any</span></p>
<p class=rvps1><span class=rvts2>later version", you have the option of following the terms and conditions</span></p>
<p class=rvps1><span class=rvts2>either of that version or of any later version published by the Free</span></p>
<p class=rvps1><span class=rvts2>Software Foundation.&nbsp; If the Program does not specify a version number of</span></p>
<p class=rvps1><span class=rvts2>this License, you may choose any version ever published by the Free Software</span></p>
<p class=rvps1><span class=rvts2>Foundation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 10. If you wish to incorporate parts of the Program into other free</span></p>
<p class=rvps1><span class=rvts2>programs whose distribution conditions are different, write to the author</span></p>
<p class=rvps1><span class=rvts2>to ask for permission.&nbsp; For software which is copyrighted by the Free</span></p>
<p class=rvps1><span class=rvts2>Software Foundation, write to the Free Software Foundation; we sometimes</span></p>
<p class=rvps1><span class=rvts2>make exceptions for this.&nbsp; Our decision will be guided by the two goals</span></p>
<p class=rvps1><span class=rvts2>of preserving the free status of all derivatives of our free software and</span></p>
<p class=rvps1><span class=rvts2>of promoting the sharing and reuse of software generally.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; NO WARRANTY</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY</span></p>
<p class=rvps1><span class=rvts2>FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.&nbsp; EXCEPT WHEN</span></p>
<p class=rvps1><span class=rvts2>OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES</span></p>
<p class=rvps1><span class=rvts2>PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED</span></p>
<p class=rvps1><span class=rvts2>OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF</span></p>
<p class=rvps1><span class=rvts2>MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.&nbsp; THE ENTIRE RISK AS</span></p>
<p class=rvps1><span class=rvts2>TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.&nbsp; SHOULD THE</span></p>
<p class=rvps1><span class=rvts2>PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,</span></p>
<p class=rvps1><span class=rvts2>REPAIR OR CORRECTION.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&nbsp; 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING</span></p>
<p class=rvps1><span class=rvts2>WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR</span></p>
<p class=rvps1><span class=rvts2>REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,</span></p>
<p class=rvps1><span class=rvts2>INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING</span></p>
<p class=rvps1><span class=rvts2>OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED</span></p>
<p class=rvps1><span class=rvts2>TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY</span></p>
<p class=rvps1><span class=rvts2>YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER</span></p>
<p class=rvps1><span class=rvts2>PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE</span></p>
<p class=rvps1><span class=rvts2>POSSIBILITY OF SUCH DAMAGES.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; END OF TERMS AND CONDITIONS</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/LoadMessageCatalog.html.










































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>LoadMessageCatalog</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="LoadMessageCatalog">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>LoadMessageCatalog</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="LanguageAPI.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PromptForDirectory.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::LoadMessageCatalog</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Load a message catalog file into the current installer.&nbsp; This will overwrite text that is already stored in a message catalog or create new message catalogs for languages that do not already exist.&nbsp; Loading messages for a language that does not exist will not add the language to the installer.&nbsp; Use the </span><a class=rvts5 href="AddLanguage.html">AddLanguage</a><span class=rvts2> API for that.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>A list of language codes used.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-data &lt;data string&gt;</span></p>
<p class=rvps1><span class=rvts2>This data will be parsed just like the contents of a message catalog.&nbsp; This option can be used to load messages that are read from some other location instead of loading from a file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-dir &lt;directory&gt;</span></p>
<p class=rvps1><span class=rvts2>This option specifies a directory to be searched for *.msg files.&nbsp; Each file in the directory must be named after its language code, and each file will be loaded based on the language code and contents of the file.&nbsp; Loading a message catalog for a language that does not exist will not result in an error, but the language will not be added to the running installer.&nbsp; Use the </span><a class=rvts6 href="AddLanguage.html">AddLanguage</a><span class=rvts2> API for that.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-encoding &lt;encoding&gt;</span></p>
<p class=rvps1><span class=rvts2>This option specifies the encoding to use when reading a message catalog from a file or from data.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-file &lt;filename&gt;</span></p>
<p class=rvps1><span class=rvts2>The name of a message catalog file to load.&nbsp; If the name of the file is &lt;code&gt;.msg where &lt;code&gt; is a valid language code in the current installer, the message catalog will be loaded into that language.&nbsp; If the file does not match a language in the installer, you must specify the -language option to tell InstallJammer which language to add the messages to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-language &lt;language or language code&gt;</span></p>
<p class=rvps1><span class=rvts2>The language to load the message catalog into.&nbsp; If this option is specified, it will override any other option that InstallJammer might use to determine the language from the file name.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-object &lt;object ID or alias&gt;</span></p>
<p class=rvps1><span class=rvts2>This option specifies the ID or alias of a file object contained within the installer that should be loaded as a message catalog.&nbsp; This allows you to package message catalogs into your installer along with the rest of your files and then load them as-needed at runtime.&nbsp; If the name of the file does not match a language in the installer, you must specify the -language option to tell InstallJammer which language to add the messages to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>The following example loads a message catalog packaged within the installer with an alias of Messages File and adds the messages to the English language.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::AddLanguage -language English -object "Messages File"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following example loads any *.msg file from a directory called msgs located in the same directory as the installer.&nbsp; These files would most likely be included with a release on CD.&nbsp; Notice the -subst 1 option that tells the API to substitute the options passed for virtual text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::AddLanguage -subst 1 -dir &lt;%InstallSource%&gt;/msgs</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following example loads a single file located in the directory with the installer into the Spanish language.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::AddLanguage -subst 1 -file &lt;%InstallSource%&gt;/es.msg</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/LocateJavaRuntime.html.
































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Locate Java Runtime</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Locate Java Runtime">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Locate Java Runtime</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GetJavaProperty.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="InstallDesktopShortcut.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action attempts to locate the most suitable Java Runtime Environment (JRE) available on the target system.&nbsp; It does this by looking at some default paths and environment variables on the system as well as allowing you to specify locations to check.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If the action successfully finds a suitable JRE, the following virtual text variable are set as a result:</span>
<br><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%JavaAvailableVersions%&gt;</span></p>
<p class=rvps1><span class=rvts2>A list of the available versions found on the target system before finding the correct one.&nbsp; Once an acceptable JRE is found, InstallJammer stops looking, so this list will only include up to and including the JRE found that matches our needs.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%JavaExecutable%&gt;</span></p>
<p class=rvps1><span class=rvts2>The full path to the java executable (usually &lt;%JavaHome%&gt;/bin/java).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%JavaFound%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if a Java runtime was found or false if none was found.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%JavaHome%&gt;</span></p>
<p class=rvps1><span class=rvts2>The Java home directory.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%JavaVersion%&gt;</span></p>
<p class=rvps1><span class=rvts2>The version of the Java runtime found. (1.4.2_11, etc...)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%JavaVersionMajor%&gt;</span></p>
<p class=rvps1><span class=rvts2>The major version of the Java runtime found. (1.4, 1.5, etc...)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%JavaVersionMinor%&gt;</span></p>
<p class=rvps1><span class=rvts2>The minor version of the Java runtime found. (1.4.2, 1.6.0, etc...)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%JavacExecutable%&gt;</span></p>
<p class=rvps1><span class=rvts2>The full path to the javac executable if it is found.&nbsp; If a javac executable is not found, this virtual text will not be set.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%JavawExecutable%&gt;</span></p>
<p class=rvps1><span class=rvts2>The full path to the javaw executable if it is found.&nbsp; If not found, this variable will point to the main java executable instead.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Maximum Version</span></p>
<p class=rvps1><span class=rvts2>This property tells Installjammer the maximum version of the JRE you will accept.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minimum Version</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer the minimum version of the JRE you will accept.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Require JDK</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the action will require that a full JDK (Java Development Kit) be installed and not just a JRE (Java Runtime Environment).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts5>This will make the installer search for the existence of a javac (the Java compiler that is lacking in a JRE installation) binary to determine if the installation is a JDK.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Search Path</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer how to search for the JRE.&nbsp; The value is a list of paths to check for a suitable java installation (separated by ;).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If </span><span class=rvts3>Default Search Path</span><span class=rvts2> is included as a path, InstallJammer will use defaults like environment variables and the user's PATH on the target system to try and find the JRE.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts5>The Default Search Path searches in the following order:</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts5>JAVA_HOME environment variable</span></li>
<li class=rvps1><span class=rvts5>JAVAHOME environment variable</span></li>
<li class=rvps1><span class=rvts5>JDK_HOME environment variable</span></li>
<li class=rvps1><span class=rvts5>JRE_HOME environment variable</span></li>
<li class=rvps1><span class=rvts5>JAVA_ROOT environment variable</span></li>
<li class=rvps1><span class=rvts5>JAVA_BINDIR environment variable</span></li>
<li class=rvps1><span class=rvts5>PATH environment variable</span></li>
<li class=rvps1><span class=rvts5>Windows registry (Windows only)</span></li>
<li class=rvps1><span class=rvts5>Program Files/Java/jre* (Windows only)</span></li>
<li class=rvps1><span class=rvts5>/usr/java/jdk (UNIX only)</span></li>
<li class=rvps1><span class=rvts5>/usr/lib/java (UNIX only)</span></li>
<li class=rvps1><span class=rvts5>/usr/lib/jvm (UNIX only)</span></li>
<li class=rvps1><span class=rvts5>/usr/lib/jvm/jre (UNIX only)</span></li>
<li class=rvps1><span class=rvts5>/usr/lib/java-1.4.0 (UNIX only)</span></li>
<li class=rvps1><span class=rvts5>/usr/lib/java-1.4.1 (UNIX only)</span></li>
<li class=rvps1><span class=rvts5>/usr/lib/java-1.4.2 (UNIX only)</span></li>
<li class=rvps1><span class=rvts5>/usr/lib/java-1.5.0 (UNIX only)</span></li>
</ul>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If </span><span class=rvts3>Prompt User</span><span class=rvts2> is included as a path, InstallJammer will check all of the other paths in order, and upon reaching Prompt User, it will prompt the user asking them to specify the location of the runtime environment.&nbsp; This is usually best left as the last path so that all of the other directories will be checked before finally prompting the user when no JRE has been found.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/LogDebugMessage.html.


















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Log Debug Message</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Log Debug Message">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Log Debug Message</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="LaunchWebBrowser.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="MessageBox.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will log a message to the debug log and to the console when an installer is run in debug mode.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Message</span></p>
<p class=rvps1><span class=rvts2>The message to output to the debug log.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/MessageBox.html.




























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Message Box</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Message Box">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Message Box</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="LogDebugMessage.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="MessagePanel.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will pop up a message box that requires the user's attention.&nbsp; It can be used simply to give the user notice of something, or it can be used to ask the user a question and get an answer.&nbsp; Once posted, InstallJammer will not continue with the install until the user has clicked a button to close the message box.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Default Button</span></p>
<p class=rvps1><span class=rvts2>The button to focus on by default.&nbsp; This is the default action if the user simply hits Enter when the message box pops up.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon</span></p>
<p class=rvps1><span class=rvts2>A choice of icon to display in the message box giving the user an indication what type of message this is.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Type</span></p>
<p class=rvps1><span class=rvts2>The type of message box to display.&nbsp; There are several common types to choose from.&nbsp; Each type will display with the given list of buttons.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text&nbsp; Field</span></p>
<p class=rvps1><span class=rvts2>The virtual text variable to hold the result of the message box.&nbsp; This variable will contain the name of the button the user clicked on.&nbsp; The name of a button is the text displayed on the button in all lowercase.&nbsp; So, if the user clicks Yes, the virtual text is set to yes.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/MessagePanel.html.






































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Message Panel</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Message Panel">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Message Panel</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="MessageBox.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ModifyObject.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>A message panel is a borderless, buttonless panel that pops up to display some message to the user.&nbsp; This is usually done when the installer is doing something that may take a moment, and you want the user to see what is happening.&nbsp; Once a message panel is posted, unless it is given a timeout, it must be destroyed using a </span><a class=rvts4 href="DestroyWidget.html">Destroy Widget</a><span class=rvts2> action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Anchor</span></p>
<p class=rvps1><span class=rvts2>The position on the screen to display the message panel.&nbsp; Default is the center of the screen.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Grab Focus</span></p>
<p class=rvps1><span class=rvts2>This tells InstallJammer to grab the focus from the user so that they can't interact with anything else in the installer while the message panel is on the screen.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Height</span></p>
<p class=rvps1><span class=rvts2>The height of the message panel in pixels.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Image</span></p>
<p class=rvps1><span class=rvts2>An icon to display on the left side of the message panel.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Image Pad X</span></p>
<p class=rvps1><span class=rvts2>How many pixels to pad the image on the left and right from the rest of the panel.&nbsp; A single number means to pad the image on both sides by that amount.&nbsp; Two numbers means to pad the image on the left the first number of pixels and pad the right the second number of pixels.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Image Pad Y</span></p>
<p class=rvps1><span class=rvts2>How many pixels to pad the image on the top and bottom from the rest of the panel.&nbsp; A single number means to pad the image on both sides by that amount.&nbsp; Two numbers means to pad the image on the top the first number of pixels and pad the bottom the second number of pixels.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Label Anchor</span></p>
<p class=rvps1><span class=rvts2>The anchor for the text in the label.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Label Pad X</span></p>
<p class=rvps1><span class=rvts2>How many pixels to pad the label on the left and right from the rest of the panel.&nbsp; A single number means to pad the label on both sides by that amount.&nbsp; Two numbers means to pad the label on the left the first number of pixels and pad the right the second number of pixels.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Label Pad Y</span></p>
<p class=rvps1><span class=rvts2>How many pixels to pad the label on the top and bottom from the rest of the panel.&nbsp; A single number means to pad the label on both sides by that amount.&nbsp; Two numbers means to pad the label on the top the first number of pixels and pad the bottom the second number of pixels.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Timeout</span></p>
<p class=rvps1><span class=rvts2>The number of seconds the panel should stay on the screen.&nbsp; If this value is 0, the panel will stay on the screen until it is destroyed with a </span><a class=rvts4 href="DestroyWidget.html">Destroy Widget</a><span class=rvts2> action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Width</span></p>
<p class=rvps1><span class=rvts2>The width of the message panel in pixels.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ModifyObject.html.
























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Modify Object</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Modify Object">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Modify Object</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="MessagePanel.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PauseInstall.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to modify the properties of any object in an installer.&nbsp; See </span><a class=rvts4 href="ObjectTypes.html">Object Types</a><span class=rvts2> for a description of the available object types.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Object State</span></p>
<p class=rvps1><span class=rvts2>If specified, this says that the given object should be Active or Inactive.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Object ID</span></p>
<p class=rvps1><span class=rvts2>The ID or alias of the object to be modified.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ModifyObject1.html.














































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>ModifyObject</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="ModifyObject">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>ModifyObject</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="GetActionGroup.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SetPlatformProperty.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::BuilderAPI::ModifyObject</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Mark an object as active or inactive.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-active</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the given object will be made active.&nbsp; If it false, the object will be deactivated.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-object</span></p>
<p class=rvps1><span class=rvts2>The alias or object ID of the object to modify.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ModifyWidget.html.






















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Modify Widget</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Modify Widget">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Modify Widget</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FocusOnWidget.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="MoveForward.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will modify the text or state of a given widget or list of widgets on the current pane.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>State</span></p>
<p class=rvps1><span class=rvts2>The state the modified widget should be.&nbsp; Normal means that the widget is active, and the user can interact with it.&nbsp; Disabled means that the widget is inactive, and the user cannot manipulate it.&nbsp; Disabled widgets are usually shown as "greyed out" to reflect that they are disabled.&nbsp; Hidden means that the widget should be removed from the pane entirely.&nbsp; A hidden widget can be restored by modifying its state back to normal.&nbsp; Readonly is a state that can be applied to entry and text widgets and means that the widget will appear as normal, but the user will not be able to enter any data.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Text</span></p>
<p class=rvps1><span class=rvts2>The text the modified widget should display.&nbsp; This will modify all the listed widgets and change their text to the given value.&nbsp; If left blank, the text will not be modified.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Widget</span></p>
<p class=rvps1><span class=rvts2>This property specifies a single widget on the current pane, or a list of widgets separated by a semicolon (;).</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/MoveForward.html.






























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Move Forward</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Move Forward">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Move Forward</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ModifyWidget.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="MoveToPane.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action causes InstallJammer to move forward to the next pane in the install.&nbsp; If there are no more panes to be displayed, it will cause InstallJammer to exit with a Finish condition.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/MoveToPane.html.












































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Move to Pane</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Move to Pane">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Move to Pane</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="MoveForward.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PopulateComponents.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action causes InstallJammer to jump forward or backward through the installer to the specified pane.&nbsp; When this action moves to the given pane, that pane will automatically be added to the backwards order of the wizard so that the user will see it if they go back through the wizard.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>If the pane being moved to is the current pane, the actions of the pane will be executed from the start, effectively reloading the current pane.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Pane</span></p>
<p class=rvps1><span class=rvts2>The ID or alias of the pane to jump to.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ObjectIsActiveCondition.html.






















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Object Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Object is Active Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Object Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ExecuteScriptCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ScriptCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if an object in the (un)install is currently active.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Object ID</span></p>
<p class=rvps1><span class=rvts2>The ID or alias of the object you are checking.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=143>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; exists</span></p>
</td>
<td width=619>
<p class=rvps1><span class=rvts2>True if the object exists.</span></p>
</td>
</tr>
<tr valign=top>
<td width=143>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not exist</span></p>
</td>
<td width=619>
<p class=rvps1><span class=rvts2>True if the object does not exist.</span></p>
</td>
</tr>
<tr valign=top>
<td width=143>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is active</span></p>
</td>
<td width=619>
<p class=rvps1><span class=rvts2>True if the object is active.</span></p>
</td>
</tr>
<tr valign=top>
<td width=143>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is not active</span></p>
</td>
<td width=619>
<p class=rvps1><span class=rvts2>True if the object is inactive.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ObjectTypes.html.


























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Object Types</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Object Types">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
}
span.rvts4
{
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: none;
}
a.rvts5:hover { color: #0000ff; }
span.rvts6
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts7
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts8
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts9, span.rvts9
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts9:hover { color: #0000ff; }
a.rvts10, span.rvts10
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts10:hover { color: #0000ff; }
a.rvts11, span.rvts11
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts11:hover { color: #0000ff; }
a.rvts12, span.rvts12
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts12:hover { color: #0000ff; }
a.rvts13, span.rvts13
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts13:hover { color: #0000ff; }
a.rvts14, span.rvts14
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts14:hover { color: #0000ff; }
a.rvts15, span.rvts15
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts15:hover { color: #0000ff; }
a.rvts16, span.rvts16
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts16:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Object Types</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="TestUninstaller.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="StandardProperties.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>InstallJammer uses objects to define various pieces of an install.&nbsp; Almost anything that is stored in your install is an object.&nbsp; They are usually identified as having an ID that is the unique name of the object.&nbsp; Below is a list of object types and a brief description of what they do.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Action</span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts9 href="WhatAreActions.html">What are Actions?</a></p>
<p class=rvps1><span class=rvts7><br></span></p>
<p class=rvps1><span class=rvts8>Action Group</span></p>
<p class=rvps1><span class=rvts7>See </span><a class=rvts10 href="WhatAreActionGroups.html">What are Action Groups?</a></p>
<p class=rvps1><span class=rvts7><br></span></p>
<p class=rvps1><span class=rvts8>Component</span></p>
<p class=rvps1><span class=rvts7>See </span><a class=rvts11 href="Components.html">Components</a><span class=rvts7>.</span></p>
<p class=rvps1><span class=rvts8><br></span></p>
<p class=rvps1><span class=rvts8>Condition</span></p>
<p class=rvps1><span class=rvts7>See </span><a class=rvts12 href="WhatAreConditions.html">What are Conditions?</a></p>
<p class=rvps1><span class=rvts7><br></span></p>
<p class=rvps1><span class=rvts8>File Group</span></p>
<p class=rvps1><span class=rvts7>See </span><a class=rvts13 href="GroupsAndFiles.html">Groups and Files</a><span class=rvts7>.</span></p>
<p class=rvps1><span class=rvts7><br></span></p>
<p class=rvps1><span class=rvts8>Files and Directories&nbsp; </span></p>
<p class=rvps1><span class=rvts7>See </span><a class=rvts14 href="FilesAndDirectories.html">Files and Directories</a><span class=rvts7>.</span></p>
<p class=rvps1><span class=rvts7><br></span></p>
<p class=rvps1><span class=rvts8>Pane</span></p>
<p class=rvps1><span class=rvts7>See </span><a class=rvts15 href="WhatArePanes.html">What are Panes?</a></p>
<p class=rvps1><span class=rvts7><br></span></p>
<p class=rvps1><span class=rvts8>Setup Type</span></p>
<p class=rvps1><span class=rvts7>See </span><a class=rvts16 href="SetupTypes.html">Setup Types</a><a class=rvts5 href="SetupTypes.html">.</a><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PackageAndArchiveInformation.html.




















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Package and Archive Information</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Package and Archive Information">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
}
span.rvts4
{
 font-family: 'Verdana';
}
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts6
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts7
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #ff0000;
}
a.rvts8, span.rvts8
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts8:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Package and Archive Information</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PlatformInformation.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GroupsAndFiles.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts6>Package Information</span></p>
<p class=rvps1><span class=rvts2>Package information can be used by you in your own installer, but its main use is by the actions in InstallJammer that register your application with the different packaging systems.&nbsp; Since most of the information is the same across package databases, this section provides an easy way to specify the information once and then let InstallJammer use the right bits for each different package system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>This information is used in the </span><a class=rvts8 href="RegisterPackage.html">Register Package</a><span class=rvts5> action.&nbsp; If you plan on registering your application with the system package manager, it is </span><span class=rvts7>highly recommended</span><span class=rvts5> that you fill in all the information for your package.&nbsp; Some package managers will not accept a package that is missing pieces of the following data.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Package Description</span></p>
<p class=rvps1><span class=rvts2>This is a long text description of your package.&nbsp; This can include multiple lines that describe what your application is and what it does.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Package License</span></p>
<p class=rvps1><span class=rvts2>This should be a one line description of the license your application uses.&nbsp; This is usually something very simple like: GPL, MPL, Apache, etc...</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Package Maintainer</span></p>
<p class=rvps1><span class=rvts2>This is a name and e-mail address of the person who maintains your application should you want to be contacted.&nbsp; This is in the form of:&nbsp; Person's Name &lt;email@address.com&gt;</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Package Name</span></p>
<p class=rvps1><span class=rvts2>The name your application will have in the package database.&nbsp; This should be all lowercase and short.&nbsp; It should not be the full name of your application.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Package Packager</span></p>
<p class=rvps1><span class=rvts2>The name and/or e-mail of the person who packages your application.&nbsp; This would be you, the person building the installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Package Release</span></p>
<p class=rvps1><span class=rvts2>The release version of your application.&nbsp; By default, InstallJammer uses the &lt;%PatchVersion%&gt; from your &lt;%InstallVersion%&gt; for this value.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Package Summary</span></p>
<p class=rvps1><span class=rvts2>This is a one line summary description of your package.&nbsp; This is the short description that briefly describes your package.&nbsp; The Package Description gives the long version.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Package Version</span></p>
<p class=rvps1><span class=rvts2>The version of your application.&nbsp; InstallJammer uses &lt;%MajorVersion%&gt;.&lt;%MinorVersion%&gt; from your &lt;%InstallVersion%&gt; by default since that's what most package managers expect.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Tar Archive Information</span></p>
<p class=rvps1><span class=rvts2>This section describes the information for building a tar file of your application.&nbsp; If this section is active, InstallJammer will build a tar file alongside your other platform-specific installers.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Active</span></p>
<p class=rvps1><span class=rvts2>If true, InstallJammer will build a tar file of your application when it builds the rest of your installers.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Compression Level</span></p>
<p class=rvps1><span class=rvts2>The level of gzip compression to use when compressing your tar file.&nbsp; If this is 0, the file will not be gzipped at all and will just be a plain tar file.&nbsp; You will want to remove the .gz from the output file name if you are not using compression.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Default Directory Permission Mask</span></p>
<p class=rvps1><span class=rvts4>The default permission mask to use when storing directories.&nbsp; If a separate permission has been set for the directory, it will override the default permission.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Default File Permission Mask</span></p>
<p class=rvps1><span class=rvts4>The default permission mask to use when storing files.&nbsp; If a separate permission has been set for the file, it will override the default permission.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Output File Name</span></p>
<p class=rvps1><span class=rvts4>The name of the tar file to output.&nbsp; This file will be in the output/ subdirectory of your project directory alongside your other installers.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text Map</span></p>
<p class=rvps1><span class=rvts4>This is a map of strings to use on each file and directory stored in the tar file.&nbsp; A string map is a list of pairs that specify that one string should be mapped to another.&nbsp; The default is to map all instances of &lt;%InstallDir%&gt; in the desination file name to &lt;%ShortAppName%&gt;.&nbsp; That means that all files being installed in &lt;%InstallDir%&gt; will end up in a subdirectory after your short application name with the rest of their directory structure intact.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts6>Zip Archive Information</span></p>
<p class=rvps1><span class=rvts2>This section describes the information for building a zip file of your application.&nbsp; If this section is active, InstallJammer will build a zip file alongside your other platform-specific installers.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Active</span></p>
<p class=rvps1><span class=rvts2>If true, InstallJammer will build a zip file of your application when it builds the rest of your installers.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts6>Compression Level</span></p>
<p class=rvps1><span class=rvts2>The level of compression to use when compressing your zip file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Output File Name</span></p>
<p class=rvps1><span class=rvts4>The name of the zip file to output.&nbsp; This file will be in the output/ subdirectory of your project directory alongside your other installers.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text Map</span></p>
<p class=rvps1><span class=rvts4>This is a map of strings to use on each file and directory stored in the zip file.&nbsp; A string map is a list of pairs that specify that one string should be mapped to another.&nbsp; The default is to map all instances of &lt;%InstallDir%&gt; in the desination file name to &lt;%ShortAppName%&gt;.&nbsp; That means that all files being installed in &lt;%InstallDir%&gt; will end up in a subdirectory after your short application name with the rest of their directory structure intact.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PackageTestCondition.html.




































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Package Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Package Test Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
span.rvts6
{
 font-family: 'Verdana';
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Package Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="EnvironmentVariableTestCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PortTestCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if a package is installed in the target system's default package manager.&nbsp; This condition will determine what the default package manager is for the target system and then attempt to determine if the given package is installed by querying the package manager.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts4>Currently-supported package systems are: DPKG and RPM.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts6><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=32>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=610>
<p class=rvps1><span class=rvts4>RPM will use 'rpm -q $package'</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>and</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>DPKG will use 'dpkg -s $package'</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>and then check the exit code.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=148>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is installed</span></p>
</td>
<td width=614>
<p class=rvps1><span class=rvts2>True if the package is installed.</span></p>
</td>
</tr>
<tr valign=top>
<td width=148>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is not installed</span></p>
</td>
<td width=614>
<p class=rvps1><span class=rvts2>True if the package is not installed.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Package</span></p>
<p class=rvps1><span class=rvts2>The name of the package to check.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PanesAndActions.html.
























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Panes and Actions</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Panes and Actions">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts5
{
 font-family: 'Verdana';
 font-weight: bold;
}
span.rvts6
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts7
{
 font-family: 'Verdana';
 color: #000000;
}
a.rvts8, span.rvts8
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts8:hover { color: #0000ff; }
a.rvts9, span.rvts9
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts9:hover { color: #0000ff; }
a.rvts10, span.rvts10
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts10:hover { color: #0000ff; }
a.rvts11, span.rvts11
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts11:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Panes and Actions</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SetupTypes.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CommandLineOptions.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>The Install / Uninstall Panes and Actions section of the install builder shows a tree of your install's user interface.&nbsp; The user interface is first defined by a set of possible install types.&nbsp; Underneath that is a list of all of the panes that are included in that install type.&nbsp; Each pane can have any number of actions that execute as the user moves through the install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Panes</span></p>
<p class=rvps1><span class=rvts2>Selecting a pane in the tree will bring up some information for that pane as well as properties that you can modify to customize the pane.&nbsp; See </span><a class=rvts8 href="WhatArePanes.html">What are Panes?</a><span class=rvts3> for more details.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Actions</span></p>
<p class=rvps1><span class=rvts3>Selecting an action in the tree will bring up some information for that action as well as properties that you can modify to customize the action.&nbsp; See </span><a class=rvts9 href="WhatAreActions.html">What are Actions?</a><span class=rvts3> for more details.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>The user interface tree defines how the user will see your install when they run it.&nbsp; It contains several install modes that are defined by InstallJammer, and beneath those are the panes that are included for that install mode.&nbsp; Each pane can have any number of actions attached to it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>The User Interface Tree</span></p>
<p class=rvps1><span class=rvts7><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts6>Panes and actions that have been added since the project was last loaded will appear in blue.&nbsp; A * beside a pane or action's title tells you that the given pane or action has conditions attached to it.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Common Components&nbsp; </span></p>
<p class=rvps1><span class=rvts2>This section of the interface tree is used to hold panes of an install theme that don't belong anywhere in the install process itself.&nbsp; Panes installed in the Common Components section can be modified just like normal panes, but you don't have the option to add the same pane to an install type.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Common examples of this are a background window that covers the screen behind the install wizard with some text or images.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Standard Install</span></p>
<p class=rvps1><span class=rvts2>This section contains the panes used by InstallJammer for a standard installation.&nbsp; A standard installation is when the user chooses to install the application just as you built it.&nbsp; All of the panes will be shown in order as they are shown on the interface tree.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Default Install</span></p>
<p class=rvps1><span class=rvts2>A default install is when the user has chosen to accept all of your default settings and just do the install without changing anything.&nbsp; The default install usually contains just a few screens to prompt the user to confirm installation and then to copy all of the files.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Console Install</span></p>
<p class=rvps1><span class=rvts2>A console install is when the user wants to install the program from a command line instead of through the GUI interface.&nbsp; A console install will run inside a terminal window and everything will be input and output to and from the terminal.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts6>Console installs are not supported on Windows.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Silent Install</span></p>
<p class=rvps1><span class=rvts2>A silent install is when the user wants to accept all of the default options and install the program silently without a GUI interface.&nbsp; This is useful for some administrators who have to install an application on many different machines.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>A silent install does not have any panes, only actions.&nbsp; Because of this, you will only see a list of actions under the Silent Install, and you are not allowed to add panes.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Action Groups</span></p>
<p class=rvps1><span class=rvts2>Action groups are a way to group actions together into one place.&nbsp; An action group can contain any number of actions to execute and has its own conditions and properties as well as those of the actions it holds.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Action groups are best used if you define an alias for them so that you don't always have to remember the ID of the action group.&nbsp; This is how InstallJammer sets up the default Startup Actions and Install Actions groups when it creates a new project.&nbsp; You can execute all of the actions in an action group by using the </span><span class=rvts3>Execute Actions action.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>See </span><a class=rvts11 href="WhatAreActionGroups.html">What are Action Groups?</a></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Previewing a pane</span></p>
<p class=rvps1><span class=rvts3>Once you've selected a pane you will see a button in the bottom right-hand corner of the properties window to preview the pane.&nbsp; Clicking this button will pop up a sample wizard with the pane you're currently viewing.&nbsp; This lets you see the pane the way it will appear during installation.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Most options, if changed, will automatically affect the appearance of the preview window, so you should be able to make textual and design changes, click Preview Pane again, and immediately see your changes.&nbsp; Not all changes are immediately seen.&nbsp; Some changes and options can only be seen when actually running the install.&nbsp; In this case, simply build and run a test install of your project to see what the panes will look like.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Editing pane code</span></p>
<p class=rvps1><span class=rvts3>Each pane in an install is defined by the Tcl/Tk code that built it.&nbsp; InstallJammer gives you the freedom and flexibility to modify each pane in your install to be exactly what you want it to be.&nbsp; Simply click the Edit Pane Code button when editing a pane, and an editor will pop up with all of the Tcl/Tk code used to create the pane you're looking at.&nbsp; If you don't understand Tcl/Tk code, you might want to read </span><a class=rvts10 href="WhatIsTclTk.html">What is Tcl/Tk?</a><span class=rvts3> as a starting point.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Restoring original pane code</span></p>
<p class=rvps1><span class=rvts3>The Restore Original Pane button will restore the original code for the pane currently being edited.&nbsp; This is useful if you wish to remove the changes you've made to the pane or you accidentally messed up the pane code.&nbsp; Restoring the pane code will put the pane code back into its original state.&nbsp; It will not modify your properties though.&nbsp; Only the code of the pane.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PauseInstall.html.






























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Pause Install</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Pause Install">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Pause Install</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ModifyObject.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SetObjectProperty.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will pause the file installation that is currently in progress.&nbsp; Once paused, the install must either be stopped using a </span><a class=rvts4 href="StopInstall.html">Stop Install</a><span class=rvts2> action or continued using a </span><a class=rvts4 href="ContinueInstall.html">Continue Install</a><span class=rvts2> action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PauseWindowsService.html.




































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Pause Windows Service</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Pause Windows Service">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 7px 0px 7px 0px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Pause Windows Service</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="DeleteWindowsService.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="StartWindowsService.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will pause a Windows service.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Database</span></p>
<p class=rvps2><span class=rvts2>Specifies the service control database to be operated on. By default, this is the active service control database on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Service Name</span></p>
<p class=rvps1><span class=rvts2>The name of the service to perform the action on.&nbsp; This can be the internal or the display name of the service.&nbsp; If the display name is given, it will automatically be translated to the internal service name for the action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>System</span></p>
<p class=rvps2><span class=rvts2>Specifies the name of the system on which the command should be invoked. By default, this is the local system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Wait</span></p>
<p class=rvps1><span class=rvts2>If not null, this specifies a number of milliseconds to wait for the action to complete.&nbsp; InstallJammer will wait until the action completes or for the specified number of milliseconds, whichever comes first. </span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PlatformCondition.html.




















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Platform Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Platform Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Platform Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="VirtualTextTestCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="StringEqualCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if a file exists or does not exist on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=148>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is</span></p>
</td>
<td width=614>
<p class=rvps1><span class=rvts2>True if the platform is the current install platform.</span></p>
</td>
</tr>
<tr valign=top>
<td width=148>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is not</span></p>
</td>
<td width=614>
<p class=rvps1><span class=rvts2>True if the platform is not the current install platform.</span></p>
</td>
</tr>
<tr valign=top>
<td width=148>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; matches</span></p>
</td>
<td width=614>
<p class=rvps1><span class=rvts2>True if the platform matches the given wildcard pattern. (Linux*) would match all Linux platforms.</span></p>
</td>
</tr>
<tr valign=top>
<td width=148>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not match</span></p>
</td>
<td width=614>
<p class=rvps1><span class=rvts2>True if the platform does not match the given wildcard pattern.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Platform</span></p>
<p class=rvps1><span class=rvts2>The name of a platform or pattern to match.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PlatformInformation.html.
























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Platform Information</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Platform Information">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
}
span.rvts4
{
 font-family: 'Verdana';
}
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Platform Information</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ApplicationInformation.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PackageAndArchiveInformation.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts4>Platform options describe options that are specific to each platform in an install project. When an install is built, these options are saved only in the installer for that platform.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Active</span></p>
<p class=rvps1><span class=rvts4>Whether or not this platform is active.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>When a platform is inactive, nothing in InstallJammer will use it or affect it. Mainly this means that an installer for the inactive platform will not be built, but several other things are also disabled when a platform is inactive.&nbsp; All of the properties for the platform will still be saved with your project, so a platform can easily be enabled again at a later time.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>You should mark a platform as inactive if you don't plan to distribute your application for that platform.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Build Separate Archives</span></p>
<p class=rvps1><span class=rvts4>If this property is true, the installer for this platform will be built in separate archive files instead of being built as a single executable file.&nbsp; This is useful for splitting up larger files for when installation will be done from a CD or DVD.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Default Destination Directory</span></p>
<p class=rvps1><span class=rvts4>The default destination directory for your application.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>This is where your application will default to installing on the target system if the user does not modify the directory (or is not given the option to modify the directory).</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Default Directory Permission Mask (UNIX only)</span></p>
<p class=rvps1><span class=rvts4>The default permission mask to use when installing directories.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>When a directory is created on the target system during installation, this option tells InstallJammer the default permission mask to use when creating.&nbsp; If a separate permission has been set for the directory, it will override the default permission.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Default File Permission Mask (UNIX only)</span></p>
<p class=rvps1><span class=rvts4>The default permission mask to use when installing files.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>When a file is installed on the target system during installation, this option tells InstallJammer the default permission mask to use when installing.&nbsp; If a separate permission has been set for the file, it will override the default permission.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Default Install Mode</span></p>
<p class=rvps1><span class=rvts4>This property sets the default install mode for the installer if the user has not specified a different mode on the command-line or if the user is not given the option to specify the mode.&nbsp; This allows you to make a console or silent only installer that the user cannot use any other way.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Default Program Folder (Windows only)</span></p>
<p class=rvps1><span class=rvts4>The default Program Folder name under the user's menu.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>This is the default Program Folder to store your application's shortcuts in on the Windows platform. If you create shortcuts in the &lt;%ProgramFolder%&gt; directory, this is the default name for that folder.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Default Setup Type</span></p>
<p class=rvps1><span class=rvts4>The default setup type chosen during installation.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>If the user is allowed to change the setup type during installation, this will be the default one chosen. If the user is not allowed to change the setup type, this will be the setup type that is installed by default.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Fall Back to Console Mode (UNIX only)</span></p>
<p class=rvps1><span class=rvts4>This property tells InstallJammer that the (un)installer should fall back to the console mode of installation if the GUI mode fails to initialize for some reason.&nbsp; This means that if the user chooses a GUI mode (or is defaulted to one), but they do not have a GUI environment, the installer will automatically detect and launch into the console install.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Include Windows API Extension (Windows only)</span></p>
<p class=rvps1><span class=rvts4>Whether or not to pack the TWAPI extension into your installer.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>The Tcl Windows API Extension provides commands at the Tcl scripting level to some of the internal Windows APIs.&nbsp; This provides the ability for you to script Windows-specific features into your installer (like services, user account commands, etc...) that would not normally be available.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Install Executable Description (Windows only)</span></p>
<p class=rvps1><span class=rvts4>This property describes the text to be used in the File Description field of a Windows install executable.&nbsp; The default is "&lt;%AppName%&gt; &lt;%Version%&gt; Setup".</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Install Executable Name</span></p>
<p class=rvps1><span class=rvts4>The name of your installer executable.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>This is the file that InstallJammer will create when it builds your installer. The installer will be built in the build subdirectory of your project directory.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Install Program Folder for All Users (Windows only)</span></p>
<p class=rvps1><span class=rvts4>If this option is true, InstallJammer will create the Program Folder under the Start menu for all users of the system and not just the user installing the application.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Program Executable</span></p>
<p class=rvps1><span class=rvts4>The main executable for your application.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>This field contains the main executable for your application. It is used throughout the install for things like creating shortcuts to your application and starting your application when the install is complete.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>If your program does not have an actual program entry point, you can just leave this blank.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Program License</span></p>
<p class=rvps1><span class=rvts4>The LICENSE file for your application.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Your application is not required to contain a LICENSE file, but some do. If you have one, this value tells InstallJammer where to look for it when offering the user the ability to read it.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>It is also appropriate, in most cases, to create a shortcut to your LICENSE file in your Program Folder.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Program Readme</span></p>
<p class=rvps1><span class=rvts4>The README file for your application.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Your application is not required to contain a README file, but some do. If you have one, this value tells InstallJammer where to look for it when offering the user the ability to read it.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>It is also appropriate, in most cases, to create a shortcut to your README file in your Program Folder.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Prompt for Root Password</span></p>
<p class=rvps1><span class=rvts4>If this property is true, and Require Root User is true, the user will be asked to specify their root password to continue instead of just getting a failure message and the installer exiting.&nbsp; When the user enters their root password, the installer will be restarted with the same options.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts5>InstallJammer attempts to use the given tools for the current desktop environment if available.&nbsp; KDE will use kdesu.&nbsp; Gnome will use gksu or gnomesu if found.&nbsp; All other environments will attempt to use one of the previously-mentioned tools if found.&nbsp; Finally, if none of these tools can be found, the user will either get an xterm if they are not running from a console, or it will simply ask for the password in the console if they are.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Require Administrator (Windows only)</span></p>
<p class=rvps1><span class=rvts4>If this property is true, the resulting installer will only work if the user is an administrator on the target Windows system.&nbsp; For Vista and beyond, this means the installer is built as an executable that requires administrator privileges, and the user will be asked for an administrator password before the install is executed.&nbsp; On earlier versions of Windows, the installer will check to see if the current user is in the Administrators group and will show an error message and exit if the user is not an administrator.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Require Root User (UNIX only)</span></p>
<p class=rvps1><span class=rvts4>Whether or not the user must install this application as root.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Some applications require a root user to install on a UNIX system.&nbsp; This option tells InstallJammer that the user cannot run the install unless it is run as root.&nbsp; InstallJammer will check the username during install initialization and fail with an error message if the user is not root.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Root Destination Directory (UNIX only)</span></p>
<p class=rvps1><span class=rvts4>The default destination directory when a user is installing as root.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>In most cases, an application can either install in a system location if the user is root or into the user's home directory if the user is not root.&nbsp; The root destination directory tells InstallJammer where the application should be installed if the user is installing as root.&nbsp; If the user is not root, or this option is left blank, InstallJammer will fall back to the Default Destination Directory for all installs.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>This option does not need Require Root User.&nbsp; The default destination will be adjusted if the user is root even if you don't require them to be root (unless it is blank).</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Use Uncompressed Binaries (Windows only)</span></p>
<p class=rvps1><span class=rvts4>If this property is true, the Windows installers will be built as uncompressed binaries.&nbsp; Installers built with InstallJammer are compressed using varying compression technologies for each platform.&nbsp; This is an attempt to keep the installers smaller at the cost of a slight increase in startup time.&nbsp; Some anti-virus software can mistakenly mark a compressed binary as having a virus when they actually don't.&nbsp; For this reason, it is sometimes best to build with the original, uncompressed binaries on Windows platforms.&nbsp; If you do build with uncompressed binaries, your installers will be several megabytes larger than the compressed versions.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Windows File Icon (Windows only)</span></p>
<p class=rvps1><span class=rvts4>The .ico to associate with your installer.&nbsp; If the icon path given is a relative path, InstallJammer will first attempt to locate the .ico file in the project's own directory and then in InstallJammer's root directory.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>If specified, the icon shown on Windows in the Explorer and as the main icon in the title bar of your installer will use the values in this file. You must specify an icon file that contains all of the possible size / color combinations for an icon.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>A default icon is associated with installers on Windows, and some icons have been provided that meet the specifications.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PopulateComponents.html.






































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Populate Components</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Populate Components">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Populate Components</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="MoveToPane.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PopulateSetupTypes.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>When placed on a Choose Components pane, this action will populate the tree with a list of components for the currently-selected setup type.&nbsp; Anytime the setup type changes (like the user moves back), the tree will be cleared and re-populated.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PopulateSetupTypes.html.






































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Populate Setup Types</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Populate Setup Types">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Populate Setup Types</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PopulateComponents.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="RemovePaneFromOrder.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>When placed on a Setup Type pane, this action will populate the setup type list with the setup types included in the current installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PortTestCondition.html.






























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Port Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Port Test Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts5
{
 font-family: 'Verdana';
}
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Port Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PackageTestCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AskYesOrNo.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if a given port number on the target system is currently bound and in use.&nbsp; It does not make any checks to see what is running on that port, only that the port is bound and answering or not.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=32>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=610>
<p class=rvps1><span class=rvts4>The action will attempt to open a socket to 127.0.0.1 (the local host) on the given port and see if anything answers the connection attempt.&nbsp; It then closes the port without ever sending or receiving any data.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts6 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=134>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; can bind</span></p>
</td>
<td width=628>
<p class=rvps1><span class=rvts2>True if the port is not currently bound and can be bound.</span></p>
</td>
</tr>
<tr valign=top>
<td width=134>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; cannot bind</span></p>
</td>
<td width=628>
<p class=rvps1><span class=rvts2>True if the port is currently bound and cannot be bound.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Port</span></p>
<p class=rvps1><span class=rvts2>The port number to check.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PromptForDirectory.html.
































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>PromptForDirectory</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="PromptForDirectory">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts5
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts6
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>PromptForDirectory</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="LoadMessageCatalog.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PromptForFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::PromptForDirectory</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Pop up a window prompting the user to choose a directory on the target system.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>A full directory path if the user selects one or an empty string if they cancel.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-message &lt;message string&gt;</span></p>
<p class=rvps1><span class=rvts2>A message to display at the top of the dialog window.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-normalize &lt;boolean&gt;</span></p>
<p class=rvps1><span class=rvts2>How to normalize the directory the user chooses.&nbsp; The options are: </span><span class=rvts6>backslash, forwardslash, platform, unix or windows</span><span class=rvts5>.&nbsp; Backslash will replace all directory separators with backslashes.&nbsp; Forwardslash will replace all directory separators with forward slashes.&nbsp; Platform means to do whatever the current platform does.&nbsp; Unix means to use forward slashes and remove any Windows drive letter (C:, D:, etc...).&nbsp; Windows means to use back slashes and leave any drive letter in place.&nbsp; The default is platform.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts6>-title &lt;title string&gt;</span></p>
<p class=rvps1><span class=rvts5>A title string to display in the title bar of the dialog.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts6>-variable &lt;variable name&gt;</span></p>
<p class=rvps1><span class=rvts5>A variable name to store the resulting directory in.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts6>-virtualtext &lt;virtual text name&gt;</span></p>
<p class=rvps1><span class=rvts5>A virtual text name (without the &lt;% and %&gt;) to store the resulting directory in.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PromptForFile.html.










































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>PromptForFile</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="PromptForFile">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts5
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts6
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>PromptForFile</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PromptForDirectory.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ReadInstallInfo.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::PromptForDirectory</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Pop up a window prompting the user to choose a file (or multiple files) on the target system.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>A full directory path if the user selects a file, a list of files if the user is allowed to select multiple files or an empty string if they cancel.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-defaultextension &lt;file extension&gt;</span></p>
<p class=rvps1><span class=rvts2>The default file extension to open the dialog with as well as the default extension to append if the user types in the name of a file without an extension.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-filetypes &lt;file type list&gt;</span></p>
<p class=rvps1><span class=rvts2>This is a Tcl list of lists that specifies valid file types for the dialog.&nbsp; The file types are specified as a list of lists where each inner list contains two elements: a text description and a file extension.&nbsp; Example:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>{{Text Files}&nbsp; {.txt}}</span></p>
<p class=rvps1><span class=rvts2>{{All Files}&nbsp; {*}}</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-initialdir &lt;directory&gt;</span></p>
<p class=rvps1><span class=rvts2>The initial directory to start the dialog in.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-initialfile &lt;filename&gt;</span></p>
<p class=rvps1><span class=rvts2>The initial file (or files in multiple mode) to select in the dialog when it first pops up.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-message &lt;message string&gt;</span></p>
<p class=rvps1><span class=rvts2>A message to display at the top of the dialog window.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-multiple &lt;boolean&gt;</span></p>
<p class=rvps1><span class=rvts2>Whether or not the user should be allowed to select multiple files.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-normalize &lt;boolean&gt;</span></p>
<p class=rvps1><span class=rvts2>How to normalize the directory the user chooses.&nbsp; The options are: </span><span class=rvts6>backslash, forwardslash, platform, unix or windows</span><span class=rvts5>.&nbsp; Backslash will replace all directory separators with backslashes.&nbsp; Forwardslash will replace all directory separators with forward slashes.&nbsp; Platform means to do whatever the current platform does.&nbsp; Unix means to use forward slashes and remove any Windows drive letter (C:, D:, etc...).&nbsp; Windows means to use back slashes and leave any drive letter in place.&nbsp; The default is platform.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts6>-title &lt;title string&gt;</span></p>
<p class=rvps1><span class=rvts5>A title string to display in the title bar of the dialog.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts6>-type &lt;open or save&gt;</span></p>
<p class=rvps1><span class=rvts5>The type of dialog to use, either: open or save.&nbsp; Open means that the dialog expects the file to already exist on the system to be opened.&nbsp; Save means that dialog can specify a file that does not already exist, and it will prompt the user if the file does exist.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts6>-variable &lt;variable name&gt;</span></p>
<p class=rvps1><span class=rvts5>A variable name to store the resulting directory in.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts6>-virtualtext &lt;virtual text name&gt;</span></p>
<p class=rvps1><span class=rvts5>A virtual text name (without the &lt;% and %&gt;) to store the resulting directory in.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/PropertyFileAPI.html.












































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>PropertyFileAPI</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="PropertyFileAPI">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333399" face="Verdana"><b>PropertyFileAPI</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FetchURL1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="FindProcesses.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::PropertyFileAPI</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This API provides the necessary functions for reading, manipulating and writing common properties files.&nbsp; A properties file follows the standard convention for Java properties files, but it basically matches an almost universal format for simple properties within a file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>See options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-array &lt;arrayName&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The name of an array to store the values in.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-do (required)</span></p>
<p class=rvps1><span class=rvts2>Specifies the action the API should take.&nbsp; Possible values are:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=1 cellpadding=1 cellspacing=2 style="border-color: #ece9d8 #aca899 #aca899 #ece9d8; border-style: solid;">
<tr valign=top>
<td width=92 valign=top>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; append</span></p>
</td>
<td width=670 valign=top>
<p class=rvps1><span class=rvts2>Add a line to the given array that should be written to the properties file as-is.</span></p>
</td>
</tr>
<tr valign=top>
<td width=92 valign=top>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; data</span></p>
</td>
<td width=670 valign=top>
<p class=rvps1><span class=rvts2>Return a string of data that will be written to a file if written.&nbsp; This data is the current contents of the properties file.</span></p>
</td>
</tr>
<tr valign=top>
<td width=92 valign=top>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; keys</span></p>
</td>
<td width=670 valign=top>
<p class=rvps1><span class=rvts2>Return a list of keys in the properties array.</span></p>
</td>
</tr>
<tr valign=top>
<td width=92 valign=top>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; read</span></p>
</td>
<td width=670 valign=top>
<p class=rvps1><span class=rvts2>Read a given properties file into the array.</span></p>
</td>
</tr>
<tr valign=top>
<td width=92 valign=top>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; set</span></p>
</td>
<td width=670 valign=top>
<p class=rvps1><span class=rvts2>Set the value of a given key to a value.&nbsp; If the key already exists, it will be overwritten, and when it is saved to a file, it will replace the original line that set the key in the same place within the file.</span></p>
</td>
</tr>
<tr valign=top>
<td width=92 valign=top>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; unset</span></p>
</td>
<td width=670 valign=top>
<p class=rvps1><span class=rvts2>Unset the value of a given key.&nbsp; This will remove the key from the array as well as delete any reference to the value when the file is written out.</span></p>
</td>
</tr>
<tr valign=top>
<td width=92 valign=top>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; write</span></p>
</td>
<td width=670 valign=top>
<p class=rvps1><span class=rvts2>Write the property array to a file.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-file</span></p>
<p class=rvps1><span class=rvts2>If the do action is read or write, this property specifies the name of the file to read from or write to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-key</span></p>
<p class=rvps1><span class=rvts2>If the do action is set or unset, this property specifies the key in the array to operate on.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-line</span></p>
<p class=rvps1><span class=rvts2>If the do action is append, this property specifies a line (or multiline) string to append directly to the given array.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-separator</span></p>
<p class=rvps1><span class=rvts2>Specifies the separator character to use between keys and values.&nbsp; The default is =.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-value</span></p>
<p class=rvps1><span class=rvts2>If the do action is set or unset, this property specifies the value to set for the given key.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>The following example shows a sample properties file and how the API uses it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>## Sample .properties file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>## Set foo</span></p>
<p class=rvps1><span class=rvts2>foo=bar</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>## Set bar</span></p>
<p class=rvps1><span class=rvts2>bar=foo</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::PropertyFileAPI -do read sample.properties -array props</span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::PropertyFileAPI -do set -array props -key foo -value "NEW FOO"</span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::PropertyFileAPI -do append -array props -line "\n## New value"</span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::PropertyFileAPI -do set -array props -key newvalue -value "NEW VALUE"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The new properties file will look like this</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>## Sample .properties file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>## Set foo</span></p>
<p class=rvps1><span class=rvts2>foo=NEW FOO</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>## Set bar</span></p>
<p class=rvps1><span class=rvts2>bar=foo</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>## New value</span></p>
<p class=rvps1><span class=rvts2>newvalue=NEW VALUE</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ReadFileIntoVirtualText.html.






























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Read File Into Virtual Text</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Read File Into Virtual Text">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Read File Into Virtual Text</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="DeleteFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="RenameFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will read a single file on the target system into a virtual text variable.&nbsp; This is useful to obtain properties or information from a file and use it within InstallJammer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Encoding</span></p>
<p class=rvps1><span class=rvts2>This property specifies the encoding to use when reading the file into virtual text.&nbsp; The default is to use whatever the system encoding is.&nbsp; utf-8 would be a common choice here.&nbsp; If you are unfamiliar with character encodings, it's probably best to leave this property alone.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File</span></p>
<p class=rvps1><span class=rvts2>The path to the file to read in.&nbsp; If the path is relative, it will be made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Trim String</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the data read from the file will be trimmed of whitespace on either side before the virtual text is set.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text</span></p>
<p class=rvps1><span class=rvts2>The name of the virtual text variable to read the file into (without &lt;% and %&gt;).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would read the file /etc/hosts.allow into the virtual text &lt;%AllowedHosts%&gt;</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>File:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /etc/hosts.allow</span></p>
<p class=rvps1><span class=rvts4>Virtual Text: AllowedHosts</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ReadInstallInfo.html.


















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>ReadInstallInfo</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="ReadInstallInfo">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>ReadInstallInfo</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PromptForFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ResponseFileAPI.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::ReadInstallInfo</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Read the install information of a previous installation.&nbsp; This API will read information from the given application / install ID and store the values in an array.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty String</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-applicationid &lt;Application ID&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The Application ID to read information for.&nbsp; This can be the installer's own &lt;%ApplicationID%&gt;, or it can be the ID of another, known install project.&nbsp; This lets your installer read the install information of another installer if you know the proper ID.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-array &lt;arrayName&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The name of an array to store the values in.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-installid &lt;Install ID&gt;</span></p>
<p class=rvps1><span class=rvts2>The install ID to read information for.&nbsp; If no ID is given, all of the installs for the given application ID will be read and stored in the array in the order they were created.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts2>The following example adds the Spanish language.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::ReadInstallInfo -applicationid SomeID -array tmp</span></p>
<p class=rvps1><span class=rvts4>parray tmp</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2>This would load all of the previous installations for the application SomeID into the array tmp, and the parray tmp would dump the array to the console.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/RebootOrShutdownSystem.html.
























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Reboot or Shutdown System</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Reboot or Shutdown System">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Reboot or Shutdown System</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="DeleteEnvironmentVariable.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="RegisterPackage.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will reboot or shutdown the target system.&nbsp; On some UNIX systems, this action cannot be performed unless the user is root.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Execute as Root</span></p>
<p class=rvps1><span class=rvts2>If this property is true, InstallJammer will prompt the user for their root password if they are not already root.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Type</span></p>
<p class=rvps1><span class=rvts2>Whether the system should be rebooted or shutdown.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/RegisterPackage.html.






















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Register Package</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Register Package">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
span.rvts6
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #ff0000;
}
span.rvts7
{
 font-family: 'Verdana';
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Register Package</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="RebootOrShutdownSystem.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="RemoveDirectoryFromPath.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will attempt to register a package with the given package manager on the target system.&nbsp; This action will almost always require root to be performed.&nbsp; If the user is not already root, the action will attempt to execute the action as root which will prompt the user to enter their root password to install the package information.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts5>Currently-supported package systems are: DPKG and RPM.&nbsp; The installer will attempt to build a dummy package on the target system using standard tools and then install it.&nbsp; Because of the limitations of the build tools, </span><span class=rvts6>this action does not register the files of your installer with the package database</span><span class=rvts5>.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>It does, however, register the uninstaller with the package system so that if the user attempts to remove the package through their system, it will call the uninstaller to do the actual file removal.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts5><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>InstallJammer will automatically add this package to be removed from the package database during uninstallation if the package is not being removed from the package manager itself.&nbsp; This requires root access, and InstallJammer will prompt the user to execute the removal as root if they are not root when they run the uninstall.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts7><br></span></p>
<p class=rvps1><span class=rvts7><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>Linux</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>DPKG Changelog File</span></p>
<p class=rvps1><span class=rvts2>A file on the target system to use as the changelog file for the DPKG database.&nbsp; If no file is specified, InstallJammer will create a dummy file to satisfy DPKG.&nbsp; If the file does not have a .gz extension, InstallJammer will gzip the file as-per DPKG requirements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>DPKG Control Script</span></p>
<p class=rvps1><span class=rvts2>This is the script that will be used as the control script when DPKG builds our dummy package.&nbsp; The default values and information will build a standard package based on information in your installer.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>Unless you are familiar with building DPKG packages, it is not recommended that you change any of the values in the Control Script.&nbsp; This can lead to your package not building or not installing correctly.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>DPKG Copyright File</span></p>
<p class=rvps1><span class=rvts2>A file on the target system to use as the copyright file for the DPKG database.&nbsp; If no file is specified, InstallJammer will create a dummy file to satisfy DPKG.&nbsp; If the file does not have a .gz extension, InstallJammer will gzip the file as-per DPKG requirements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>DPKG Debian Changelog File</span></p>
<p class=rvps1><span class=rvts2>A file on the target system to use as the Debian changelog file for the DPKG database.&nbsp; If no file is specified, InstallJammer will create a dummy file to satisfy DPKG.&nbsp; If the file does not have a .gz extension, InstallJammer will gzip the file as-per DPKG requirements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>DPKG Pre Install Script</span></p>
<p class=rvps1><span class=rvts2>A script to execute before installation in the DPKG database.&nbsp; Since InstallJammer is doing most of the work here, you should probably leave this blank unless you know what you are doing.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>DPKG Pre Uninstall Script</span></p>
<p class=rvps1><span class=rvts2>A script to execute before uninstallation in the DPKG database.&nbsp; The default script is a standard script expected for all DPKG packages, and you should probably not change it unless you know what you are doing.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>DPKG Post Install Script</span></p>
<p class=rvps1><span class=rvts2>A script to execute after installation in the DPKG database.&nbsp; The default script is a standard script expected for all DPKG packages, and you should probably not change it unless you know what you are doing.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>DPKG Post Uninstall Script</span></p>
<p class=rvps1><span class=rvts2>A script to execute after uninstallation in the DPKG database.&nbsp; InstallJammer automatically populates this script with a script to call our uninstaller.&nbsp; Since the DPKG database doesn't really know anything about the files in our installer or how to remove them, we want DPKG to remove its package and then call our uninstaller.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Since DPKG attempts to remove a previously-installed package before proceeding with a new install, this script checks to see if our removal is being run from another installer and exits if we are.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Package Name</span></p>
<p class=rvps1><span class=rvts2>The name of the package to use when storing this package to the database.&nbsp; The rest of the information is stored in the different scripts that build our dummy packages.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Package Databases</span></p>
<p class=rvps1><span class=rvts2>Specifies which package database should be registered with on the target system.&nbsp; Defaults to all, which means both RPM and DPKG if they exist on the system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>RPM Spec Script</span></p>
<p class=rvps1><span class=rvts2>The contents of this script are stored to a SPEC file to build our dummy RPM from.&nbsp; The default values and information will build a standard package based on information in your installer.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>Unless you are familiar with building RPM packages, it is not recommended that you change any of the values in the Spec Script.&nbsp; This can lead to your package not building or not installing correctly.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/RegisterWindowsLibrary.html.
































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Register Windows Library</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Register Windows Library">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Register Windows Library</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ImportWindowsRegistryFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="RemoveWindowsRegistryKey.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will register a DLL or other library with the Windows registry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>This action simply builds up the arguments and then calls the regsvr32.exe that is standard on Windows systems.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>Windows</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Call DLL Install</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the DLLInstall() function will be called for the given library when it is installed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Call DLL Register Server</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the DLLRegisterServer() function will be called for the given library when it is registered.&nbsp; If this property is false, then Call DLL Install must be true.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Library File</span></p>
<p class=rvps1><span class=rvts2>The path to the library file to register.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/RegistryEntryExistsCondition.html.


























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Registry Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Registry Entry Exists Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Registry Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="FileTypeExistsCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="WindowsServiceTestCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if a given registry key or value exists in Windows registry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=137>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; exists</span></p>
</td>
<td width=625>
<p class=rvps1><span class=rvts2>True if the key or value exists.</span></p>
</td>
</tr>
<tr valign=top>
<td width=137>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not exist</span></p>
</td>
<td width=625>
<p class=rvps1><span class=rvts2>True if the key or value does not exist.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Registry Key</span></p>
<p class=rvps1><span class=rvts2>The registry key to check.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Registry Value</span></p>
<p class=rvps1><span class=rvts2>The registry value to check.&nbsp; If this property is null, we only check to see if the key exists.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ReleaseNotes.html.








































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Release Notes</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Release Notes">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Release Notes</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="Credits.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="1214.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>1.2.15 (October 29th, 2010)</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This release contains minor bug fixes and enhancements.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Bug Fixes</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Fixed several issues in the uninstall cleanup process.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where saving some projects could cause an error when reloading a project file due to unmatched braces in the project file.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Add Widget action where the browse entry did not properly fire an event.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where nested action groups would cause an error when executing.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the Copy Value from the right-click menu would copy a blank value and clear the buffer.</span></li>
<li class=rvps1><span class=rvts2>Fixed the movement keys for text widgets in a readonly state so that they scroll properly.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the Uninstall Selected Files action where trying to uninstall a file that doesn't exist would cause an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in building separate archives that would cause it to fail on some platforms.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the exit dialog on Linux was not modal enough.&nbsp; The dialog will not be completely modal in the sense that people are used to on Windows, but the user shouldn't be able to click the X a second time and cause an error.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where the GetSelectedFiles API was appending an extra directory tail onto each directory object returned.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where non-ASCII filenames were not supported in the installer.&nbsp; This could produce an incompatibility with anyone using a custom UTF-8 message catalog.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in launching the file explorer on UNIX with no selected group.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in dragging and dropping files on UNIX with no selected group.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug with file URLs dropped from Nautilus not being decoded, so the builder doesn't recognize files with spaces because they show up as %20.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug in the builder where text would show up blank if the system language was not a language supported by InstallJammer.</span></li>
<li class=rvps1><span class=rvts2>Fixed a but in the chmod of the installkit startup on UNIX that could cause an error if the root user owned the installation.</span></li>
<li class=rvps1><span class=rvts2>Make sure the install information is updated before we redraw the setup type description.&nbsp; This fixes a bug where a setup type description that includes space required would not show properly because the space had not been updated before the text was changed.</span></li>
<li class=rvps1><span class=rvts2>Fixed a hard-coded error title string in the condition failure popups.</span></li>
<li class=rvps1><span class=rvts2>Made /tmp the default TempRoot instead of /usr/tmp.</span></li>
<li class=rvps1><span class=rvts2>Removed the hard-coded "directory is not empty" message string.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug that allowed illegal characters in the installer executable name.</span></li>
<li class=rvps1><span class=rvts2>Remove symbolic color names from the source and use hex RGB values instead.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where kdesu no longer worked under KDE4.</span></li>
<li class=rvps1><span class=rvts2>Fixed a bug where -T title is no longer supported for konsole in the Execute External Program action.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Minor Enhancements</span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Changed the build and quick build keyboard shortcuts.&nbsp; Control-b is now quick build and Control-Shift-b is a full build.&nbsp; Changed the menus to reflect the change.</span></li>
<li class=rvps1><span class=rvts2>Added a Description field to the Windows Shortcut action.&nbsp; This sets the Comments field and tooltip of a shortcut created on Windows.</span></li>
<li class=rvps1><span class=rvts2>Hitting space while viewing a component tree during installation will now toggle the current component.</span></li>
<li class=rvps1><span class=rvts2>Added a new "Show Hidden Directories" checkbutton to the choose file dialog on UNIX platforms.</span></li>
<li class=rvps1><span class=rvts2>Added a new -separator option to the PropertyFileAPI.</span></li>
<li class=rvps1><span class=rvts2>If a Move to Pane action attempts to move to the current pane it's already on, the pane will reload and rerun its actions instead of just doing nothing.</span></li>
<li class=rvps1><span class=rvts2>Made the default state of text widgets readonly.</span></li>
<li class=rvps1><span class=rvts2>Added Windows7 to the &lt;%WindowsPlatform%&gt; virtual text.</span></li>
<li class=rvps1><span class=rvts2>Added a new Display Name property to file groups.</span></li>
<li class=rvps1><span class=rvts2>Added a new GetDisplayName API call.</span></li>
<li class=rvps1><span class=rvts2>Modifying the title of an object now sets the Alias to that title if the alias is currently empty or equal to the current title.</span></li>
<li class=rvps1><span class=rvts2>Added a new DecodeURL API call.</span><span class=rvts1></span></li>
</ul>

</div></body></html>
Added docs/html/RemoveDirectoryFromPath.html.




































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Remove Directory from Path</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Remove Directory from Path">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Remove Directory from Path</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="RegisterPackage.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="UninstallLeftoverFiles.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is used to remove a directory from a path variable on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>Windows</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Directory</span></p>
<p class=rvps1><span class=rvts2>The directory to be removed from the path variable.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Level</span></p>
<p class=rvps1><span class=rvts2>This specifies whether the directory should be removed from the path variable for every user on the system or just the current user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Separator</span></p>
<p class=rvps1><span class=rvts2>This property specifies what separator to use between the paths for the given variable.&nbsp; Defaults to &lt;%PathSeparator%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Variable</span></p>
<p class=rvps1><span class=rvts2>This property specifies the variable to add your path to.&nbsp; By default, this is PATH, but it could easily be something like CLASSPATH to add to the Java class path on the target system.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/RemovePaneFromOrder.html.
















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Remove Pane from Order</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Remove Pane from Order">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Remove Pane from Order</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PopulateSetupTypes.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="WhatAreConditions.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will take the given pane and remove it from the wizard's back order.&nbsp; This means that when the user moves back with the Back button, this pane will no longer be shown.&nbsp; This is useful for controlling how the wizad behaves in tricky installs.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Pane</span></p>
<p class=rvps1><span class=rvts2>The ID or alias of a pane to be added to the back order of the wizard.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/RemoveWindowsRegistryKey.html.
































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Remove Windows Registry Key</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Remove Windows Registry Key">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Remove Windows Registry Key</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="RegisterWindowsLibrary.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="UnregisterWindowsLibrary.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will remove a registry key or value from the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>You do not need to remove during uninstall any registry keys and values added during installation.&nbsp; InstallJammer automatically registers any keys added by its own installers and adds them to the list to be uninstalled.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>Windows</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Key</span></p>
<p class=rvps1><span class=rvts2>The name of the key to remove from the registry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Value</span></p>
<p class=rvps1><span class=rvts2>A value to be removed from the key.&nbsp; If this is not null, the key itself will not be removed, only this value will be removed from the key.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Root Key</span></p>
<p class=rvps1><span class=rvts2>The root key in the registry.&nbsp; If Key already contains a root key, this property is ignored.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/RenameFile.html.


















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Rename File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Rename File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Rename File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ReadFileIntoVirtualText.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ReplaceTextInFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will rename a single file or directory on the target system to another name.&nbsp; This is the same as "moving" a file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Source</span></p>
<p class=rvps1><span class=rvts2>The path to the file or directory to be renamed.&nbsp; If the path is relative, it will be made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Destination</span></p>
<p class=rvps1><span class=rvts2>The new path to rename the file or directory to.&nbsp; If the path is relative, it will be made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would rename the file foo.cfg to bar.cfg in the &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Source:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foo.cfg</span></p>
<p class=rvps1><span class=rvts4>Destination: bar.cfg</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ReplaceTextInFile.html.












































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Replace Text in File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Replace Text in File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Replace Text in File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="RenameFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="WriteTextToFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will replace text strings in a file with other strings as based on a string map.&nbsp; This is useful for writing out configuration files with virtual text values from InstallJammer, etc...</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Encoding</span></p>
<p class=rvps1><span class=rvts2>Specifies the language encoding to use when replacing text in the file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Files</span></p>
<p class=rvps1><span class=rvts2>A list of files or patterns separated by a ;.&nbsp; Any pattern or file that is a relative path is automatically made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Line Feed</span></p>
<p class=rvps1><span class=rvts2>The type of linefeeds for the specified files.&nbsp; The following choices are available:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Auto - choose the linefeeds based on the target install platform.</span></li>
<li class=rvps1><span class=rvts2>Unix - Use UNIX linefeeds (lf)</span></li>
<li class=rvps1><span class=rvts2>Windows - Use Windows linefeeds (crlf)</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>String Map</span></p>
<p class=rvps1><span class=rvts2>A string map is a list of strings in pairs separated by whitespaces.&nbsp; Each string in a string map has a corresponding string to map it to.&nbsp; Strings with spaces should be placed in quotes to show that they are to be treated as a single string.&nbsp; See the example below for a sample string map.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would convert all instances of @@INSTALL_DIR@@ to our installation directory and all instances of the string "replace this string" with "our new string" in a file called config.cfg.&nbsp; It will also convert linefeeds to UNIX (lf) linefeeds.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Files:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; config.cfg</span></p>
<p class=rvps1><span class=rvts4>Line Feed:&nbsp; Unix</span></p>
<p class=rvps1><span class=rvts4>String Map: "@@INSTALL_DIR@@" &lt;%InstallDir%&gt;</span></p>
<p class=rvps1><span class=rvts4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "replace this string" "our new string"</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ResponseFileAPI.html.






































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>ResponseFileAPI</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="ResponseFileAPI">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>ResponseFileAPI</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ReadInstallInfo.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="RollbackInstall.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::ResponseFileAPI</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Manipulate options for response files within installers.&nbsp; This API can be used to read and write response files as well as manipulate the virtual text values that will be saved in an installer response file.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-do (required)</span></p>
<p class=rvps1><span class=rvts2>Specifies the action the API should take.&nbsp; Possible values are:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=1 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=92 style="border-width : 1px; border-color: #000000; border-style: solid; border-top: none; border-right: none; border-bottom: none; border-left: none;">
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; add</span></p>
</td>
<td width=670 style="border-width : 1px; border-color: #000000; border-style: solid; border-top: none; border-right: none; border-bottom: none; border-left: none;">
<p class=rvps1><span class=rvts2>Add the list of virtual text given by -virtualtext to the list of variables to save in the response file.</span></p>
</td>
</tr>
<tr valign=top>
<td width=92 style="border-width : 1px; border-color: #000000; border-style: solid; border-top: none; border-right: none; border-bottom: none; border-left: none;">
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; read</span></p>
</td>
<td width=670 style="border-width : 1px; border-color: #000000; border-style: solid; border-top: none; border-right: none; border-bottom: none; border-left: none;">
<p class=rvps1><span class=rvts2>Read the file given by -file as a response file.</span></p>
</td>
</tr>
<tr valign=top>
<td width=92 style="border-width : 1px; border-color: #000000; border-style: solid; border-top: none; border-right: none; border-bottom: none; border-left: none;">
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; remove</span></p>
</td>
<td width=670 style="border-width : 1px; border-color: #000000; border-style: solid; border-top: none; border-right: none; border-bottom: none; border-left: none;">
<p class=rvps1><span class=rvts2>Remove the list of virtual text given by -virtualtext from the list of variables to save in the response file.</span></p>
</td>
</tr>
<tr valign=top>
<td width=92 style="border-width : 1px; border-color: #000000; border-style: solid; border-top: none; border-right: none; border-bottom: none; border-left: none;">
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; write</span></p>
</td>
<td width=670 style="border-width : 1px; border-color: #000000; border-style: solid; border-top: none; border-right: none; border-bottom: none; border-left: none;">
<p class=rvps1><span class=rvts2>Write the installer response to the file given by -file.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-file</span></p>
<p class=rvps1><span class=rvts2>Specifies a filename for read and write operations.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-virtualtext</span></p>
<p class=rvps1><span class=rvts2>Specifies a list of virtual text for add and remove operations.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/RevertWow64Redirection.html.






































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Revert Wow64 Redirection</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Revert Wow64 Redirection">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Revert Wow64 Redirection</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="DisableWow64Redirection.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddWindowsFileCommand.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>On 64 bit Windows Vista (and beyond?) systems, installers and setup programs have certain system directories automatically redirected to a 32 bit directory hierarchy.&nbsp; This action reverts any previous redirection from the </span><a class=rvts4 href="DisableWow64Redirection.html">Disable Wow64 Redirection</a><span class=rvts2> action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>Windows</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/RollbackInstall.html.






































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>RollbackInstall</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="RollbackInstall">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>RollbackInstall</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ResponseFileAPI.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SetActiveSetupType.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::RollbackInstall</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Rollback any files, directories and registry entries installed on the system during the current installation.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty string</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/ScriptCondition.html.














































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Script Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Script Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
a.rvts7, span.rvts7
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts7:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Script Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ObjectIsActiveCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="VirtualTextTestCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition is a Tcl script that is substituted and then evaluated by Tcl's expression parser.&nbsp; This is not a condition that is used for full scripts.&nbsp; It is used for a combination of expressions that are combined together.&nbsp; To use an actual Tcl script as a condition, use the </span><a class=rvts6 href="ExecuteScriptCondition.html">Execute Script Condition</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Script</span></p>
<p class=rvps1><span class=rvts2>A Tcl expression to evaluate.&nbsp; The entire expression is substituted for virtual text before being evaluated.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following example is a valid Tcl expression:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>[string is true &lt;%RunningInstaller%&gt;] &amp;&amp; [string is true &lt;%UpgradeInstall%&gt;]</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Note that this an expression, not a full Tcl script.&nbsp; An expression is multiple commands that are strung together using expression operators like &amp;&amp; and ||.&nbsp; The following is </span><span class=rvts3>not</span><span class=rvts2> a valid expression:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>set test1 [string is true &lt;%RunningInstaller%&gt;]</span></p>
<p class=rvps1><span class=rvts4>set test2 [string is true &lt;%UpgradeInstall%&gt;]</span></p>
<p class=rvps1><span class=rvts4>return [expr {$test1 &amp;&amp; $test2}]</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2>This is a full Tcl script to be evaluated, not an expression.&nbsp; This type of script can be used in the </span><a class=rvts7 href="ExecuteScriptCondition.html">Execute Script Condition</a><span class=rvts2>, but not in a Script Condition.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SetActiveSetupType.html.








































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>SetActiveSetupType</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Set Active Setup Type">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>SetActiveSetupType</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="RollbackInstall.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SetExitCode.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::SetActiveSetupType</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Sets the active Setup Type in the current installer.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=33>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=608>
<p class=rvps1><span class=rvts4>This call will set the &lt;%InstallType%&gt; and &lt;%InstallTypeID%&gt; variables in the installer.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-setuptype &lt;setup type name or ID&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The setup type can either be the name of the setup type (like Typical or Custom), or it can be the ID of the setup type.&nbsp; The API call will figure out what you mean.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SetExitCode.html.


















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>SetExitCode</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="SetExitCode">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>SetExitCode</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SetActiveSetupType.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SetFileTypeEOL.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::SetExitCode</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Set the exit code for the current (un)installer.&nbsp; By default, an (un)installer will exit with an exit code of 0 if it finishes or 1 if it is canceled.&nbsp; By setting the exit code you are forcing an exit code of your choice.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-exitcode &lt;exit code&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>Set the exit code to the given number.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SetFileTypeEOL.html.












































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>SetFileTypeEOL</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="SetFileTypeEOL">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>SetFileTypeEOL</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SetExitCode.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SetObjectProperty1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::SetFileTypeEOL</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The the end-of-line character for a given filetype that is to be used when files of that type are installed.&nbsp; This API modifies the behavior of the installer such that each file that matches a given file type will be installed with the specified EOL characters instead of the platform default.&nbsp; This is useful for translating EOL characters from Windows to UNIX or vice-versa when installing files.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empy string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-eol &lt;eol&gt;</span></p>
<p class=rvps1><span class=rvts2>The EOL string to use.&nbsp; Can be: auto, binary, crlf, lf, unix or windows.&nbsp; In most cases, this value must be a list of two EOL characters: the character the file is currently using and the character to translate to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-extension &lt;file extension&gt;</span></p>
<p class=rvps1><span class=rvts2>A file extension or a list of file extensions separated by ; that are to be translated with the given EOL.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Example:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This would translate all .txt files that are installed from a Windows (CRLF) EOL to unix (LF) EOL.&nbsp; This assumes that the .txt files stored in your installer already have the Windows EOL.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::SetFileTypeEOL -eol {windows unix} -extension .txt</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This would translate all .ini files that are installed from a unix (LF) EOL to a Windows (CRLF) EOL.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::SetFileTypeEOL -eol {unix windows} -extension .ini</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SetInstallPassword.html.






































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>SetInstallPassword</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="SetInstallPassword">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333399" face="Verdana"><b>SetInstallPassword</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SetFileTypeEOL.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SetObjectProperty1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::SetInstallPassword</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Set the install password for the current installer.&nbsp; This is necessary when the installer has been encrypted with a password.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empy string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-password &lt;password&gt;</span></p>
<p class=rvps1><span class=rvts2>The password to set for the current installer.&nbsp; Setting an incorrect password will result in the installer being unable to read the encrypted files within the installer.&nbsp; This usually manifests as the installer failing with an error when it attempts to unpack a file during file installation.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SetObjectProperty.html.




























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Set Object Property</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Set Object Property">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Set Object Property</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PauseInstall.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SetVirtualText.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will set the value of any property on a given object.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Object ID</span></p>
<p class=rvps1><span class=rvts2>The ID or alias of the object to set the property on.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Property</span></p>
<p class=rvps1><span class=rvts2>This is the property to set on the given object.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Substitute Value</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the Value will be substituted fully for virtual text before being set as the new property value.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Value</span></p>
<p class=rvps1><span class=rvts2>The value to set the property to on the object.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SetObjectProperty1.html.






















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>SetObjectProperty</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="SetObjectProperty">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>SetObjectProperty</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SetFileTypeEOL.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SetVirtualText1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::SetObjectProperty</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Set the value of a single property on a given object.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>The new value of the property.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-object &lt;object ID or alias&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The object ID or alias of the object to set the new property on.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-property &lt;property name&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The name of the property to set on the given object.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-value &lt;property value&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The new value to assign to the object property.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following example would change the destination directory that an Unzip File action is supposed to unzip to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::SetObjectProperty -object "unzip action" -property Destination -value &lt;%InstallDir%&gt;/foo</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SetPlatformProperty.html.




















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>SetPlatformProperty</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="SetPlatformProperty">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>SetPlatformProperty</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ModifyObject1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="WhatIsTheInstallAPI.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::BuilderAPI::SetPlatformProperty</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Set a platform-specific property for a given platform</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>Empty string</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-platform</span></p>
<p class=rvps1><span class=rvts2>The platform to set the property for.&nbsp; This can be any platform supported in the current installation, or it can be the word "all" to mean all plaforms, the word "unix" to mean all unix platforms, or the word "active" to mean al active platforms.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-property</span></p>
<p class=rvps1><span class=rvts2>Specfies the property to set for the given platform.&nbsp; The current properties for platforms are: Active, BuildSeparateArchives, DefaultFilePermission, DefaultDirectoryPermission, Executable, FallBackToConsole, FileDescription, InstallDir, InstallMode, InstallType, ProgramName, ProgramReadme, ProgramLicense, ProgramFolderName, ProgramExecutable, ProgramFolderAllUsers, PromptForRoot, RequireAdministrator, RequireRoot, RootInstallDir, UseUncompressedBinaries, WindowsIcon.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-value</span></p>
<p class=rvps1><span class=rvts2>The value to set the given property to.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SetVirtualText.html.




























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Set Virtual Text</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Set Virtual Text">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Set Virtual Text</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SetObjectProperty.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="StopInstall.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will set the value of a virtual text variable.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Auto Update</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the virtual text being set will be added to a list of variables that automatically update the screen whenever they are changed.&nbsp; By default, InstallJammer only updates the screen during actions or when moving between panes.&nbsp; This will make this virtual text cause an update anytime its value changes.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Language</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer what language to set the virtual text in.&nbsp; If the value is None, the virtual text is set in a non-localized variable that works for all languages.&nbsp; If the virtual text already exists in a language though, that value will override the non-localized value.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Value</span></p>
<p class=rvps1><span class=rvts2>This is the new value to set the virtual text variable to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text&nbsp; </span></p>
<p class=rvps1><span class=rvts2>The name of the virtual text variable to set.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SetVirtualText1.html.








































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>SetVirtualText</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Set Virtual Text">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>SetVirtualText</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SetObjectProperty1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="SubstVirtualText.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::SetVirtualText</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Set the value of a virtual text variable in a given language.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>The new value of the virtual text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-action &lt;action ID or alias&gt;</span></p>
<p class=rvps1><span class=rvts2>The ID or alias of an action that should be executed anytime the value of the given virtual text changes.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>-command &lt;Tcl command&gt;</span></p>
<p class=rvps1><span class=rvts2>A Tcl command or proc that should be executed anytime the value of the given virtual text changes.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>-language &lt;Language or None&gt;</span></p>
<p class=rvps1><span class=rvts2>The language to set the virtual text in.&nbsp; If language is None or not specified, the virtual text will be set without being associated with a language.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-object &lt;object ID or alias&gt;</span></p>
<p class=rvps1><span class=rvts2>The ID or alias of an object to set this virtual text on.&nbsp; This option is used to set the text property of a specific object like a pane or action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-value &lt;new value&gt;</span></p>
<p class=rvps1><span class=rvts2>The value to set in the virtual text variable.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-virtualtext &lt;virtual text name&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The virtual text variable name to set (without &lt;% and %&gt;).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following example would give you a virtual text variable Foo that is set to Bar.&nbsp; This could then be accessed as &lt;%Foo%&gt; from within InstallJammer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::SetVirtualText -virtualtext Foo -value Bar</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SetupTypes.html.


















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Setup Types</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Setup Types">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts5
{
 font-family: 'Verdana';
 font-weight: bold;
}
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
span.rvts7
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Setup Types</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="Components.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PanesAndActions.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>Setup types define a method of installation when the install is run.&nbsp; The user can choose the method of installation based on the setup types available.&nbsp; Each setup type has a list of included components that are installed if the user chooses that setup type.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The "Custom" setup type has special meaning to InstallJammer.&nbsp; All other setup types are regarded as normal and have no special features.&nbsp; If the user is offered the ability to choose their setup type, and they choose Custom, they should also be offered the ability to select the individual components they wish to install.&nbsp; Any component added to the Custom setup type will be available to the user to choose during installation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts7>By default, InstallJammer creates two setup types:&nbsp; Typical and Custom.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Standard Properties</span></p>
<p class=rvps1><span class=rvts3>See </span><a class=rvts6 href="StandardProperties.html">Standard Properties</a><span class=rvts3>.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Name</span></p>
<p class=rvps1><span class=rvts3>The name of this setup type.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Show Setup Type</span></p>
<p class=rvps1><span class=rvts3>If this property is false, this setup type will not be shown when populating setup types in a pane.&nbsp; This is used to create setup types that you want hidden from the user during installation.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Text Properties</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Description</span></p>
<p class=rvps1><span class=rvts3>This is a brief description of the contents of this setup type.&nbsp; If the user is able to choose which setup type they wish to install they will see this description for each type to tell them what is in it.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Display Name</span></p>
<p class=rvps1><span class=rvts3>The name of the setup type to display when populating the setup types on a pane.&nbsp; If this property is left blank for a given language, the installer will use the standard Name property instead.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Build Platforms</span></p>
<p class=rvps1><span class=rvts3>This is a list of all the platforms that are supported by InstallJammer and whether or not this setup type should be built for each platform. If a platform is marked No, this setup type will not be included when the installer for that platform is built.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>It is possible to build a setup type into multiple platforms and then not install the setup type based on parameters during installation, but this option specifically tells InstallJammer to not even include this setup type for the given platform.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>Creating a new setup type</span></p>
<p class=rvps1><span class=rvts2>Click the Add New Setup Type button on the toolbar to add a new setup type to your install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>A new setup type is created with default values that you can change after its creation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>Deleting a setup type</span></p>
<p class=rvps1><span class=rvts2>Select the setup type you wish to delete and click the Delete Setup Type button on the toolbar or the delete key on your keyboard.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/StandardProperties.html.












































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Standard Properties</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Standard Properties">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts5
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Standard Properties</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ObjectTypes.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="WhatArePanes.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts4>Some properties are standard to many objects throughout InstallJammer.&nbsp; This is a list of standard properties that can appear throughout your project and what they are.&nbsp; An object is defined as any piece of an install (file group, file, action, condition, etc...).</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>ID</span></p>
<p class=rvps1><span class=rvts4>A unique identifier for this object.&nbsp; This ID is generated when the object is created and does not change throughout the life of the object.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>Component</span></p>
<p class=rvps1><span class=rvts2>This property tells you what component was originally used to create this object.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>Active</span></p>
<p class=rvps1><span class=rvts4>This tells InstallJammer whether this object is active or not.&nbsp; An inactive object is not packaged when building an installer.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>Alias</span></p>
<p class=rvps1><span class=rvts4>An alias is an alias by which to call an object ID.&nbsp; Any object in InstallJammer that has an ID can also have an alias.&nbsp; This makes it easier to remember objects by their alias instead of their object ID.&nbsp; For example, the Install Actions group that is created for a new project is aliased to be called Install Actions to make it easier to call from other actions.</span></p>
<p class=rvps1><span class=rvts4>v</span></p>
<p class=rvps1><span class=rvts5>Comment</span></p>
<p class=rvps1><span class=rvts4>Comments are sometimes provided by InstallJammer to tell you what an object is doing, but they are usually set by someone building the project.&nbsp; Comments are not used by InstallJammer for anything and can contain any text you want.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>Conditions</span></p>
<p class=rvps1><span class=rvts4>This tells you if there are any conditions placed on the object that will be checked during installation.&nbsp; Selecting this property will let you bring up the Conditions Editor to see and modify any conditions on the object.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>Data</span></p>
<p class=rvps1><span class=rvts4>This property is used to hold user-specific data.&nbsp; Just like comments, this data is not used by InstallJammer and is safe for you to store anything you want into it.&nbsp; This can be helpful for storing other bits of relevant data with an object in the system for use by other objects, actions or conditions.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>Include</span></p>
<p class=rvps1><span class=rvts4>This property tells InstallJammer when and where to include this object when running an installer or uninstaller.&nbsp; The object will either be: always included, included only when testing or included only when not testing.&nbsp; This property is affected by the &lt;%Testing%&gt; virtual text.&nbsp; When testing, only objects which are always included or included when testing will be created.&nbsp; When not testing, only objects which are always included or included when not testing will be created.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/StartWindowsService.html.




































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Start Windows Service</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Start Windows Service">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 7px 0px 7px 0px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Start Windows Service</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PauseWindowsService.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="StopWindowsService.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will start a Windows service.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Database</span></p>
<p class=rvps2><span class=rvts2>Specifies the service control database to be operated on. By default, this is the active service control database on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Service Name</span></p>
<p class=rvps1><span class=rvts2>The name of the service to perform the action on.&nbsp; This can be the internal or the display name of the service.&nbsp; If the display name is given, it will automatically be translated to the internal service name for the action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>System</span></p>
<p class=rvps2><span class=rvts2>Specifies the name of the system on which the command should be invoked. By default, this is the local system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Wait</span></p>
<p class=rvps1><span class=rvts2>If not null, this specifies a number of milliseconds to wait for the action to complete.&nbsp; InstallJammer will wait until the action completes or for the specified number of milliseconds, whichever comes first. </span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/StopInstall.html.






























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Stop Install</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Stop Install">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Stop Install</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SetVirtualText.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="TextWindow.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action stops file installation if it was previously paused using the </span><a class=rvts4 href="PauseInstall.html">Pause Install</a><span class=rvts2> action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/StopWindowsService.html.




































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Stop Windows Service</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Stop Windows Service">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 7px 0px 7px 0px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Stop Windows Service</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="StartWindowsService.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddPaneToOrder.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will stop a Windows service.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Database</span></p>
<p class=rvps2><span class=rvts2>Specifies the service control database to be operated on. By default, this is the active service control database on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Service Name</span></p>
<p class=rvps1><span class=rvts2>The name of the service to perform the action on.&nbsp; This can be the internal or the display name of the service.&nbsp; If the display name is given, it will automatically be translated to the internal service name for the action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>System</span></p>
<p class=rvps2><span class=rvts2>Specifies the name of the system on which the command should be invoked. By default, this is the local system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Wait</span></p>
<p class=rvps1><span class=rvts2>If not null, this specifies a number of milliseconds to wait for the action to complete.&nbsp; InstallJammer will wait until the action completes or for the specified number of milliseconds, whichever comes first. </span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/StringEqualCondition.html.


























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>String Equal Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="String Equal Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>String Equal Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="PlatformCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="StringIsCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if two given strings equal each other.&nbsp; Each string is substituted for virtual text before comparison.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=151>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; equals</span></p>
</td>
<td width=611>
<p class=rvps1><span class=rvts2>True if the two strings equal each other.</span></p>
</td>
</tr>
<tr valign=top>
<td width=151>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not equal</span></p>
</td>
<td width=611>
<p class=rvps1><span class=rvts2>True if the two strings do not equal each other.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>String 1</span></p>
<p class=rvps1><span class=rvts2>The first string to compare.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>String 2</span></p>
<p class=rvps1><span class=rvts2>The second string to compare.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/StringIsCondition.html.




















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>String Is Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="String Is Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>String Is Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="StringEqualCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="StringMatchCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks the type of a given string to see if it is or is not of the correct type.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=139>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; true</span></p>
</td>
<td width=623>
<p class=rvps1><span class=rvts2>True if the sting is true (1, true, yes or on).</span></p>
</td>
</tr>
<tr valign=top>
<td width=139>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; false</span></p>
</td>
<td width=623>
<p class=rvps1><span class=rvts2>True if the string is false (0, false, no or off).</span></p>
</td>
</tr>
<tr valign=top>
<td width=139>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is empty</span></p>
</td>
<td width=623>
<p class=rvps1><span class=rvts2>True if the string is empty, meaning it contains no real data.</span></p>
</td>
</tr>
<tr valign=top>
<td width=139>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is not empty</span></p>
</td>
<td width=623>
<p class=rvps1><span class=rvts2>True if the string has any data in it.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>String</span></p>
<p class=rvps1><span class=rvts2>The string to check.&nbsp; The value of the string will be substituted for virtual text before comparison.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/StringMatchCondition.html.




































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>String Match Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="String Match Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-size: 12pt;
 font-family: 'Times New Roman';
}
span.rvts5
{
 font-size: 12pt;
 font-family: 'Times New Roman';
 font-style: italic;
}
span.rvts6
{
 font-size: 12pt;
 font-family: 'Times New Roman';
 font-weight: bold;
}
a.rvts7, span.rvts7
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts7:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 7px 0px 7px 0px;
}
.rvps3
{
 margin: 7px 0px 7px 24px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>String Match Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="StringIsCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="EnvironmentVariableTestCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if a given string matches a given pattern using standard glob-style matching.&nbsp; Each string is substituted for virtual text before comparison.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts7 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=163>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; matches</span></p>
</td>
<td width=599>
<p class=rvps1><span class=rvts2>True if the string matches the pattern.</span></p>
</td>
</tr>
<tr valign=top>
<td width=163>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not match</span></p>
</td>
<td width=599>
<p class=rvps1><span class=rvts2>True if the string does not match the pattern.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Pattern</span></p>
<p class=rvps1><span class=rvts2>The pattern to match the string against.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps2><span class=rvts4>The </span><span class=rvts5>pattern</span><span class=rvts4> argument may contain any of the following special characters:</span></p>
<p class=rvps2><span class=rvts6>?</span><span class=rvts4> </span></p>
<p class=rvps3><span class=rvts4>Matches any single character. </span></p>
<p class=rvps2><span class=rvts6>*</span><span class=rvts4> </span></p>
<p class=rvps3><span class=rvts4>Matches any sequence of zero or more characters. </span></p>
<p class=rvps2><span class=rvts6>[</span><span class=rvts5>chars</span><span class=rvts6>]</span><span class=rvts4> </span></p>
<p class=rvps3><span class=rvts4>Matches any single character in </span><span class=rvts5>chars</span><span class=rvts4>. If </span><span class=rvts5>chars</span><span class=rvts4> contains a sequence of the form </span><span class=rvts5>a</span><span class=rvts6>-</span><span class=rvts5>b</span><span class=rvts4> then any character between </span><span class=rvts5>a</span><span class=rvts4> and </span><span class=rvts5>b</span><span class=rvts4> (inclusive) will match. </span></p>
<p class=rvps2><span class=rvts6>\</span><span class=rvts5>x</span><span class=rvts4> </span></p>
<p class=rvps3><span class=rvts4>Matches the character </span><span class=rvts5>x</span><span class=rvts4>. </span></p>
<p class=rvps2><span class=rvts6>{</span><span class=rvts5>a</span><span class=rvts6>,</span><span class=rvts5>b</span><span class=rvts6>,</span><span class=rvts5>...</span><span class=rvts4>} </span></p>
<p class=rvps3><span class=rvts4>Matches any of the strings </span><span class=rvts5>a</span><span class=rvts4>, </span><span class=rvts5>b</span><span class=rvts4>, etc. </span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>String</span></p>
<p class=rvps1><span class=rvts2>The string to match against the pattern.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/SubstVirtualText.html.














































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>SubstVirtualText</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Subst Virtual Text">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>SubstVirtualText</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SetVirtualText1.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="URLIsValid.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::SubstVirtualText</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Given a string, substitute all virtual text out of the string and return the substituted string.</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>The substituted string.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-virtualtext &lt;virtual text string&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The virtual text string to be substituted.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Example</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If you had your application name as "My Application" and Version as "1.0", you could do:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::SubstVirtualText -virtualtext "&lt;%AppName%&gt; &lt;%Version%&gt;"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>which would return: "My Application 1.0"</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/TestRun.html.










































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Test Installer</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Test Run">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Test Installer</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="DiskBuilder.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="TestUninstaller.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This panel allows you to test your newly-built install. By default, testing an install means just executing the binary.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Save temporary directory for debugging</span></p>
<p class=rvps1><span class=rvts2>This option tells InstallJammer to save the temporary directory created during installation for debugging purposes. When an InstallJammer install runs, a temporary directory is created to hold the unpacking program and other temporary files. Normally, the temporary directory is cleaned up upon exiting the install. If this option is checked, the temporary directory will be left for debugging.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Test in default mode</span></p>
<p class=rvps1><span class=rvts2>This tells the install to use the Default install mode.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Test in console mode (UNIX only)</span></p>
<p class=rvps1><span class=rvts2>This tells the install to test the console-based version of the installer.&nbsp; InstallJammer will launch the installer in a new console window.&nbsp; Console installs are not available on Windows.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Test in silent mode</span></p>
<p class=rvps1><span class=rvts2>This tells the install to use the Silent install mode.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Test install without installing files</span></p>
<p class=rvps1><span class=rvts2>This option tells your install to run through all of the panes without actually going through the steps to install the files of your install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Test install with an open console</span></p>
<p class=rvps1><span class=rvts2>This option tells the install to open a debugging console window during installation.&nbsp; The console allows you to do anything you want while your install is running.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/TestUninstaller.html.






























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Test Uninstaller</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Test Uninstaller">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Test Uninstaller</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="TestRun.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ObjectTypes.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This panel allows you to test your uninstaller after you've run the installer on your system.&nbsp; InstallJammer will attempt to locate the uninstaller for the last installation of your project and run the uninstaller if it finds it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Test in console mode (UNIX only)</span></p>
<p class=rvps1><span class=rvts2>This tells the uninstall to test the console-based version of the uninstaller.&nbsp; InstallJammer will launch the uninstaller in a new console window.&nbsp; Console uninstalls are not available on Windows.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Test in silent mode</span></p>
<p class=rvps1><span class=rvts2>This tells the uninstall to use the Silent uninstall mode.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Test install without uninstalling files</span></p>
<p class=rvps1><span class=rvts2>This option tells your uninstall to run through all of the panes without actually going through the steps to uninstall the files of your install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Test uninstall with an open console</span></p>
<p class=rvps1><span class=rvts2>This option tells the uninstall to open a debugging console window during uninstallation.&nbsp; The console allows you to do anything you want while your uninstall is running.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/TextWindow.html.




















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Text Window</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Text Window">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Text Window</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="StopInstall.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="Wait.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action pops up a simple text window to display a long bit of text to the user.&nbsp; It is useful for posting text files like READMEs and for displaying progressive output from an </span><a class=rvts4 href="ExecuteExternalProgram.html">Execute External Program</a><span class=rvts2> action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Anchor</span></p>
<p class=rvps1><span class=rvts2>The position on the screen to display the message panel.&nbsp; Default is the center of the screen.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Grab Focus</span></p>
<p class=rvps1><span class=rvts2>This tells InstallJammer to grab the focus from the user so that they can't interact with anything else in the installer while the message panel is on the screen.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Height</span></p>
<p class=rvps1><span class=rvts2>The height of the text window in pixels.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Image</span></p>
<p class=rvps1><span class=rvts2>An icon to display on the left side of the message panel.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Text File</span></p>
<p class=rvps1><span class=rvts2>The name of a file on the target system to read and display in the text window.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Text Wrap</span></p>
<p class=rvps1><span class=rvts2>Tells the textbox how to wrap text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Wait&nbsp; on Window</span></p>
<p class=rvps1><span class=rvts2>If this value is true, InstallJammer will wait for the user to close the window before continuing on with the installation.&nbsp; If it is false, the text window will pop up, and the install will continue on.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Width</span></p>
<p class=rvps1><span class=rvts2>The width of the text window in pixels.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/TheUserInterfaceTree.html.




















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>The User Interface Tree</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="The User Interface Tree">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #6699FF; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
}
span.rvts4
{
 font-family: 'Verdana';
 font-weight: bold;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
span.rvts6
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
var stContextString;
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333399" face="Verdana"><b>The User Interface Tree</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CommandLineOptions.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="VirtualText.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>The user interface tree defines how the user will see your install when they run it.&nbsp; It contains several install modes that are defined by InstallJammer, and beneath those are the panes that are included for that install mode.&nbsp; Each pane can have any number of actions attached to it.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Common Components&nbsp; </span></p>
<p class=rvps1><span class=rvts3>This section of the interface tree is used to hold panes of an install theme that don't belong anywhere in the install process itself.&nbsp; Panes installed in the Common Components section can be modified just like normal panes, but you don't have the option to add the same pane to an install type.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Common examples of this are a background window that covers the screen behind the install wizard with some text or images.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Standard Install</span></p>
<p class=rvps1><span class=rvts3>This section contains the panes used by InstallJammer for a standard installation.&nbsp; A standard installation is when the user chooses to install the application just as you built it.&nbsp; All of the panes will be shown in order as they are shown on the interface tree.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Default Install</span></p>
<p class=rvps1><span class=rvts3>A default install is when the user has chosen to accept all of your default settings and just do the install without changing anything.&nbsp; The default install usually contains just a few screens to prompt the user to confirm installation and then to copy all of the files.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Console Install</span></p>
<p class=rvps1><span class=rvts3>A console install is when the user wants to install the program from a command line instead of through the GUI interface.&nbsp; A console install will run inside a terminal window and everything will be input and output to and from the terminal.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2>
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts6>Console installs are not supported on Windows.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Silent Install</span></p>
<p class=rvps1><span class=rvts3>A silent install is when the user wants to accept all of the default options and install the program silently without a GUI interface.&nbsp; This is useful for some administrators who have to install an application on many different machines.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>A silent install does not have any panes, only actions.&nbsp; Because of this, you will only see a list of actions under the Silent Install, and you are not allowed to add panes.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Action Groups</span></p>
<p class=rvps1><span class=rvts3>Action groups are a way to group actions together into one place.&nbsp; An action group can contain any number of actions to execute and has its own conditions and properties as well as those of the actions it holds.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Action groups are best used if you define an alias for them so that you don't always have to remember the ID of the action group.&nbsp; This is how InstallJammer sets up the default Startup Actions and Install Actions groups when it creates a new project.&nbsp; You can execute all of the actions in an action group by using the </span><span class=rvts2>Execute Actions action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="WhatAreActionGroups.html">What are Action Groups?</a><span class=rvts1></span></p>

</div></body></html>
Added docs/html/URLIsValid.html.




















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>URLIsValid</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="URLIsValid">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>URLIsValid</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SubstVirtualText.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="VirtualTextAPI.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::URLIsValid</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Validate whether a given URL is a valid URL that can be fetched.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>True or false.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-proxyhost &lt;hostname&gt;</span></p>
<p class=rvps1><span class=rvts2>The host name of a proxy server to use for the request.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-proxyport &lt;port number&gt;</span></p>
<p class=rvps1><span class=rvts2>The port number of a proxy server to use for the request.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-url &lt;URL&gt;</span></p>
<p class=rvps1><span class=rvts2>The URL to validate.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/UninstallLeftoverFiles.html.


































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Uninstall Leftover Files</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Uninstall Leftover Files">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Uninstall Leftover Files</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="RemoveDirectoryFromPath.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="UninstallSelectedFiles.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action is just like </span><a class=rvts4 href="UninstallSelectedFiles.html">Uninstall Selected Files</a><span class=rvts2> except that it will forcefully try to remove any pieces of the uninstall that could not be removed on the first pass.&nbsp; This means deleting directories eventhough they are not empty or forcibly trying to remove a file that could not be deleted the first time.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If any errors still occur while executing this action, they are appended to the &lt;%Errors%&gt; virtual text, and the &lt;%ErrorsOccurred%&gt; virtual text will be set to true.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/UninstallSelectedFiles.html.


































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Uninstall Selected Files</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Uninstall Selected Files">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Uninstall Selected Files</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="UninstallLeftoverFiles.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="DisableWow64Redirection.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This is the main action of the uninstall process.&nbsp; This action will attempt to uninstall everything that was installed on the target system during installation.&nbsp; This includes all files, directories and registry entries.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If any piece cannot be removed for some reason, an error will be appended to the &lt;%Errors%&gt; virtual text, and the &lt;%ErrorsOccurred%&gt; virtual text will be set to true.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/UnpackStoredFile.html.






























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Unpack Stored File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Unpack Stored File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Unpack Stored File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="InstallWrappedScript.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GetJavaProperty.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will unpack a file stored in the installer to a specified location on the target system.&nbsp; Since the installer will already unpack all of the selected files during installation, this action should only be used to extract a file to a special location or before the actual installation is performed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add to Uninstall</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the unpacked file will be added to the list of files for the uninstaller to remove.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>Files unpacked to the &lt;%Temp%&gt; directory are never added to the uninstall.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File ID</span></p>
<p class=rvps1><span class=rvts2>The ID of the file to unpack.&nbsp; This can be the valid ID of any file stored in the installer or an alias to a file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Target Directory</span></p>
<p class=rvps1><span class=rvts2>The target directory to unpack this file into.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Target Filename</span></p>
<p class=rvps1><span class=rvts2>The name of the file to create.&nbsp; If this property is left blank, the name of the file will be the same name that it was stored with.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/UnregisterWindowsLibrary.html.
































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Unregister Windows Library</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Unregister Windows Library">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Unregister Windows Library</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="RemoveWindowsRegistryKey.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ContinueWindowsService.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will unregister a DLL or other library with the Windows registry.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts5>This action simply builds up the arguments and then calls the regsvr32.exe that is standard on Windows systems.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>Windows</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Call DLL Uninstall</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the DLLUninstall() function will be called for the given library when it is installed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Call DLL Unregister Server</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the DLLUnregisterServer() function will be called for the given library when it is registered.&nbsp; If this property is false, then Call DLL Uninstall must be true.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Library File</span></p>
<p class=rvps1><span class=rvts2>The path to the library file to unregister.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/UnzipFile.html.
















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Unzip File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Unzip File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Unzip File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="WriteTextToFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ContinueInstall.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will take a given .zip file that is installed on the target system and unzip it to a destination directory.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add to Uninstall</span></p>
<p class=rvps1><span class=rvts2>If this property is true, any directory or file created while unzipping the file will be added the uninstall log to be removed later during uninstallation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Destination</span></p>
<p class=rvps1><span class=rvts2>The new path to unpack the zip file to.&nbsp; If the path is relative, it will be made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Progress Virtual Text</span></p>
<p class=rvps1><span class=rvts2>If not null, this specifies a virtual text variable to update with the percentage complete as the files are unzipped.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Status Virtual Text</span></p>
<p class=rvps1><span class=rvts2>If not null, this specifies a virtual text variable to update with the status of the files as they are unzipped.&nbsp; The virtual text will be set to the value of Status Text and then updated.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Zip File</span></p>
<p class=rvps1><span class=rvts2>The path to the zip ile or directory to be unpacked.&nbsp; If the path is relative, it will be made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Text Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Status Text</span></p>
<p class=rvps1><span class=rvts2>A text string to use when showing status during the unzip.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values would unpack the file foo.zip into the directory &lt;%InstallDir%&gt;/bar.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Source:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foo.zip</span></p>
<p class=rvps1><span class=rvts4>Destination: foo</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/VirtualDirectoryDefinitions.html.
























































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Virtual Directory Definitions</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Virtual Directory Definitions">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
}
span.rvts5
{
 font-family: 'Verdana';
 font-weight: bold;
}
span.rvts6
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Virtual Directory Definitions</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="VirtualTextDefinitions.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="DebuggingAnInstall.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts4>The following Virtual Directories are currently available in InstallJammer.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%Desktop%&gt;</span></p>
<p class=rvps1><span class=rvts4>The directory location of the user's desktop.&nbsp; On Windows, this is the user's desktop.&nbsp; On UNIX, the value is dependant upon which window manager the user is running during installation.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%GnomeDesktop%&gt;</span></p>
<p class=rvps1><span class=rvts4>The Gnome desktop directory. This is where Gnome stores all of the shortcuts that appear on the desktop. This directory is empty if the user does not have the Gnome Desktop.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%Home%&gt;</span></p>
<p class=rvps1><span class=rvts4>The user's home directory. On Windows, InstallJammer attempts to find the best possible option for the user's home directory if they have not specified a location for it. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%InstallDir%&gt;</span></p>
<p class=rvps1><span class=rvts4>The destination directory the user has chosen to install to. If the user is not given the option to select a destination directory, or that pane has not been shown yet, this variable will default to the Default Destination Directory set during build time.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%InstallInfoDir%&gt;</span></p>
<p class=rvps1><span class=rvts4>The directory where InstallJammer will store all of its registry information for this install or where it will check for registry information during uninstallation.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallJammerRegistryDir%&gt;</span></p>
<p class=rvps1><span class=rvts2>The root directory that InstallJammer is using to store registry information about your installs.&nbsp; This does not include the subdirectory for the current install.&nbsp; This is the directory where the directories for each install are stored.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallSource%&gt;</span></p>
<p class=rvps1><span class=rvts2>The directory the installer executable was in when it was started.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%KDEDesktop%&gt;</span></p>
<p class=rvps1><span class=rvts4>The KDE desktop directory. This is where KDE stores all of the shortcuts that appear on the desktop. This directory is empty if the user does not have the KDE Desktop.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%ProgramFolder%&gt;</span></p>
<p class=rvps1><span class=rvts4>The full path to the Program Folder the user has selected. This is usually a combination of the Programs folder and ProgramFolderName.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%RootInstallDir%&gt;</span></p>
<p class=rvps1><span class=rvts4>The root install dir.&nbsp; If this is not null, and the user is root, &lt;%InstallDir%&gt; will be set to this value on startup.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%Temp%&gt;</span></p>
<p class=rvps1><span class=rvts4>The temporary directory used by InstallJammer during installation. Once InstallJammer has finished, this directory, and all of its contents, will be deleted. This is useful for creating temporary files during installation.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%TempRoot%&gt;</span></p>
<p class=rvps1><span class=rvts4>The root of the temporary directory being used by InstallJammer.&nbsp; InstallJammer will always create a subdirectory in &lt;%TempRoot%&gt; to do all of its work in, but &lt;%TempRoot%&gt; is the actual temporary directory on the user's system.&nbsp; The user can specify this directory on the command-line with the --temp option.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=32>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=610>
<p class=rvps1><span class=rvts6>Temp Root is determined by looking at:</span></p>
<p class=rvps1><span class=rvts6><br></span></p>
<p class=rvps1><span class=rvts6>TEMP environment variable</span></p>
<p class=rvps1><span class=rvts6>TMP environment variable</span></p>
<p class=rvps1><span class=rvts6>C:/Documents and Settings/&lt;user&gt;/Local Settings/Temp (Windows only)</span></p>
<p class=rvps1><span class=rvts6>C:/Windows/Temp (Windows only)</span>
<br><span class=rvts6>C:/Winnt/Tmp (Windows only)</span></p>
<p class=rvps1><span class=rvts6>C:/Temp (Windows only)</span></p>
<p class=rvps1><span class=rvts6>/usr/tmp (UNIX only)</span></p>
<p class=rvps1><span class=rvts6>/tmp (UNIX only)</span></p>
<p class=rvps1><span class=rvts6>/var/tmp (UNIX only)</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>Windows Virtual Directories</span></p>
<p class=rvps1><span class=rvts4>The following Virtual Directories are also available on the Windows platform.&nbsp; Virtual text in all uppercase letters is treated specially by InstallJammer as a Windows directory.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%ADMINTOOLS%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%ALTSTARTUP%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that corresponds to the user's nonlocalized Startup program group. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%APPDATA%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that serves as a common repository for application-specific data. A typical path is C:\Documents and Settings\username\Application Data. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%BITBUCKET%&gt;</span></p>
<p class=rvps1><span class=rvts4>Virtual folder containing the objects in the user's Recycle Bin. </span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%CDBURN_AREA%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_ADMINTOOLS%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_ALTSTARTUP%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that corresponds to the nonlocalized Startup program group for all users. Valid only for Microsoft Windows NT® systems. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_APPDATA%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_DESKTOPDIRECTORY%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that contains files and folders that appear on the desktop for all users. A typical path is C:\Documents and Settings\All Users\Desktop. Valid only for Windows NT systems. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_DOCUMENTS%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_FAVORITES%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that serves as a common repository for all users' favorite items. Valid only for Windows NT systems. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_MUSIC%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_OEM_LINKS%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_PICTURES%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_PROGRAMS%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that contains the directories for the common program groups that appear on the Start menu for all users. A typical path is C:\Documents and Settings\All Users\Start Menu\Programs. Valid only for Windows NT systems.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_QUICK_LAUNCH%&gt;</span></p>
<p class=rvps1><span class=rvts4>The quick launch directory common to all users on the system.&nbsp; Adding a shortcut here will cause it to appear on every user's quick launch bar.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_STARTMENU%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that contains the programs and folders that appear on the Start menu for all users. A typical path is C:\Documents and Settings\All Users\Start Menu. Valid only for Windows NT systems. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_STARTUP%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that contains the programs that appear in the Startup folder for all users. A typical path is C:\Documents and Settings\All Users\Start Menu\Programs\Startup. Valid only for Windows NT systems. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_TEMPLATES%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMMON_VIDEO%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COMPUTERSNEARME%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%CONNECTIONS%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%CONTROLS%&gt;</span></p>
<p class=rvps1><span class=rvts4>Virtual folder containing icons for the Control Panel applications. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%COOKIES%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that serves as a common repository for Internet cookies. A typical path is C:\Documents and Settings\username\Cookies. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%DESKTOP%&gt;</span></p>
<p class=rvps1><span class=rvts4>Windows Desktop virtual folder that is the root of the namespace. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%DESKTOPDIRECTORY%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory used to physically store file objects on the desktop (not to be confused with the desktop folder itself). A typical path is C:\Documents and Settings\username\Desktop. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%DRIVES%&gt;</span></p>
<p class=rvps1><span class=rvts4>My Computer -- virtual folder containing everything on the local computer: storage devices, printers, and Control Panel. The folder may also contain mapped network drives. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%FAVORITES%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that serves as a common repository for the user's favorite items. A typical path is C:\Documents and Settings\username\Favorites. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%FONTS%&gt;</span></p>
<p class=rvps1><span class=rvts4>Virtual folder containing fonts. A typical path is C:\Windows\Fonts. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%HISTORY%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that serves as a common repository for Internet history items. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%INTERNET%&gt;</span></p>
<p class=rvps1><span class=rvts4>Virtual folder representing the Internet. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%INTERNET_CACHE%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that serves as a common repository for temporary Internet files. A typical path is C:\Documents and Settings\username\Temporary Internet Files. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%LOCAL_APPDATA%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%MYDOCUMENTS%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%MYMUSIC%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%MYPICTURES%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%MYVIDEO%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%NETHOOD%&gt;</span></p>
<p class=rvps1><span class=rvts4>A file system folder containing the link objects that may exist in the My Network Places virtual folder. It is not the same as NETWORK, which represents the network namespace root. A typical path is C:\Documents and Settings\username\NetHood. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%NETWORK%&gt;</span></p>
<p class=rvps1><span class=rvts4>Network Neighborhood -- virtual folder representing the root of the network namespace hierarchy. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%PERSONAL%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that serves as a common repository for documents. A typical path is C:\Documents and Settings\username\My Documents. This should be distinguished from the virtual My Documents folder in the namespace. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%PRINTERS%&gt;</span></p>
<p class=rvps1><span class=rvts4>Virtual folder containing installed printers. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%PRINTHOOD%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that contains the link objects that may exist in the Printers virtual folder. A typical path is C:\Documents and Settings\username\PrintHood. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%PROFILE%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%PROGRAM_FILES%&gt;</span></p>
<p class=rvps1><span class=rvts4>A folder for components that are shared across applications. A typical path is C:\Program Files. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%PROGRAM_FILESX86%&gt;</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%PROGRAM_FILES_COMMON%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%PROGRAM_FILES_COMMONX86%&gt;</span></p>
<p class=rvps1><span class=rvts5><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%PROGRAMS%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that contains the user's program groups (which are also file system directories). A typical path is C:\Documents and Settings\username\Start Menu\Programs. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%QUICK_LAUNCH%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that contains Windows shortcuts that appear on the user's Quick Launch toolbar. Not valid on Windows 95. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%RECENT%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that contains the user's most recently used documents. A typical path is C:\Documents and Settings\username\Recent. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%RESOURCES%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%RESOURCES_LOCALIZED%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%SENDTO%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that contains Send To menu items. A typical path is C:\Documents and Settings\username\SendTo. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%STARTMENU%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory containing Start menu items. A typical path is C:\Documents and Settings\username\Start Menu. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%STARTUP%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that corresponds to the user's Startup program group. The system starts these programs whenever any user logs onto Windows NT or starts Windows 95. A typical path is C:\Documents and Settings\username\Start Menu\Programs\Startup. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%SYSTEM%&gt;</span></p>
<p class=rvps1><span class=rvts4>System folder. A typical path is C:\WINNT\SYSTEM.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%SYSTEM32%&gt;</span></p>
<p class=rvps1><span class=rvts4>System folder. A typical path is C:\WINNT\SYSTEM32.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%SYSTEMX86%&gt;</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%TEMPLATES%&gt;</span></p>
<p class=rvps1><span class=rvts4>File system directory that serves as a common repository for document templates. </span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>&lt;%WINDOWS%&gt;</span></p>
<p class=rvps1><span class=rvts4>Windows directory or SYSROOT. This corresponds to the %windir% or %SYSTEMROOT% environment variables. A typical path is C:\Windows.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/VirtualText.html.


























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Virtual Text</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Virtual Text">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Virtual Text</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CommandLineOptions.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="DiskBuilder.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>The Virtual Text panel allows you to see what virtual text and virtual directory definitions are defined in InstallJammer as well as add your own virtual text to your project.&nbsp; Adding your own virtual text lets you customize your installer by using common strings throughout instead of using constant values.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>To learn more about virtual text, please read </span><a class=rvts5 href="WhatIsVirtualText.html">What is Virtual Text?</a></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Adding New Virtual Text</span></p>
<p class=rvps1><span class=rvts3>You can add your own virtual text by clicking the "Add New Virtual Text" button located on the toolbar in the panel.&nbsp; A new line will be added to the bottom of the virtual text table with values that are left blank for you to fill in.&nbsp; The first field is the index value for the virtual text field you are adding.&nbsp; The second field is the text that will be used for your new virtual text within the installer.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Now that you've added your new virtual text, you can use it throughout your install in place of constants.&nbsp; Here's an example:</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>Let's say you add a virtual text definition called "MyVirtualText" with a value of "This is my virtual text."&nbsp; Anywhere you use &lt;%MyVirtualText%&gt; within InstallJammer, it will be substituted with the text "This is my virtual text."&nbsp; And, since virtual text can be embedded within other virtual text, you could set your virtual text to something like, "Today's date is &lt;%Date%&gt;" and InstallJammer will do the substitution of &lt;%Date%&gt; inside your text whenever you use it.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts4>Deleting Virtual Text</span></p>
<p class=rvps1><span class=rvts3>You can only delete virtual text that you have added to your project.&nbsp; Virtual text that is defined by InstallJammer cannot be deleted.&nbsp; To delete a virtual text definition that you have added, click on the row for the text and then click the "Delete Virtual Text" button on the toolbar in the panel.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>You can select multiple rows to delete at once.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/VirtualTextAPI.html.






































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>VirtualTextAPI</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="VirtualTextAPI">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333399" face="Verdana"><b>VirtualTextAPI</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="URLIsValid.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="VirtualTextExists.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::VirtualTextAPI</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This API is used to manipulate and query virtual text in an installer or uninstaller.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>See options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-do</span></p>
<p class=rvps1><span class=rvts2>Specifies the action the API should take.&nbsp; Possible values are:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=80>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; settype</span></p>
</td>
<td width=682>
<p class=rvps1><span class=rvts2>Set the type of a virtual text.&nbsp; Type affects how some virtual text is treated within the installer. </span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-type</span></p>
<p class=rvps1><span class=rvts2>Specifies the type to assign to the virtual text.&nbsp; The current available types are: boolean and directory.&nbsp; A boolean type means that the value saved in the virtual text will always be a 0 or 1 based on what is set.&nbsp; A directory type means that the virtual text will automatically be converted to the proper representation for the current platform.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/VirtualTextDefinitions.html.




















































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Virtual Text Definitions</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Virtual Text Definitions">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Virtual Text Definitions</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="WhatIsVirtualText.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="VirtualDirectoryDefinitions.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>The following virtual text definitions are currently available in InstallJammer.&nbsp; Anytime you see </span><span class=rvts3>?something?</span><span class=rvts2> inside of a virtual text field, it means that that virtual text can or must have an argument passed to it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%AllowLanguageSelection%&gt;</span></p>
<p class=rvps1><span class=rvts2>If true, the user will be prompted to select a language at the beginning of the install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%AppName%&gt;</span></p>
<p class=rvps1><span class=rvts2>The name of the application as set during build time in the Application Information tab.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ApplicationID%&gt;</span></p>
<p class=rvps1><span class=rvts2>A unique identifier for this application.&nbsp; This ID is set when the install project is first created and never changes through the life of the project.&nbsp; It can be used to identify previous installs of the same application on a target system, and InstallJammer uses it during uninstallation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%BuildVersion%&gt;</span></p>
<p class=rvps1><span class=rvts2>The build version is the fourth value of the &lt;%InstallVersion%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%CancelledInstallAction%&gt;</span></p>
<p class=rvps1><span class=rvts2>Contains the text describing the action InstallJammer will take if the install is cancelled mid-process.&nbsp; This virtual text is defined under the Install Features in the Application Information tab.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%CleanupCancelledInstall%&gt;</span></p>
<p class=rvps1><span class=rvts2>Tells InstallJammer whether it needs to cleanup a cancelled install or not.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Company%&gt;</span></p>
<p class=rvps1><span class=rvts2>The company name set during build time in the Application Information tab.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ConsoleMode%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the install is currently being run in console mode.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%CurrentAction%&gt;</span></p>
<p class=rvps1><span class=rvts2>The ID of the current action being executed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%CurrentCondition%&gt;</span></p>
<p class=rvps1><span class=rvts2>The ID of the current condition being executed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%CurrentObject%&gt;</span></p>
<p class=rvps1><span class=rvts2>The ID of the current object being used in the system.&nbsp; This can be a pane, action or condition.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%CurrentPane%&gt;</span></p>
<p class=rvps1><span class=rvts2>The Pane ID of the current pane displayed to the user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Date ?dateFormat?%&gt;</span></p>
<p class=rvps1><span class=rvts2>A formatted string of today's date based on &lt;%DateFormat%&gt;.&nbsp; The Date virtual text can receive an optional argument of the format to use for the date.</span></p>
<p class=rvps1><span class=rvts2>Defaults to &lt;%Date &lt;%DateFormat%&gt;%&gt;</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%DateFormat%&gt;</span></p>
<p class=rvps1><span class=rvts2>The default format to use for &lt;%Date%&gt; when no format argument is specified.</span></p>
<p class=rvps1><span class=rvts2>Defaults to %Y%m%d, which looks like 20051201.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Debugging%&gt;</span></p>
<p class=rvps1><span class=rvts2>If true, InstallJammer will run in debugging mode.&nbsp; Debug mode outputs debug messages to a log file and saves the temporary directory used during installation for later debugging.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%DefaultLanguage%&gt;</span></p>
<p class=rvps1><span class=rvts2>The default language if none is specified or if the user is not allowed to choose a language.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%DefaultMode%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the user selected to run in the install in Default mode.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Dir ?directory or filename? ?platform?%&gt;</span></p>
<p class=rvps1><span class=rvts2>Take the given directory and normalize it so that it matches the format of the current platform.&nbsp; On Windows this will use a \ as the path separator.&nbsp; On UNIX, the path separator will be / and any drive lettering (C:, D:, etc...) will be stripped off.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If a second argument is specified, it can be one of the following: </span><span class=rvts3>backslash, forwardslash, platform, unix or windows</span><span class=rvts2>.&nbsp; Backslash and forwardslash specifies which path separator to use but no other modifications are done to the directory.&nbsp; Unix or Windows will behave as described above for the given platform.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Dirname ?directory or filename?%&gt;</span></p>
<p class=rvps1><span class=rvts2>Given a directory or filename, return the parent directory.&nbsp; Example: &lt;%Dirname C:/foo/bar%&gt; would return C:/foo.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%DiskSpace ?disk space?%&gt;</span></p>
<p class=rvps1><span class=rvts2>Returns a pretty text string describing the space in disk space.&nbsp; Depending on the size, this will be N KB, N MB, or N GB where N is the size.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%DOSName ?directory or filename?%&gt;</span></p>
<p class=rvps1><span class=rvts2>Given a directory or filename, return the 8.3 short DOS name on Windows.&nbsp; This will return something like C:/Progra~1/file by using the Windows native short name.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Env ?variable?%&gt;</span></p>
<p class=rvps1><span class=rvts2>This will return the value of an environment variable if it exists.&nbsp; &lt;%Env PATH%&gt; would return the user's current PATH variable.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ErrorDirs%&gt; (set by Uninstall Selected Files)</span></p>
<p class=rvps1><span class=rvts2>If &lt;%ErrorsOccurred%&gt; is true, this virtual text may contain a list of directories that the uninstaller failed to remove.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ErrorFiles%&gt; (set by Uninstall Selected Files)</span></p>
<p class=rvps1><span class=rvts2>If &lt;%ErrorsOccurred%&gt; is true, this virtual text may contain a list of files that the uninstaller failed to remove.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Errors%&gt; (set by Uninstall Selected Files)</span></p>
<p class=rvps1><span class=rvts2>If &lt;%ErrorsOccurred%&gt; is true, this virtual text will contain a string representation of the errors that occurred during an uninstall.&nbsp; This is usually displayed to the user in the uninstall details.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ErrorsOccurred%&gt; (set by Uninstall Selected Files)</span></p>
<p class=rvps1><span class=rvts2>This is set during the Uninstall Selected Files action.&nbsp; It will be false if no errors occurred during the uninstall, or it will be true if some error happened while doing the uninstall.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Ext%&gt;</span></p>
<p class=rvps1><span class=rvts2>Return the executable extension for the current platform.&nbsp; This is .exe on Windows and empty on UNIX.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ExtractSolidArchivesOnStartup%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the developer has opted to extract any solid archives when the installer first starts.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%FileBeingInstalled%&gt;</span></p>
<p class=rvps1><span class=rvts2>The file currently being installed.&nbsp; This is only valid during file installation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%FileBeingInstalledText%&gt;</span></p>
<p class=rvps1><span class=rvts2>A pretty text describing the current file being installed.</span></p>
<p class=rvps1><span class=rvts2>Defaults to "Copying &lt;%FileBeingInstalled%&gt;"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%FileGroup ?file group?%&gt;</span></p>
<p class=rvps1><span class=rvts2>Given the name of a file group, return the full directory path for that file group.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%GroupBeingInstalled%&gt;</span></p>
<p class=rvps1><span class=rvts2>The name of the current file group being installed.&nbsp; This is only valid during file installation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%GroupBeingInstalledText%&gt;</span></p>
<p class=rvps1><span class=rvts2>A pretty text describing the current group being installed.</span></p>
<p class=rvps1><span class=rvts2>Defaults to "Installing &lt;%GroupBeingInstalled%&gt;"</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%GUID%&gt;</span></p>
<p class=rvps1><span class=rvts2>Generates a new globally unique identifier (GUID).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%GuiMode%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the install is currently running in a mode that requires a GUI.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%IncludeDebugging%&gt;</span></p>
<p class=rvps1><span class=rvts2>Whether or not debugging options were included in this installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallDirSuffix%&gt;</span></p>
<p class=rvps1><span class=rvts2>If this virtual text variable exists in your project, its value will automatically be appended to the &lt;%InstallDir%&gt; anytime it is changed if the &lt;%InstallDir%&gt;'s tail directory does not already match the value.&nbsp; So, if InstallDirSuffix were set to &lt;%AppName%&gt;, for example, the installer would always append the name of your application to the installation directory path no matter where the user chooses to install, unless the InstallDir already has &lt;%AppName%&gt; at the end.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallDrive%&gt;</span></p>
<p class=rvps1><span class=rvts2>This Windows-only virtual text holds the drive letter that the installation is targeted for.&nbsp; So, if &lt;%InstallDir%&gt; is C:/install, &lt;%InstallDrive%&gt; would be C:.&nbsp; This virtual text is automatically updated anytime the &lt;%InstallDir%&gt; value is changed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallFinished%&gt;</span></p>
<p class=rvps1><span class=rvts2>Whether or not InstallJammer completed the file installation.&nbsp; This is only true if file installation was begun and completed without the user cancelling.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallHasSolidArchives%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the installer has any solid archives.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallID%&gt;</span></p>
<p class=rvps1><span class=rvts2>A unique identifier for this instance of the running installer.&nbsp; This ID is set when the installer first starts up, and a new one is generated every time the installer is run.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallMode%&gt;</span></p>
<p class=rvps1><span class=rvts2>The current mode of installation chosen by the user.&nbsp; Can be: Console, Default, Silent or Standard.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallPassword%&gt;</span></p>
<p class=rvps1><span class=rvts2>This virtual text is used, by default, in the Install Password pane of most themes.&nbsp; It is empty by default, and will contain a password if the user enters one.&nbsp; This is usually matched against the &lt;%InstallPasswordEncrypted%&gt; virtual text to see if the password is correct.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallPasswordEncrypted%&gt;</span></p>
<p class=rvps1><span class=rvts2>If the project was defined with an install password for the installer, this virtual text will contain the encrypted form of that password.&nbsp; The plain-text form of the install password is never stored in the installer itself.&nbsp; This virtual text is usually compared against a password the user enters using the Password Test Condition to see if they match.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallPercentComplete%&gt;</span></p>
<p class=rvps1><span class=rvts2>The current percentage complete of the file installation.&nbsp; This is only valid during file installation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallRegistryInfo%&gt;</span></p>
<p class=rvps1><span class=rvts2>If this virtual text is set to false in your project, InstallJammer will not attempt to create a registry directory separate from your installation to hold its install information.&nbsp; Instead, all of the install information will be stored inside the uninstaller so that it can properly uninstall.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallSource%&gt;</span></p>
<p class=rvps1><span class=rvts2>The full path to the source directory the installation executable was started from.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallStarted%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the file installation portion of the install was started, whether it completed or not.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallStopped%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the user cancelled the file installation before it had a chance to complete.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallType%&gt;</span></p>
<p class=rvps1><span class=rvts2>The setup type of installation the user has chosen to install. If the user is not given the option to select a setup type, or that pane has not been shown yet, this variable will default to the Default Setup Type set during build time.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallVersion%&gt;</span></p>
<p class=rvps1><span class=rvts2>The install version of your application.&nbsp; This version is represented as X.X.X.X and is also used by InstallJammer when determining whether to install files based on version numbers.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Installer%&gt;</span></p>
<p class=rvps1><span class=rvts2>The full path to the installation executable when it was started.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%InstallerID%&gt;</span></p>
<p class=rvps1><span class=rvts2>A unique identifier for this installer.&nbsp; This ID is set when the installer is built and remains the same no matter how many times the install is run.&nbsp; This ID changes with each build of an installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Installing%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the file installation is currently in progress.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Language%&gt;</span></p>
<p class=rvps1><span class=rvts2>The current language of the installer as expressed as a language code, an optional country code, and an optional system-specific code, each separated by _.&nbsp; The country and language code are specified in standards ISO-639 and ISO-3166.&nbsp; For example, the locale "en" specified English, and "en_US" specifies U.S. english.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%LastGUID%&gt;</span></p>
<p class=rvps1><span class=rvts2>Contains the value of the last GUID generated by using the &lt;%GUID%&gt; virtual text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%LastUUID%&gt;</span></p>
<p class=rvps1><span class=rvts2>Contains the value of the last UUID generated by using the &lt;%UUID%&gt; virtual text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%LicenseAccepted%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the user has seen and accepted the license agreement for the application.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%MajorVersion%&gt;</span></p>
<p class=rvps1><span class=rvts2>The major version is the first value of the &lt;%InstallVersion%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%MinorVersion%&gt;</span></p>
<p class=rvps1><span class=rvts2>The minor version is the second value of the &lt;%InstallVersion%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PackageDescription%&gt;</span></p>
<p class=rvps1><span class=rvts2>The package description defined in the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PackageLicense%&gt;</span></p>
<p class=rvps1><span class=rvts2>The package license defined in the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PackageMaintainer%&gt;</span></p>
<p class=rvps1><span class=rvts2>The package maintainer defined in the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PackageName%&gt;</span></p>
<p class=rvps1><span class=rvts2>The package name defined in the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PackagePackager%&gt;</span></p>
<p class=rvps1><span class=rvts2>The package packager defined in the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PackageRelease%&gt;</span></p>
<p class=rvps1><span class=rvts2>The package release version defined in the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PackageSummary%&gt;</span></p>
<p class=rvps1><span class=rvts2>The package summary defined in the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PackageVersion%&gt;</span></p>
<p class=rvps1><span class=rvts2>The package version defined in the project.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PatchVersion%&gt;</span></p>
<p class=rvps1><span class=rvts2>The patch version is the third value of the &lt;%InstallVersion%&gt;.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PathSeparator%&gt;</span></p>
<p class=rvps1><span class=rvts2>The character used to separate paths in variables on the target system.&nbsp; This is ; for Windows and : for UNIX.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Platform%&gt;</span></p>
<p class=rvps1><span class=rvts2>The name of the current platform being installed. This variable only exists during installation time. </span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ProgramExecutable%&gt;</span></p>
<p class=rvps1><span class=rvts2>If specified by the user during build time, this variable contains the path to the executable that will start the installed program upon completion of installation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ProgramFolderName%&gt;</span></p>
<p class=rvps1><span class=rvts2>The name of the Program Folder the user has chosen. If the user is not given the option to select the program folder, or that pane has not been shown yet, this variable will default to the Default Program Folder set during build time.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ProgramLicense%&gt;</span></p>
<p class=rvps1><span class=rvts2>The location of the application's LICENSE file as specified in the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ProgramReadme%&gt;</span></p>
<p class=rvps1><span class=rvts2>The location of the application's README file as specified in the project.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%PromptForRoot%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the developer has opted to prompt for the root password when a root password is required to run the (un)install.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Property ?object? ?property?%&gt;</span></p>
<p class=rvps1><span class=rvts2>This will return the value of a property on a given object.&nbsp; If object is specified, the property value for that object will be returned.&nbsp; If no object is specified, the property will be returned for the currently-active object.&nbsp; This can be whatever action or condition is currently being executed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%RealUsername%&gt;</span></p>
<p class=rvps1><span class=rvts2>The name of the real user running the install.&nbsp; If the user is running as root (through su or sudo), the &lt;%Username%&gt; will show root instead of the real user name.&nbsp; This value always reflects the real user.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%RegValue ?registry key? ?value?%&gt;</span></p>
<p class=rvps1><span class=rvts2>The current value of a registry key on Windows.&nbsp; If only a key is passed, the default value for that key will be returned.&nbsp; If value is passed, that value within the specified key will be returned.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%RequireRoot%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the (un)installer requires root to run.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%RunningInstaller%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the currently-running program is the installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%RunningUninstaller%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the currently-running program is the uninstaller.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ScriptExt%&gt;</span></p>
<p class=rvps1><span class=rvts2>This is the file extension for common script on each platform.&nbsp; This is set to .bat on Windows and .sh on UNIX platforms.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%SelectedComponents%&gt;</span></p>
<p class=rvps1><span class=rvts2>A list of components that are currently selected for installation.&nbsp; This should be treated as a Tcl list.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%SelectedFileGroups%&gt;</span></p>
<p class=rvps1><span class=rvts2>A list of file groups that are currently selected for installation.&nbsp; This should be treated as a Tcl list.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ShortAppName%&gt;</span></p>
<p class=rvps1><span class=rvts2>A shortened version of your application name.&nbsp; This is usually used on UNIX systems as a directory for your application, so it should usually be all lowercase and contain no spaces.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%ShowConsole%&gt;</span></p>
<p class=rvps1><span class=rvts2>If true, InstallJammer will show a debugging console on startup.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%SilentMode%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the user selected to run the install in Silent mode.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%SolidArchivesExtracted%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the installer has any solid archives that have been extracted already.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%SpaceAvailable ?directory?%&gt;</span></p>
<p class=rvps1><span class=rvts2>Returns the disk space available on the current drive.&nbsp; If directory is specified, returns the disk space available for that drive.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%SpaceAvailableText%&gt;</span></p>
<p class=rvps1><span class=rvts2>Returns a pretty text description of the disk space available on the current drive.</span></p>
<p class=rvps1><span class=rvts2>Equivalent to &lt;%DiskSpace &lt;%SpaceAvailable%&gt;%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%SpaceRequired%&gt;</span></p>
<p class=rvps1><span class=rvts2>The current amount of space required on the target system to install the selected components.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%SpaceRequiredText%&gt;</span></p>
<p class=rvps1><span class=rvts2>A pretty text describing the amount of space required to install.</span></p>
<p class=rvps1><span class=rvts2>Equivalent to &lt;%DiskSpace &lt;%SpaceRequired%&gt;%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Status%&gt;</span></p>
<p class=rvps1><span class=rvts2>This variable is used as the current status of what InstallJammer is doing.&nbsp; During file installation, this is usually set to &lt;%FileBeingInstalledText%&gt;, but it can reflect many other actions InstallJammer is taking.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Tail ?directory or filename?%&gt;</span></p>
<p class=rvps1><span class=rvts2>Given a directory or filename, return the tail end of the path.&nbsp; Example:&nbsp; &lt;%Tail C:/foo/bar%&gt; would return bar.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Testing%&gt;</span></p>
<p class=rvps1><span class=rvts2>If true, InstallJammer will run in test mode which means no files will be installed or uninstalled.&nbsp; This does not stop other actions that create shortcuts, etc...</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%UninstallMode%&gt;</span></p>
<p class=rvps1><span class=rvts2>The current uninstall mode: Console, Silent or Standard.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%UninstallPercentComplete%&gt;</span></p>
<p class=rvps1><span class=rvts2>The current percentage complete of the file uninstallation.&nbsp; This is only valid during uninstall.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%UpgradeApplicationID%&gt;</span></p>
<p class=rvps1><span class=rvts2>The Upgrade Application ID specified by the developer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%UpgradeInstall%&gt;</span></p>
<p class=rvps1><span class=rvts2>If Upgrade Application ID is not null, this value will be true, telling InstallJammer that this is an upgrade install and certain actions should not be performed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%UserIsRoot%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the user currently installing is root.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%UserMovedBack%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the user has reached the current pane by clicking the Back button.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%UserMovedNext%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the user has reached the current pane by clicking the Next button.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Username%&gt;</span></p>
<p class=rvps1><span class=rvts2>The username of the current system user executing the install.&nbsp; If the user is currently root, this value will show 'root'.&nbsp; If you want to know the user who is currently running as root, you can use &lt;%RealUsername%&gt;</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%Version%&gt;</span></p>
<p class=rvps1><span class=rvts2>The version set during build time in the Application Information tab.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%WindowsPlatform%&gt;</span></p>
<p class=rvps1><span class=rvts2>A string specifying the exact version of Windows currently being installed on.&nbsp; Possible versions are: Win95, Win98, WinNT, WinME, Win2k, WinXP, Win2003, Vista, and Windows7.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%WizardCancelled%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the wizard started and the user cancelled the wizard before it completed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%WizardFinished%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the wizard was started and actually completed successfully without the user cancelling.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%WizardFirstStep%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the pane currently displayed is the first step of the wizard.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%WizardLastStep%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the pane currently displayed is the last step of the wizard.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>&lt;%WizardStarted%&gt;</span></p>
<p class=rvps1><span class=rvts2>True if the wizard started up successfully.&nbsp; This virtual text will always be false for silent and console installs since no wizard is ever started.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/VirtualTextExists.html.
























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>VirtualTextExists</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="VirtualTextExists">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>VirtualTextExists</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="VirtualTextAPI.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CreateANewInstallFast.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::VirtualTextExists</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Check to see if the given virtual text variable exists in the given language.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>True or false.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-language &lt;language or None&gt;</span></p>
<p class=rvps1><span class=rvts2>If a language is passed, the API will check to see if the virtual text exists in that language.&nbsp; If no language is passed, or if language is None, the virtual text will be checked in the language-neutral messages.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-virtualtext &lt;virtual text string&gt; (required)</span></p>
<p class=rvps1><span class=rvts2>The virtual text string to be substituted.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/VirtualTextTestCondition.html.










































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Virtual Text Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Virtual Text Exists Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Virtual Text Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ScriptCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="PlatformCondition.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition checks to see if a virtual text variable exists or not.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Language</span></p>
<p class=rvps1><span class=rvts2>The language of the virtual text you are checking.&nbsp; None means to check the virtual text without a language.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=258>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; exists</span></p>
</td>
<td width=504>
<p class=rvps1><span class=rvts2>True if the virtual text exists.</span></p>
</td>
</tr>
<tr valign=top>
<td width=258>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not exist</span></p>
</td>
<td width=504>
<p class=rvps1><span class=rvts2>True if the virtual text does not exist.</span></p>
</td>
</tr>
<tr valign=top>
<td width=258>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; was set from the command line</span></p>
</td>
<td width=504>
<p class=rvps1><span class=rvts2>True if the virtual text was set or modified as a result of an option passed on the command line.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Virtual Text</span></p>
<p class=rvps1><span class=rvts2>The virtual text (without &lt;% and %&gt;) to check.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/Wait.html.










































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Wait</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Wait">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Wait</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="TextWindow.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddInstallInfo.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will cause InstallJammer to wait a specified number of milliseconds before continuing with the install.&nbsp; This works just like sleep on most systems.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Wait Time</span></p>
<p class=rvps1><span class=rvts2>The amount of time (in milliseconds) to wait.&nbsp; 1000 == 1 second.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/Welcome.html.












































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Welcome</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Welcome">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
a.rvts7, span.rvts7
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts7:hover { color: #0000ff; }
a.rvts8, span.rvts8
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts8:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Welcome</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="License.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>InstallJammer is a multiplatform GUI installer and builder designed to be completely cross-platform and function on Windows and most all versions of UNIX with eventual support for Mac OS X.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Using InstallJammer</span></p>
<p class=rvps1><span class=rvts2>You can read through </span><a class=rvts4 href="GettingStarted.html">Getting Started</a><span class=rvts2> to learn a little bit about how to start using InstallJammer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>New Features and Bug Fixes</span></p>
<p class=rvps1><span class=rvts2>If you are upgrading from a previous version of InstallJammer, read through the </span><a class=rvts5 href="ReleaseNotes.html">Release Notes</a><span class=rvts2> to learn about all of the changes since the last version.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Helping InstallJammer Development</span></p>
<p class=rvps1><span class=rvts2>InstallJammer will continue to develop with help from people like you.&nbsp; Please report any bugs that you find, or let us know if there are features that you would like to see in InstallJammer.&nbsp; InstallJammer is is always improving and still has bugs to work out, but it can only get better with help from you.&nbsp; Below are some links that may help you help us.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><a class=rvts6 href="http://www.installjammer.com/" target="_blank">InstallJammer Homepage</a></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><a class=rvts7 href="http://www.installjammer.com/forums/">Ask a Question</a></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><a class=rvts8 href="http://tracker.installjammer.com/" target="_blank">Report a Bug or Request a New Feature</a><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WhatAreActionGroups.html.
























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>What are Action Groups?</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="What are Action Groups?">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
span.rvts6
{
 font-family: 'Verdana';
 color: #ff0000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>What are Action Groups?</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="WhatAreActions.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ActionStandardProperties.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>Action groups are a way to group individual actions together under a single set of conditions.&nbsp; Action groups are defined independent of any particular pane and can be called from anywhere in an install using the </span><a class=rvts4 href="ExecuteAction.html">Execute Action</a><span class=rvts2> action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>When executing an action group, the conditions of the Execute Action are first checked, then any conditions on the action group itself are checked, and finally, if the Evaluate Conditions property of the Execute Action is true, the individual conditions on each action in the action group are checked before executing.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>If any conditions on the Action Group exist that are executed Before the Next Action, these conditions are checked after all of the actions in the group are executed, and if the conditions fail, the entire action group will be executed again.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=22>
<p class=rvps1><img border="0" src="Images/note.jpg" alt="Note" width="32" height="32"></p>
</td>
<td width=604>
<p class=rvps1><span class=rvts6>InstallJammer creates five action groups for a new project:&nbsp; Setup Actions, Startup Actions, (Un)Install Actions, Finish Actions and Cancel Actions.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Setup Actions</span></p>
<p class=rvps1><span class=rvts2>This action group is executed near the very beginning of the install and uninstall startup.&nbsp; It happens just before the command-line arguments specified by the user are parsed.&nbsp; Since no wizard exists yet and some of the setup has not been done yet, this action group should only be used to initialize virtual text or to alter command-line options before they are parsed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Startup Actions</span></p>
<p class=rvps1><span class=rvts2>This action group is executed automatically during the startup of the installer.&nbsp; This is done after some default checks and setup has been done but before the first pane of the wizard is displayed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>(Un)Install Actions</span></p>
<p class=rvps1><span class=rvts2>This action group is called from within the (un)install panes and is usually attached to the Copy Files pane.&nbsp; InstallJammer does not call this action group automatically, instead letting you call it wherever you want from within the installer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Finish Actions</span></p>
<p class=rvps1><span class=rvts2>This action group is executed automatically when the install is finished.&nbsp; It is the last thing called before the installer exits.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Cancel Actions</span></p>
<p class=rvps1><span class=rvts2>This action group is executed automatically when the install is cancelled.&nbsp; It is the last thing called before the installer exits.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="StandardProperties.html">Standard Properties</a><span class=rvts2>.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WhatAreActions.html.


























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>What are Actions?</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="What are actions?">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>What are Actions?</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="WhatArePanes.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="WhatAreActionGroups.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>Actions are what InstallJammer uses to perform tasks while an installer or uninstaller is running.&nbsp; An action can be anything that you might want to do.&nbsp; Any action can be added to any pane in an install, and each action is checked and run in order during installation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Actions allow you a great amount of flexibility in your installer.&nbsp; While many actions are provided as a convenience for common tasks you might want to perform, you also have the option to script your actions to do anything you like.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Each action may also have any number of conditions (see: </span><a class=rvts5 href="WhatAreConditions.html">What are Conditions?</a><span class=rvts2>) attached to it that are checked before executing.&nbsp; If the action does not meet the necessary conditions, it will be skipped, and the next action will be checked.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Actions may also be a part of an action group (see: </span><a class=rvts4 href="WhatAreActionGroups.html">What are Action Groups?</a><span class=rvts2>) where the group itself has a set of conditions that determine whether the group will be executed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>A new install will come setup with many default actions.&nbsp; Without actions, the installer is nothing more than a bunch of panes to move back-and-forth through.&nbsp; The actions are what really does the work during the installation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts6 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>Most actions and conditions in InstallJammer are supported by all available platforms, but some of them are platform-specific and only apply to those platforms.&nbsp; When dealing with actions or conditions that are platform-specific, you don't need to worry about adding conditions to check the platform.&nbsp; When the documentation lists that only certain platforms are supported for an action or condition, InstallJammer will automatically skip those actions on other platforms during execution.&nbsp; The action will still show up in debug logs as being exected though, so if you wanted to make that clearer, you could add your own Platform Condition.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2>Each action has a different set of advanced properties that further define the properties of the action.&nbsp; Please see the documentation for each type of action for more information.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WhatAreConditions.html.


















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>What are Conditions?</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="What are Conditions?">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
a.rvts3, span.rvts3
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts3:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>What are Conditions?</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="RemovePaneFromOrder.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="ConditionStandardProperties.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>Conditions are a way to tell InstallJammer how and when it should do certain things within an installer.&nbsp; Most objects in InstallJammer can have conditions attached to them that will control whether or not an action is taken on that object.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>When conditions are checked, they are checked with an explicit AND, which means that the first false condition that is found will stop, and the rest will not be checked.&nbsp; The </span><a class=rvts3 href="ScriptCondition.html">Script Condition</a><span class=rvts2> can be used in cases where more complicated conditions are needed.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WhatArePanes.html.




































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>What are Panes?</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="What Are Panes?">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>What are Panes?</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="StandardProperties.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="WhatAreActions.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>Panes are what the user sees as they move forward and backward through your installer.&nbsp; Your available panes are defined by the theme you chose when you created your project, and each theme has a different set of panes and a different look-and-feel for those panes.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>By default, the install theme you choose will select a default set of panes that are the most common for a simple installer.&nbsp; These usually include a welcome, a pane to let the user select their installation directory, the pane to copy the files and do the install, and a finishing pane.&nbsp; For most applications, these are the simplest panes you will need to give your user the minimum flexibility during installation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Select a pane in your install, and you will see the properties for that pane come up to the right of the pane tree.&nbsp; These properties define the actions and look-and-feel of your pane.&nbsp; The most common options will already be chosen for you, but you can modify your panes any way you like.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="StandardProperties.html">Standard Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2>The advanced properties of a pane are different for each pane in each theme.&nbsp; Most are self-explanatory, but if you need help, you can usually find a brief description of the property by hovering over the property's name for a second, and a help balloon will appear.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Below is a list of some common properties that appear throughout the themes.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Anchor</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer where to place a window when displaying it.&nbsp; The coordinates are defined as the points of the desktop (n, s, e, w, etc...).&nbsp; So, s will place the window at the bottom center of the screen.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Buttons</span></p>
<p class=rvps1><span class=rvts2>Defines the buttons that are available on the selected pane.&nbsp; Each theme defines the buttons that are available on each pane and sets up the default values for each pane based on default settings.&nbsp; Any button not included in the list given will be hidden when the pane is displayed.&nbsp; Disabling a button is usually the better way to go to keep your installer uniform.&nbsp; This can be achieved with the </span><a class=rvts5 href="ModifyWidget.html">Modify Widget</a><span class=rvts2> action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Icon</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer what image to use as a small icon on the selected pane.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Image</span></p>
<p class=rvps1><span class=rvts2>This property tells InstallJammer what image to use as a larger image on the selected pane.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Text Properties</span></p>
<p class=rvps1><span class=rvts2>Text properties are properties that directly relate to the text displayed in a pane.&nbsp; They have the added option of not substituting virtual text if it's not required or if you don't want it to.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Besides every button on the wizard, text properties also include any widget on a pane whose text can be changed.&nbsp; Anytime you change a text property, you can preview the pane to see what the new text will look like during installation.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WhatIsTclTk.html.










































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>What is Tcl/Tk?</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="What is Tcl/Tk?">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
}
span.rvts3
{
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
a.rvts7, span.rvts7
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts7:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>What is Tcl/Tk?</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="CreateANewInstallStep-by-Step.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>Tcl (Tool Command Language) is a very powerful but easy to learn dynamic programming language, suitable for a very wide range of uses, including web and desktop applications, networking, administration, testing and many more. Open source and business-friendly, Tcl is a mature yet evolving language that is truly cross platform, easily deployed and highly extensible.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Tk is a graphical user interface toolkit that takes developing desktop applications to a higher level than conventional approaches. Tk is the standard GUI not only for Tcl, but for many other dynamic languages, and can produce rich, native applications that run unchanged across Windows, Mac OS X, Linux and more.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>InstallJammer is written almost entirely in Tcl/Tk with a little bit of help from some extensions written in C.&nbsp; Since all scripting in InstallJammer is done through Tcl/Tk, it might be helpful for you to learn a little about Tcl if you plan on doing any kind of complex operations with your installer.&nbsp; Below are some links to get you started.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><a class=rvts5 href="http://www.tcl.tk/about/compare.html" target="_blank">Why would I choose Tcl/Tk over...?</a></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><a class=rvts6 href="http://www.tcl.tk/about/language.html" target="_blank">What does Tcl/Tk code look like?</a></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><a class=rvts7 href="http://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html" target="_blank">A Full Tcl Tutorial</a><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WhatIsTheBuilderAPI.html.
































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>What is the Builder API?</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="What is the Builder API?">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
span.rvts5
{
 font-family: 'Courier New';
 color: #993366;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>What is the Builder API?</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="DebuggingAnInstall.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="GetAction.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>The Builder API is a set of functions that can be used in control scripts when executing the builder from the command line.&nbsp; This allows you to create scripts that can be passed on the command line that modify your installer based on criteria.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Calling a Builder API proc</span></p>
<p class=rvps1><span class=rvts2>All of the procs in the Builder API are in the ::BuilderAPI namespace.&nbsp; To call a proc in the Builder API, simply use the fully-qualified name of the proc in your code.&nbsp; All arguments passed to an Builder API proc are non-positional key-value pairs.&nbsp; That means that it doesn't matter what order you pass the arguments in since each argument is specified as a -option with a value.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>For example, let's say we wanted to change the name of the installer produced for the Windows platform in a certain case.&nbsp; You would add something like this to a control script:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::BuilderAPI::SetPlatformProperty -platform Windows -property Executable -value "setup.exe"</span>
<br><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>In this example, we call the proc ::BuilderAPI::SetPlatformProperty with three arguments:&nbsp; -platform, -property and -value.&nbsp; Each property must have a value after it.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Finding the arguments to an API call</span></p>
<p class=rvps1><span class=rvts2>All API calls are loaded into the install builder when it loads, so you can easily go into the console (through the Help-&gt;Show Debug Console menu) and type a Builder API call to see what it can do.&nbsp; To see the usage for an API call, type the name of the call and the argument -? into the console.&nbsp; Like this:</span>
<br><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts5>::BuilderAPI::SetPlatformProperty -?</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This will dump the usage information, including all possible arguments, for the ::BuilderAPI::SetPlatformProperty API call.&nbsp; Of course, you can always read the documentation for each call as well, but this might be quicker for some people.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WhatIsTheInstallAPI.html.
































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>What is the Install API?</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="What is the Install API?">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier New';
 color: #993366;
}
span.rvts5
{
 font-family: 'Verdana';
 color: #ff0000;
}
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
a.rvts7, span.rvts7
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts7:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>What is the Install API?</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="SetPlatformProperty.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="AddInstallInfo1.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>The Install API is a set of functions that can be used in your installer to create more complex installers than is normally available through the standard actions and conditions.&nbsp; Some of the actions and conditions in InstallJammer even use pieces of the Install API to do the real work.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The Install API is loaded with procs that you can call from </span><a class=rvts6 href="ExecuteScript.html">Execute Script</a><span class=rvts2> actions or </span><a class=rvts7 href="ScriptCondition.html">Script Condition</a><span class=rvts2> conditions that give you program-level access to the inner workings of InstallJammer.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=20>
<p class=rvps1><img border="0" src="Images/detail.jpg" alt="Technical Detail" width="32" height="32"></p>
</td>
<td width=606>
<p class=rvps1><span class=rvts5>It is important to know that the Install API is built on-the-fly as your installer is packaged.&nbsp; Only procs that you actually use in your installer will be included in the packaged installer.&nbsp; This really only means that you cannot make API calls from a running console unless you are already using that API somewhere in your installer since the API call would not have been built into your installer.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Calling an Install API proc</span></p>
<p class=rvps1><span class=rvts2>All of the procs in the Install API are in the ::InstallAPI namespace.&nbsp; To call a proc in the Install API, simply use the fully-qualified name of the proc in your code.&nbsp; All arguments passed to an Install API proc are non-positional key-value pairs.&nbsp; That means that it doesn't matter what order you pass the arguments in since each argument is specified as a -option with a value.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>For example, let's say we had an Execute Script action where we wanted to do some checking and then set a virtual text variable.&nbsp; It might look something like this:</span>
<br><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>if {![::InstallAPI::VirtualTextExists -virtualtext Foo]} {</span></p>
<p class=rvps1><span class=rvts4>&nbsp;&nbsp;&nbsp; ::InstallAPI::SetVirtualText -virtualText Foo -value Bar</span></p>
<p class=rvps1><span class=rvts4>}</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>As you can see from the example, we make two calls to procs in the ::InstallAPI namespace.&nbsp; This code uses ::InstallAPI::VirtualTextExists to check and see if the virtual text Foo exists, and if it doesn't already exist, we're going to use ::InstallAPI::SetVirtualText to set it to Bar.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The arguments -virtualtext Foo passed to ::InstallAPI::VirtualTextExists tells the call that we want to check if the virtual text variable Foo exists.&nbsp; The arguments -virtualtext Foo -value Bar tell ::InstallAPI::SetVirtualText that we want to set the virtual text variable Foo to the value Bar.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Finding the arguments to an API call</span></p>
<p class=rvps1><span class=rvts2>All API calls are loaded into the install builder when it loads, so you can easily go into the console (through the Help-&gt;Show Debug Console menu) and type an Install API call to see what it can do.&nbsp; To see the usage for an API call, type the name of the call and the argument -? into the console.&nbsp; Like this:</span>
<br><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>::InstallAPI::SetVirtualText -?</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This will dump the usage information, including all possible arguments, for the ::InstallAPI::SetVirtualText API call.&nbsp; Of course, you can always read the documentation for each call as well, but this might be quicker for some people.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WhatIsVirtualText.html.








































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>What is Virtual Text?</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="What is Virtual Text?">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Verdana';
}
span.rvts5
{
 font-family: 'Verdana';
 font-weight: bold;
}
a.rvts6, span.rvts6
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts6:hover { color: #0000ff; }
a.rvts7, span.rvts7
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts7:hover { color: #0000ff; }
a.rvts8, span.rvts8
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts8:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>What is Virtual Text?</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="WindowsServiceTestCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="VirtualTextDefinitions.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts4>Virtual text is used throughout InstallJammer as a way to define variables within an install and sometimes within the install builder itself.&nbsp; You will see virtual text throughout your use of InstallJammer as text that is between &lt;% and %&gt;.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Some virtual text is defined by you when you create your project and other virtual text is defined by InstallJammer when it builds your project.&nbsp; An example of virtual text that you define is the &lt;%AppName%&gt; virtual text which represents the Application Name you filled in when you created your project.&nbsp; An example of virtual text defined by InstallJammer would be &lt;%InstallMode%&gt; which, during installation, can tell you whether the user chose a Standard, Default or Silent install.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Virtual text is an easy way for InstallJammer to represent variable data within an install, and since it can be nested, virtual text can contain other virtual text that will all be represented when it is used within an install.</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts5>Using Virtual Text&nbsp; </span></p>
<p class=rvps1><span class=rvts4>Virtual text can be used almost anywhere in an install, and InstallJammer will automatically substitute the virtual text for its value when it is needed.&nbsp; To use virtual text, simply use one of the available </span><a class=rvts6 href="VirtualTextDefinitions.html">Virtual Text Definitions</a><span class=rvts2> between &lt;% and %&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>For example, &lt;%AppName%&gt; when used in a project will be substituted for your Application Name during installation.&nbsp; &lt;%Platform%&gt; will be substituted for the name of the current platform you're installing on (Windows, Linux-x86, etc...).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Virtual text can be nested inside of another virtual text definition, and InstallJammer will automatically substitute all the values recursively.&nbsp; This means that if your Application Name contains "My Application &lt;%Version%&gt;" InstallJammer will substitute the &lt;%Version%&gt; recursively inside the virtual text to the value of your application's version.&nbsp; So, you would get "My Application 1.0" (or whatever your version is).</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Arguments in Virtual Text&nbsp; </span></p>
<p class=rvps1><span class=rvts2>Some virtual text fields can also receive arguments that modify the value of the virtual text.&nbsp; In this case, the virtual text will not be a single word surrounded by &lt;% and %&gt;, but will instead be the first word of the virtual text along with arguments passed after the word.&nbsp; An example is the &lt;%Date%&gt; virtual text which can be passed with an argument that specifies the format of the date string.&nbsp; Example:</span>
<br><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&lt;%Date %m/%d/%Y%&gt;</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This tells InstallJammer to return today's date in format of Month/Day/Four-digit-year.&nbsp; %m/%d/%Y is an argument passed to the Date virtual text.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>Another example:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>&lt;%Dir C:\foo\bar forwardslash%&gt;</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>would return</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>C:/foo/bar</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Boolean Values in Virtual Text&nbsp; </span></p>
<p class=rvps1><span class=rvts2>InstallJammer automatically converts any virtual text value that looks like a boolean into a 0 or 1.&nbsp; This is mostly to make dealing with booleans simpler, but it's also so that checkbuttons respond accurately to virtual text since checkbuttons expect a 0 or 1 for value and not the various boolean values that are acceptable.&nbsp; Acceptable boolean values are: 0, false, no, or off or 1, true, yes or on, or any abbreviated or uppercase spellings.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>You should always check virtual text variables that are boolean by checking to see if the string is true or false and not a specific string like yes or no.&nbsp; The </span><a class=rvts7 href="StringIsCondition.html">String Is Condition</a><span class=rvts2> is better than a </span><a class=rvts8 href="StringEqualCondition.html">String Equal Condition</a><span class=rvts2> for boolean values.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WindowsServiceTestCondition.html.




























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Windows Service Test Condition</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Windows Service Test Condition">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
a.rvts4, span.rvts4
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts4:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
.rvps2
{
 margin: 7px 0px 7px 0px;
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Windows Service Test Condition</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="RegistryEntryExistsCondition.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="WhatIsVirtualText.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This condition tests certain properties of a Windows service.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts4 href="ConditionStandardProperties.html">Standard Condition Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Database</span></p>
<p class=rvps2><span class=rvts2>Specifies the service control database to be operated on. By default, this is the active service control database on the target system.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Operator</span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=134>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; exists</span></p>
</td>
<td width=628>
<p class=rvps1><span class=rvts2>True if the service exists.</span></p>
</td>
</tr>
<tr valign=top>
<td width=134>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; does not exist</span></p>
</td>
<td width=628>
<p class=rvps1><span class=rvts2>True if the service does not exist.</span></p>
</td>
</tr>
<tr valign=top>
<td width=134>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is paused</span></p>
</td>
<td width=628>
<p class=rvps1><span class=rvts2>True if the service is in a paused state.</span></p>
</td>
</tr>
<tr valign=top>
<td width=134>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is running</span></p>
</td>
<td width=628>
<p class=rvps1><span class=rvts2>True if the service is currently running.</span></p>
</td>
</tr>
<tr valign=top>
<td width=134>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; is stopped</span></p>
</td>
<td width=628>
<p class=rvps1><span class=rvts2>True if the service is not currently running.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Service Name</span></p>
<p class=rvps1><span class=rvts2>The name of the service to perform the action on.&nbsp; This can be the internal or the display name of the service.&nbsp; If the display name is given, it will automatically be translated to the internal service name for the action.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>System</span></p>
<p class=rvps2><span class=rvts2>Specifies the name of the system on which the command should be invoked. By default, this is the local system.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WizardAPI.html.




























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>WizardAPI</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="WizardAPI">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333399" face="Verdana"><b>WizardAPI</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="VirtualTextExists.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="CreateANewInstallFast.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts3>::InstallAPI::WizardAPI</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>This API is used to manipulate the main (un)install wizard.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Returns</span></p>
<p class=rvps1><span class=rvts2>See options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Options</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-checkconditions (default 0)</span></p>
<p class=rvps1><span class=rvts2>If this property is true, the wizard will check any conditions on the current pane before moving forward or backward.&nbsp; The conditions could stop the wizard from moving if the conditions are not met.&nbsp; If this property is false, the wizard will skip any conditions and move without checking them.</span></p>
<p class=rvps1><span class=rvts3><br></span></p>
<p class=rvps1><span class=rvts3>-do</span></p>
<p class=rvps1><span class=rvts2>Specifies the action the API should take.&nbsp; Possible values are:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<div class=rvps1><table border=0 cellpadding=1 cellspacing=2 style="border-width: 0px;">
<tr valign=top>
<td width=80>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; back</span></p>
</td>
<td width=682>
<p class=rvps1><span class=rvts2>Move the wizard back one pane.</span></p>
</td>
</tr>
<tr valign=top>
<td width=80>
<p class=rvps1><span class=rvts3>&nbsp;&nbsp;&nbsp; next</span></p>
</td>
<td width=682>
<p class=rvps1><span class=rvts2>Move the wizard forward one pane.&nbsp; If there is no pane left to move forward to, the wizard will either do nothing or exit depending on the -exit option.</span></p>
</td>
</tr>
</table>
</div>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>-exit</span></p>
<p class=rvps1><span class=rvts2>If this property is true and there is no next pane when moving forward, the installer will simply exit.</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/WriteTextToFile.html.








































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><TITLE>Write Text to File</TITLE><meta name="generator" content="Fast-Help"><meta name="keywords" content="Write Text to File">
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
#FHNonScroll
{padding: 6px 6px 0px 6px; border-bottom: none; background: #D1D1D1; vertical-align: top;z-index: 2; visibility: visible; position: absolute; left: 0; top: 0; width: 100%; }
#FHScroll
{left: 0; top: 0px; position: absolute; margin: 0; padding: 10px; z-index: 1; background-repeat: no-repeat; background-position: bottom right; background-attachment: fixed; }





/* ========== Text Styles ========== */
hr { color: #000000}
body, table /* Normal */
{
 font-size: 10pt;
 font-family: 'Arial';
 font-style: normal;
 font-weight: normal;
 color: #000000;
 text-decoration: none;
}
span.rvts1
{
 font-family: 'Arial Unicode MS';
}
span.rvts2
{
 font-family: 'Verdana';
 color: #000000;
}
span.rvts3
{
 font-family: 'Verdana';
 font-weight: bold;
 color: #000000;
}
span.rvts4
{
 font-family: 'Courier';
 color: #000000;
}
a.rvts5, span.rvts5
{
 font-family: 'Verdana';
 color: #0000ff;
 text-decoration: underline;
}
a.rvts5:hover { color: #0000ff; }
/* ========== Para Styles ========== */
p,ul,ol /* Left */
{
 text-align: left;
 text-indent: 0px;
 padding: 0px 0px 0px 0px;
 margin: 0px 0px 0px 0px;
}
.rvps1
{
}
--></style>
<script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script>
<script type="text/JavaScript" language="JavaScript">
<!-- If this page is displayed outside of the Website Help Frameset, then reload in the Frame set
if (parent.location.href == self.location.href)
{location.href = "index.html?"+extractFileNameWithoutKnownExtension(location.href);}
//--></script>
<script type="text/javascript" language="JavaScript" src="FHNonscroll.js"></script><script type="text/javascript" language="JavaScript" src="FHUtilities.js"></script></HEAD>
<body bgcolor="#FFFFFF" scroll="no"><div id="FHNonScroll"><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td width="100%" align="left">
<font size=2 color="#000000" face="Arial">
<div><font size=5 color="#333333" face="Verdana"><b>Write Text to File</b></font></div>
</font>
</TD><td width="120" align="right" nowrap><font face="Verdana" size="2"><a href="ReplaceTextInFile.html"><img src="Images/BrowseBlueLeft.png" border="0" alt="Previous Topic"></a>&nbsp;&nbsp;<a href="UnzipFile.html"><img src="Images/BrowseBlueRight.png" border="0" alt="Next Topic"></a>&nbsp;</font></td></tr></table></div><div id="FHScroll">

<p class=rvps1><span class=rvts2>This action will write text out to a text file.&nbsp; It can either overwrite a file or append text to an existing file.&nbsp; Any file that does not exist will automatically be created.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Supported Platforms</span></p>
<p class=rvps1><span class=rvts2>All Platforms</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Standard Properties&nbsp; </span></p>
<p class=rvps1><span class=rvts2>See </span><a class=rvts5 href="ActionStandardProperties.html">Standard Action Properties</a><span class=rvts2>.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Advanced Properties</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Add to Uninstall</span></p>
<p class=rvps1><span class=rvts2>If this property is true, any file touched by this action will be added to the list of files to be removed during uninstallation.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Append Newline</span></p>
<p class=rvps1><span class=rvts2>If this property is true, a newline will be output at the end of the text to be written to the file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Encoding</span></p>
<p class=rvps1><span class=rvts2>Specifies the language encoding to use when writing text to the file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>File Open Action</span></p>
<p class=rvps1><span class=rvts2>This tells the action how to open the file for writing.&nbsp; The following choices are available:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Append to file - Append the text to an existing file or create a new one if it doesn't exist.</span></li>
<li class=rvps1><span class=rvts2>Overwrite existing file - Write the text to a new file, overwriting any file that already exists.</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Files</span></p>
<p class=rvps1><span class=rvts2>A list of files separated by a ;.&nbsp; Any file that is a relative path is automatically made relative to &lt;%InstallDir%&gt;.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Line Feed</span></p>
<p class=rvps1><span class=rvts2>The type of linefeeds for the specified files.&nbsp; The following choices are available:</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<ul style="text-indent: 0px; margin-left: 24px; list-style-position: outside;">
<li class=rvps1><span class=rvts2>Auto - choose the linefeeds based on the target install platform.</span></li>
<li class=rvps1><span class=rvts2>Unix - Use UNIX linefeeds (lf)</span></li>
<li class=rvps1><span class=rvts2>Windows - Use Windows linefeeds (crlf)</span></li>
</ul>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts3>Examples</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts2>The following values will write some of our install configuration out to a config.cfg file.</span></p>
<p class=rvps1><span class=rvts2><br></span></p>
<p class=rvps1><span class=rvts4>Files:&nbsp;&nbsp;&nbsp;&nbsp; config.cfg</span></p>
<p class=rvps1><span class=rvts4>Line Feed: Unix</span></p>
<p class=rvps1><span class=rvts4><br></span></p>
<p class=rvps1><span class=rvts4>Text to Write: InstallDir: &lt;%InstallDir%&gt;</span></p>
<p class=rvps1><span class=rvts4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Installer:&nbsp; &lt;%Installer%&gt;</span></p>
<p class=rvps1><span class=rvts4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Username:&nbsp;&nbsp; &lt;%Username%&gt;</span><span class=rvts1></span></p>

</div></body></html>
Added docs/html/index.html.


















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- saved from url=(0014)about:internet -->
<html><head><title></title>
<script language="JavaScript" src="FHTocTab.js"></script>
<script language="JavaScript" src="FHTocParas.js"></script>
<script language="JavaScript" src="FHDisplayToc.js"></script>
<script language="JavaScript">
  var URL = location.href.split("?");
  if(URL[1])
    {
    var IndexPageToLoad = URL[1];
    }
  else
    {
    var IndexPageToLoad = 'Welcome';
    }
</script>
</head>
<frameset rows="50,*" cols="*" frameborder="NO" border="0" framespacing="0" onload="reDisplay(IndexPageToLoad,1,0,0);"> 
  <frame name="topFrame" scrolling="NO" noresize src="FHTop.html">
    <frameset cols="335,*" frameborder="YES" border="1" framespacing="1" rows="*" bordercolor="#003080">
	<frame src="about:blank" name="toc">
	<frame src="Welcome.html" name="content">
    </frameset>
</frameset>
</html>
Added docs/twapi.chm.

cannot compute difference between binary files

Added instaljammer.bat.






>
>
>
1
2
3
$echo off
start C:\PG\github\INSTALLERS\installjammer\Binaries\Windows\installkit.exe C:\PG\github\INSTALLERS\installjammer\installjammer.tcl
exit
Added installjammer.






































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/bin/sh

## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

##
## Set this variable to the string that matches your platform if this script
## cannot find a suitable InstallKit binary.  A list of supported platforms
## can be found in the Binaries/ subdirectory.
##
PLATFORM=""

##
## This script attempts to find an installkit to start InstallJammer.
##

platform() {
    OS=`uname`
    MACHINE=`uname -m`

    case $MACHINE in
        *86)
            MACHINE=x86
            ;;
        *sun*)
            MACHINE=sparc
            ;;
        Power*)
            MACHINE=ppc
            ;;
    esac

    case $OS in
        AIX)
            PLATFORM=AIX-ppc
            ;;
        Darwin)
            PLATFORM="MacOS-X"
            ;;
        FreeBSD)
            VERSION=`uname -r | cut -f 1 -d .`
            PLATFORM=$OS-$VERSION-$MACHINE
            ;;
        HP-UX)
            PLATFORM=HPUX-hppa
            ;;
        IRIX*)
            PLATFORM=IRIX-mips
            ;;
        SunOS)
            PLATFORM=Solaris-$MACHINE
            ;;
        *MINGW*|*CYGWIN*)
            PLATFORM=Windows
            ;;
        *)
            PLATFORM=$OS-$MACHINE
            ;;
    esac
}

if test -z "$PLATFORM"; then
    platform
fi

INSTALLJAMMER_HOME=`dirname "$0"`

INSTALLKIT="$INSTALLJAMMER_HOME/Binaries/$PLATFORM/installkit"

if test ! -f "$INSTALLKIT"; then
    echo
    echo "Could not find an installkit for your platform '$PLATFORM'."
    echo "You must modify this script and define a platform at the top."
    echo
    exit 1
fi

chmod -f +x ${INSTALLKIT}
exec "${INSTALLKIT}" "${INSTALLJAMMER_HOME}/installjammer.tcl" $*
Added installjammer.tcl.
































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

if {[info exists ::installkit::wrapped] && $::installkit::wrapped} {
    set conf(pwd) [file dirname [info nameofexecutable]]
} else {
    set conf(pwd) [file dirname [info script]]
}

set conf(pwd) [file normalize $conf(pwd)]

source [file join $conf(pwd) lib main.tcl]
Added lib/Actions/ConsoleActions/ConsoleAskYesOrNo.action.
















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ConsoleAskYesOrNo

Property Default choice "Default" "None" {No None Yes}

Property Prompt short "Prompt"

Property VirtualText short "Virtual Text" "Answer"

proc ::InstallJammer::actions::ConsoleAskYesOrNo { obj } {
    $obj properties props -subst 1

    set prompt \n$props(Prompt)

    if {$props(Default) eq "" || $props(Default) eq "None"} {
        append prompt { [y/n]}
    } elseif {$props(Default) eq "Yes"} {
        append prompt { [n/Y]}
    } else {
        append prompt { [y/N]}
    }

    append prompt " "

    while {1} {
        puts -nonewline stdout [::InstallJammer::WrapText $prompt]
        flush stdout

        set ans [string trim [string tolower [gets stdin]]]

        puts  stdout ""
        flush stdout

        if {$ans eq "" && $props(Default) ne "None"} {
            set ans $props(Default)
            break
        }

        if {$ans eq "n"} { set ans "no" }
        if {$ans eq "y"} { set ans "yes" }

        if {$ans eq "yes" || $ans eq "no"} { break }
    }

    if {$props(VirtualText) ne ""} {
        set ::info($props(VirtualText)) $ans
    }

    return $ans
}
Added lib/Actions/ConsoleActions/ConsoleClearScreen.action.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ConsoleClearScreen

proc ::InstallJammer::actions::ConsoleClearScreen { obj } {
    system "clear"
    return
}
Added lib/Actions/ConsoleActions/ConsoleGetUserInput.action.


















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ConsoleGetUserInput

Property EchoInput boolean "Echo Input" "Yes"
Help EchoInput "Echo the input as the user types.  If this property is set\
        to no, the input will not be echoed.  This is good for password input."

Property Prompt short "Prompt"
Help Prompt "A string of text to prompt the user for their input"

Property RequireResponse boolean "Require Response" "No"
Help RequireResponse "If this property is true, the user will not be able to\
        enter an empty response.  They must enter something."

Property TrimResult boolean "Trim Result" "Yes"
Help TrimResult "If this property is true, the input from the user will be\
        trimmed of whitespace before being set in the virtual text."

Property VirtualText short "Virtual Text"
Help VirtualText "The virtual text variable (without <% and %>) to store the\
        input into.  If this virtual text has a value when the action\
        executes, that text will be the default response."

proc ::InstallJammer::actions::ConsoleGetUserInput { obj } {
    $obj properties props -subst 1

    fconfigure stdin -buffering line

    set prompt \n$props(Prompt)

    set virtual "<%$props(VirtualText)%>"
    set default [::InstallJammer::SubstText $virtual]
    if {$default ne $virtual} { append prompt " \[$default\]" }

    append prompt " "

    while {1} {
        puts -nonewline stdout [::InstallJammer::WrapText $prompt]
        flush stdout

        if {!$props(EchoInput)} {
            catch { exec stty -echo }
        }

        gets stdin result

        if {!$props(EchoInput)} {
            catch { exec stty echo }
        }

        puts  stdout ""
        flush stdout

        if {$props(RequireResponse) && [string trim $result] eq ""} { continue }
        break
    }

    if {$props(TrimResult)} { set result [string trim $result] }

    if {$default ne $virtual && $result eq ""} {
        set result $default
    }

    if {$result ne ""} {
        set ::info($props(VirtualText)) $result
    }
}
Added lib/Actions/ConsoleActions/ConsoleMessage.action.






















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ConsoleMessage

Property AllowQuit boolean "Allow Quit" "Yes"
Help AllowQuit "Allow the user to quit pagination of the message"

Property PaginateMessage boolean "Paginate Message" "Yes"
Help PaginateMessage "Whether to display the message in pages instead of\
                        all at once (like the more command)"

Property WrapText boolean "Wrap Text" "Yes"
Help WrapText "Whether the text should be wrapped at the width of the console"

Text Message

proc ::InstallJammer::actions::ConsoleMessage { obj } {
    global conf

    $obj properties props
    set message [::InstallJammer::GetText [$obj id] Message]

    if {$props(PaginateMessage)} {
        set command [list ::more -allowquit $props(AllowQuit)]

        if {$props(WrapText)} {
            lappend command -width $conf(ConsoleWidth)
        }
    } else {
        set command [list puts stdout]

        if {$props(WrapText)} {
            set message [::InstallJammer::WrapText $message]
        }
    }

    eval $command [list $message]
}
Added lib/Actions/ConsoleActions/ConsolePause.action.
























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ConsolePause

Text Message

proc ::InstallJammer::actions::ConsolePause { obj } {
    catch { exec stty raw -echo <@stdin }

    catch { 
        puts -nonewline stdout [::InstallJammer::GetText [$obj id] Message]
        flush stdout

        while {1} {
            set x [read stdin 1]
            if {$x eq " "} { break }
        }
    }

    catch { exec stty -raw echo <@stdin }

    return
}
Added lib/Actions/ExecuteActions/ExecuteAction.action.


















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ExecuteAction "Execute Action"

Property "Action" action "Action"
Help Action "The ID of the action you want to execute"

Property EvaluateConditions boolean "Evaluate Conditions" Yes
Help EvaluateConditions "Whether or not to evaluate the conditions of the\
        target action"

proc ::InstallJammer::actions::ExecuteAction { obj } {
    set id [$obj id]

    $obj properties props -subst 1

    if {$props(Action) eq ""} {
        return -code error "Error in Execute Action: Action is empty"
    }

    set eval   $props(EvaluateConditions)
    set action [::InstallJammer::ID $props(Action)]

    if {![::InstallJammer::ObjExists $action]} {
        return -code error "Error in Execute Action:\
                Action \"$action\" does not exist"
    }

    if {![$action is action actiongroup]} {
        return -code error "Error in Execute Action:\
                \"$action\" is not an action or action group"
    }

    if {[$action is action]} {
        ::InstallJammer::ExecuteActions $action -parent $id -conditions $eval
        return
    }

    ## This is an action group.

    set when "Before Action is Executed"
    if {$eval && ![$action checkConditions $when]} {
        debug "Skipping action group $id - [$id title] - conditions failed"
        return
    }

    set when "Before Next Action is Executed"
    while {1} {
        ::InstallJammer::ExecuteActions $action -parent $id -conditions $eval
        if {!$eval || [$action checkConditions $when]} { break }
    }
}
Added lib/Actions/ExecuteActions/ExecuteExternalProgram.action.






































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ExecuteExternalProgram "Execute External Program"

Property ExecuteAsRoot boolean "Execute as Root" "No"
Help ExecuteAsRoot "If true, this program will be executed as the root user\
                        if the user is not already root (UNIX only)"

Property ClearProgressiveWidget boolean "Clear Progressive Widget" "Yes"
Help ClearProgressiveWidget "If this property is true, the progressive\
	widget when showing progressive output will be cleared before the\
	external program is executed"

Property ConsoleTitle short "Console Title" "<%AppName%> Setup"
Help ConsoleTitle "If not null, specifies the title to use for the console\
                        when Execute In Console is true"

Property ExecuteInConsole boolean "Execute In Console" "No"
Help ExecuteInConsole "Whether or not this program should be executed in\
                        a console window"

Property IncludeStderr boolean "Include Stderr" "No"
Help IncludeStderr "Whether output from the stderr channel should be included\
                        along with stdout"

Property ProgramCommandLine text "Program Command Line"
Help ProgramCommandLine "The actual command and arguments to be executed"

Property ProgressiveOutputWidget widget "Progressive Output Widget" ""
Help ProgressiveOutputWidget "A text box widget on the pane to update with\
        the progressive output of the external command"

Property ResultVirtualText short "Result Virtual Text" "ExternalProgramResult"
Help ResultVirtualText "A virtual text variable to hold the result output\
        from the external program"

Property ShowProgressiveOutput boolean "Show Progressive Output" "No"
Help ShowProgressiveOutput "Output will update progressively instead of all\
        at once when the command finishes"

Property StatusVirtualText short "Status Virtual Text" "ExternalProgramStatus"
Help StatusVirtualText "A virtual text variable to hold the exit code from\
        the external program"

Property WatchProgressiveOutput boolean "Watch Progressive Output" "No"
Help WatchProgressiveOutput "If Show Progressive Output is true, this property\
        tells InstallJammer to watch the output for special text to signal\
        changes in InstallJammer's virtual text"

Property WatchRegularExpression short "Watch Regular Expression" \
    {^:([^ ]+) (.*):$}
Help WatchRegularExpression "This defines the regular expression that\
        InstallJammer uses to find special meaning when watching progressive\
        output.\nThe regular expression must have two sub matches.  The first\
        for the virtual text variable and the second for the value.\nIf less\
        than two sub matches are found, the Watch Virtual Text variable will\
        be used to hold the matching data"

Property WatchVirtualText short "Watch Virtual Text" "Status"
Help WatchVirtualText "If the Watch Regular Expression only matches a single\
        sub match or an entire line of text, the Watch Virtual Text variable\
        will be used to hold the match"

Property WaitForProgram boolean "Wait for Program to Finish Running" "Yes"
Help WaitForProgram "Whether or not to proceed with the rest of the install\
        or wait for the external program to finish"

Property WorkingDirectory installedfile "Working Directory"
Help WorkingDirectory "If not null, the install will change to this directory\
                        before executing the command line"


proc ::InstallJammer::actions::ExecuteExternalProgram { obj } {
    global conf
    global info

    set id [$obj id]

    $obj properties props -subst {ConsoleTitle}

    set resultVarName [::InstallJammer::SubstText $props(ResultVirtualText)]
    set statusVarName [::InstallJammer::SubstText $props(StatusVirtualText)]

    set resultVar ::conf(ExternalResult)
    if {[string length $resultVarName]} { set resultVar ::info($resultVarName) }

    set statusVar ::conf(ExternalStatus)
    if {[string length $statusVarName]} { set statusVar ::info($statusVarName) }

    set $statusVar 0
    set $resultVar ""

    ::InstallJammer::UpdateWidgets -update 1

    set workdir [::InstallJammer::SubstText $props(WorkingDirectory)]
    if {$workdir ne "" && [file exists $workdir]} {
        debug "Changing to working directory $workdir"
        set pwd [pwd]
        cd $workdir
    }

    set cmdline $props(ProgramCommandLine)

    if {$props(ShowProgressiveOutput)} {
        debug "Executing with progressive output"

        set proc   ::ReadOutput${id}
        set watch  $props(WatchProgressiveOutput)
        set widget $props(ProgressiveOutputWidget)
        set widget [::InstallAPI::GetWidgetPath -widget $widget]

        if {!$info(GuiMode) || ![winfo exists $widget]
            || [winfo class $widget] ne "Text"} {
            set widget ""
        } else {
            ## We have a valid text widget.  Blank its contents to start.
            if {$props(ClearProgressiveWidget)} { $widget delete 1.0 end }

            ## This is kind of lame, but we need to attach something
            ## to this widget to tell the updater not to overwrite
            ## its data.  We're going to use the -maxundo option of
            ## the text widget since we'll never use it otherwise.
            $widget configure -maxundo 1
        }

        if {$watch} {
            debug "Watching progressive output for special syntax."
        }

        proc ::CloseProgressive { fp statusVar resultVar } {
            unset -nocomplain ::conf(update)
            fconfigure $fp -blocking 1
            if {[catch { close $fp } error]} {
                if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
                    set $statusVar [lindex $::errorCode 2]
                } else {
                    set $statusVar 1
                }

                set $resultVar $error
            } else {
                set $statusVar 0
            }
        }

        proc $proc { fp statusVar resultVar widget watch } {
            set ::conf(update) 0
            if {[llength $watch]} {
                gets $fp data

                if {[fblocked $fp]} { return }

                if {$::conf(windows)} {
                    set data [string map [list \r ""] $data]
                }

                if {[eof $fp]} {
                    CloseProgressive $fp $statusVar $resultVar
                    return
                }

                lassign $watch pattern var
                set matches [regexp -inline -- $pattern $data]
                set len [llength $matches]
                if {$len == 1 || $len == 2} {
                    set val [lindex $matches end]
                } elseif {$len == 3} {
                    set var [lindex $matches 1]
                    set val [lindex $matches 2]
                }

                if {$len && $var ne ""} {
                    ## This is status text output from the program.
                    set ::info($var) [::InstallJammer::SubstText $val]
                    ::InstallJammer::UpdateWidgets
                    return
                }

                append data \n
            } else {
                set data [read $fp]

                if {$::conf(windows)} {
                    set data [string map [list \r ""] $data]
                }

                if {[eof $fp]} {
                    CloseProgressive $fp $statusVar $resultVar
                    return
                }
            }

	    set data [::InstallJammer::SubstText $data]

            append $resultVar $data

            if {$::info(ConsoleMode)} {
                puts -nonewline stdout $data
                flush stdout
            } elseif {$widget ne ""} {
                set auto [expr {[lindex [$widget yview] 1] == 1}]

                $widget configure -state normal
                $widget insert end $data
                $widget configure -state disabled

                ## If the user is all the way at the bottom of the text,
                ## we want to keep auto-scrolling to the bottom. 
                if {$auto} { $widget yview moveto 1.0 }

                update idletasks
            }
        }

        set cmd [::InstallJammer::SubstForPipe $cmdline]

        if {$props(IncludeStderr)} { lappend cmd "2>@1" }

        debug "Executing Command Line: $cmd"

        if {[catch { open "|$cmd" } fp]} {
            set $statusVar 1
            set $resultVar $fp
            if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
                set $statusVar [lindex $::errorCode 2]
            }

            return -code error [set $resultVar]
        } else {
            if {$watch} {
                debug "Watching progressive output for matches"
                set watch [list $props(WatchRegularExpression) \
                                $props(WatchVirtualText)]
            } else {
                set watch ""
            }

            fconfigure $fp -buffering none -blocking 0 -translation lf
            fileevent $fp readable \
                [list $proc $fp $statusVar $resultVar $widget $watch]

            if {$props(WaitForProgram)} { vwait $statusVar }
        }
    } else {
        set cmd [::InstallJammer::SubstForPipe $cmdline]

        if {$props(ExecuteInConsole)} {
            debug "Executing in console"

            if {$conf(windows)} {
                set cmd [linsert $cmd 0 $::env(COMSPEC) /c]
            } else {
                set title Console
                if {$props(ConsoleTitle) ne ""} {
                    set title $props(ConsoleTitle)
                }

                set konsole   0
                set gnometerm 0
                set desktop   [::InstallJammer::GetDesktopEnvironment]

                if {$desktop eq "KDE" && [auto_execok konsole] ne ""} {
                    set konsole 1
                    set term konsole
                } elseif {$desktop eq "Gnome"
                    && [auto_execok gnome-terminal] ne ""} {
                    set gnometerm 1
                    set term gnome-terminal
                } elseif {[info exists ::env(COLORTERM)]} {
                    set term $::env(COLORTERM)
                } elseif {[info exists ::env(TERM)]} {
                    set term $::env(TERM)
                } else {
                    set term xterm
                }

                if {[auto_execok $term] eq ""} {
                    return -code error "Execute External Program failled:\
                                        Cannot execute program in console\
                                        because a suitable terminal program\
                                        could not be found."
                }

                set cmd [join $cmd]
                set tmpfile [::InstallJammer::TmpFile].sh
                set fp [open $tmpfile w 00755]
                puts $fp "#!/bin/sh"
                puts $fp $cmd
                close $fp

                if {$props(ExecuteAsRoot) && !$info(UserIsRoot)} {
                    set sutmpfile [::InstallJammer::TmpFile].sh
                    set fp [open $sutmpfile w 00755]
                    puts $fp "#!/bin/sh"
                    puts $fp "echo [sub "<%PromptForRootText%>"]"
                    puts $fp "su -c '$tmpfile'"
                    close $fp
                    set tmpfile $sutmpfile
                }
                set cmd $tmpfile

                if {$gnometerm} {
                    set cmd [list $term -t $title -e $cmd]
                } else {
                    set cmd [list $term -e $cmd]
                }
            }

            if {!$props(WaitForProgram)} { lappend cmd & }

            debug "Executing Command Line: $cmd"

            if {[catch { eval exec $cmd } $resultVar]} {
                debug "Error while executing: [set $resultVar]"

                set $statusVar 1
                if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
                    set $statusVar [lindex $::errorCode 2]
                }
            }
        } elseif {$props(ExecuteAsRoot) && !$info(UserIsRoot)
                    && !$conf(windows)} {
            debug "Executing as root"
            set cmd [::InstallJammer::SubstForPipe $cmdline]

            if {$props(IncludeStderr)} { lappend cmd "2>@1" }

            debug "Executing Command Line: $cmd"
            ::InstallJammer::ExecAsRoot $cmd -wait $props(WaitForProgram)
        } else {
            if {$props(IncludeStderr)} { lappend cmd "2>@1" }

            if {!$props(WaitForProgram)} { lappend cmd & }

            debug "Executing Command Line: $cmd"
            if {[catch { eval exec $cmd } $resultVar]} {
                debug "Error while executing: [set $resultVar]"

                set $statusVar 1
                if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
                    set $statusVar [lindex $::errorCode 2]
                }
            }
        }
    }

    ::InstallJammer::UpdateWidgets -updateidletasks 1

    if {[info exists pwd]} { cd $pwd }
}
Added lib/Actions/ExecuteActions/ExecuteScript.action.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ExecuteScript "Execute Script"

Property ResultVirtualText short "Result Virtual Text" ScriptResult
Property TclScript code "Tcl Script"

proc ::InstallJammer::actions::ExecuteScript { obj } {
    $obj properties props -subst {ResultVirtualText}

    set varName result
    if {$props(ResultVirtualText) ne ""} {
        set varName ::info($props(ResultVirtualText))
    }

    set script [::InstallJammer::SubstForEval $props(TclScript)]
    if {[uplevel #0 [list catch $script $varName]] == 1} {
        return -code error [set $varName]
    }
}
Added lib/Actions/FileActions/AdjustLineFeeds.action.




































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AdjustLineFeeds

Property Files short "Files"
Help Files "A list of file patterns separated by \; (example: */*.txt\;*/*.sh)"

Property LineFeed choice "Line Feed" "Auto" {Auto Unix Windows}
Help LineFeed "The end-of-line character to use when outputting lines"

proc ::InstallJammer::actions::AdjustLineFeeds { obj } {
    $obj properties props

    set translation auto
    if {$props(LineFeed) eq "Unix"} {
        set translation lf
    } elseif {$props(LineFeed) eq "Windows"} {
        set translation crlf
    }

    foreach file [::InstallJammer::GetFilesForPattern $props(Files) -type f] {
        set contents [read_file $file]

        set fp [open $file w]
        fconfigure $fp -translation $translation
        puts -nonewline $fp $contents
        close $fp
    }
}
Added lib/Actions/FileActions/BackupFile.action.


























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action BackupFile

Property Files short "Files"
Help Files "A list of file patterns separated by \; (example: */*.txt\;*/*.sh)"

Property FileExtension short "File Extension" ".bak%d"
Help FileExtension "The extension to append to each file to be backed up.\
                        %d is substituted with a number"

Property OverwriteFiles boolean "Overwrite Files" "No"
Help OverwriteFiles "If this is true, the action will overwrite a file that\
                        already exists instead of skipping to the next one."

Property RenameFiles boolean "Rename Files" "No"
Help RenameFiles "If this is true, the files to be backed up will be moved\
                        to their new file instead of copied.  This is helpful\
                        if you want the original file out of the way."

Property StartingBackup short "Starting Backup" "1"
Help StartingBackup "The number to start at when backing up files"

proc ::InstallJammer::actions::BackupFile { obj } {
    $obj properties props -subst {
        FileExtension OverwriteFiles RenameFiles StartingBackup
    }

    set ext   $props(FileExtension)
    set force $props(OverwriteFiles)

    foreach file [::InstallJammer::GetFilesForPattern $props(Files)] {
        set i $props(StartingBackup)
        set lastfile ""
        while {1} {
            set newfile $file[format $ext $i]

            if {!$force && $newfile eq $lastfile} {
                return -code error \
                    "Could not backup file '$newfile': file already exists"
            }

            if {$force || ![file exists $newfile]} {
                if {$props(RenameFiles)} {
                    file rename -force $file $newfile
                } else {
                    file copy -force $file $newfile
                }
                break
            }

            set lastfile $newfile
            incr i
        }
    }
}
Added lib/Actions/FileActions/ChangeFileOwnership.action.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ChangeFileOwnership

Property Files short "Files"
Help Files "A list of file patterns separated by \; (example: */*.txt\;*/*.sh)"

Property Owner short "Owner"
Help Owner "The name or user id of the owner to change to"

Property Group short "Group"
Help GrouP "The name or group id of the group to change to"

proc ::InstallJammer::actions::ChangeFileOwnership { obj } {
    global conf

    ## This is a UNIX-only action.  Ignore on Windows.
    if {$conf(windows)} { return }

    $obj properties props -subst {Owner Group}

    set opts [list]
    if {[string length $props(Owner)]} { lappend opts -owner $props(Owner) }
    if {[string length $props(Group)]} { lappend opts -group $props(Group) }

    if {![llength $opts]} { return }

    foreach file [::InstallJammer::GetFilesForPattern $props(Files) -type f] {
        eval file attributes [list $file] $opts
    }
}
Added lib/Actions/FileActions/ChangeFilePermissions.action.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ChangeFilePermissions

Property Files short "Files"
Help Files "A list of file patterns separated by \; (example: */*.txt\;*/*.sh)"

Property Permissions short "Permissions" "0755"
Help Permissions "The UNIX permissions mask (in octal format)"

proc ::InstallJammer::actions::ChangeFilePermissions { obj } {
    global conf

    ## This is a UNIX-only action.  Ignore on Windows.
    if {$conf(windows)} { return }

    $obj properties props

    set perms [format %.5d [string trimleft $props(Permissions) 0]]

    foreach file [::InstallJammer::GetFilesForPattern $props(Files) -type f] {
        file attributes $file -permissions $perms
    }
}
Added lib/Actions/FileActions/CopyFile.action.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action CopyFile

Property Source installedfile "Source"
Help FileName "The name of the source file or directory on the target system"

Property Destination installedfile "Destination"
Help FileName "The name of the destination file or directory on the target\
                system"

proc ::InstallJammer::actions::CopyFile { obj } {
    $obj properties props -subst 1

    set dst [::InstallJammer::RelativeFile $props(Destination)]

    foreach src [::InstallJammer::GetFilesForPattern $props(Source)] {
        file copy -force $src $dst
    }
}
Added lib/Actions/FileActions/CreateFileLink.action.


















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action CreateFileLink

Property AddToUninstall boolean "Add to Uninstall" "Yes"
Help AddToUninstall "If this property is true, the link that is created\
    will be added to the list of files to be uninstalled."

Property LinkName installedfile "Link Name"
Help FileName "The name of the link to create on the target system"

Property LinkType choice "Link Type" "symbolic" {hard symbolic}

Property LinkTarget installedfile "Link Target"
Help FileName "The name of the target file or directory on the target system"

proc ::InstallJammer::actions::CreateFileLink { obj } {
    global conf

    $obj properties props -subst 1

    set link   [::InstallJammer::RelativeFile $props(LinkName)]
    set target [::InstallJammer::RelativeFile $props(LinkTarget)]

    if {$conf(windows)} {
        file link -$props(LinkType) $link $target
    } else {
        if {$props(LinkType) eq "hard"} {
            exec ln $target $link
        } else {
            exec ln -s $target $link
        }
    }

    if {$props(AddToUninstall)} { ::InstallJammer::LogFile $link }
}
Added lib/Actions/FileActions/CreateFolder.action.






























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action CreateFolder "Create Folder"

Property FolderName installedfile "Folder Name"

proc ::InstallJammer::actions::CreateFolder { obj } {
    $obj get FolderName folder
    ::InstallJammer::CreateDir [::InstallJammer::SubstText $folder]
}
Added lib/Actions/FileActions/DeleteFile.action.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action DeleteFile

Property Files short "Files"
Help Files "A list of file patterns separated by \; (example: */*.txt\;*/*.sh)"

proc ::InstallJammer::actions::DeleteFile { obj } {
    $obj properties props

    foreach file [::InstallJammer::GetFilesForPattern $props(Files)] {
        file delete -force $file
    }
}
Added lib/Actions/FileActions/ReadFileIntoVirtualText.action.




































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ReadFileIntoVirtualText

Property Encoding short "Encoding"
Help Encoding "The encoding to read this file in (defaults to system encoding)"

Property File short "File"
Help File "The name of the file to read into the virtual text variable"

Property TrimString boolean "Trim String" "Yes"
Help TrimString "Trim any whitespace from the front and back of the string\
                    before setting it in the virtual text"

Property VirtualText short "Virtual Text"
Help VirtualText "The virtual text variable to store the file in"

proc ::InstallJammer::actions::ReadFileIntoVirtualText { obj } {
    $obj properties props -subst 1
    set file [::InstallJammer::RelativeFile $props(File)]

    set opts {}
    if {$props(Encoding) ne ""} { lappend opts -encoding $props(Encoding) }

    set data [eval [list read_file $file] $opts]

    if {$props(TrimString)} { set data [string trim $data] }
    set ::info($props(VirtualText)) $data
}
Added lib/Actions/FileActions/RenameFile.action.














































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action RenameFile

Property Source installedfile "Source"
Help FileName "The name of the source file or directory on the target system"

Property Destination installedfile "Destination"
Help FileName "The name of the destination file or directory on the target\
                system"

proc ::InstallJammer::actions::RenameFile { obj } {
    $obj properties props -subst 1
    set src [::InstallJammer::RelativeFile $props(Source)]
    set dst [::InstallJammer::RelativeFile $props(Destination)]

    file rename -force $src $dst
}
Added lib/Actions/FileActions/ReplaceTextInFile.action.


























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ReplaceTextInFile

Property Encoding short "Encoding"
Help Encoding "Specifies an encoding to use when writing data to the file"

Property Files short "Files"
Help Files "A list of file patterns separated by \; (example: */*.txt\;*/*.sh)"

Property StringMap stringmap "String Map"
Help StringMap "A map of text translations to make in the target file"

Property LineFeed choice "Line Feed" "Auto" {Auto Unix Windows}
Help LineFeed "The end-of-line character to use when outputting lines"

proc ::InstallJammer::actions::ReplaceTextInFile { obj } {
    $obj properties props

    set translation auto
    if {$props(LineFeed) eq "Unix"} {
        set translation lf
    } elseif {$props(LineFeed) eq "Windows"} {
        set translation crlf
    }

    set map [::InstallJammer::SubstForPipe $props(StringMap)]

    foreach file [::InstallJammer::GetFilesForPattern $props(Files) -type f] {
        set contents [read_file $file]

        set fp [open $file w]
        fconfigure $fp -translation $translation
        if {$props(Encoding) ne ""} {
            fconfigure $fp -encoding $props(Encoding)
        }
        puts -nonewline $fp [string map $map $contents]
        close $fp
    }
}
Added lib/Actions/FileActions/UnzipFile.action.




































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action UnzipFile

Property AddToUninstall boolean "Add to Uninstall" "Yes"
Help AddToUninstall "Added files and directories created to the uninstaller"

Property Destination installedfile "Destination"
Help FileName "The name of the destination directory on the target system"

Property ProgressVirtualText short "Progress Virtual Text" \
                                        "InstallPercentComplete"
Help ProgressVirtualText "The name of a virtual text variable to track the\
                                progress while unzipping."

Property StatusVirtualText short "Status Virtual Text" ""
Help StatusVirtualText "The name of a virtual text variable to update with\
                        the status while unzipping."

Property ZipFile installedfile "Zip File"
Help FileName "The name of the zip file to unzip on the target system"

Text StatusText

proc ::InstallJammer::actions::UnzipFile { obj } {
    global info

    $obj properties props -subst 1

    set zip [::InstallJammer::RelativeFile $props(ZipFile)]
    set dst [::InstallJammer::RelativeFile $props(Destination)]

    set mnt [::InstallJammer::TmpMount]
    set map [list $mnt/ ""]

    zvfs::mount $zip $mnt

    set count    0
    set lastpct  0
    set status   [string length $props(StatusVirtualText)]
    set progress [string length $props(ProgressVirtualText)]

    set virtualtext {}
    if {$status} { lappend virtualtext $props(StatusVirtualText) }
    if {$progress} { lappend virtualtext $props(ProgressVirtualText) }

    set info(Status) "<%UnpackingFilesText%>"
    if {$status} {
        set info($props(StatusVirtualText)) "<%UnpackingFilesText%>"
    }
    
    if {$progress} {
        set info($props(ProgressVirtualText)) 0
    }

    ::InstallJammer::UpdateWidgets -updateidletasks 1

    set files [recursive_glob $mnt *]
    set total [llength $files]

    if {$status} {
        set info($props(StatusVirtualText)) \
            [::InstallJammer::GetText [$obj id] StatusText -subst 0]
    }

    ::InstallAPI::SetUpdateWidgets -widgets \
        [::InstallJammer::FindUpdateWidgets $virtualtext]
    
    foreach file $files {
        set update 0

        set new [file join $dst [string map $map $file]]
        set dir [file dirname $new]
        if {![file exists $dir]} {
            if {$props(AddToUninstall)} {
                ::InstallJammer::CreateDir $dir
            } else {
                file mkdir $dir
            }
        }

        if {$status} {
            set update 1
            set info(FileBeingInstalled) $new
        }

        if {$progress} {
            set pct [expr {([incr count] * 100) / $total}]
            if {$pct != $lastpct} {
                set update  1
                set lastpct $pct
                set info($props(ProgressVirtualText)) $pct
            }
        }

        if {$update} {
            ::InstallJammer::UpdateSelectedWidgets
            update
        }

        file copy -force $file $new

        if {$props(AddToUninstall)} { ::InstallJammer::LogFile $new }
    }

    zvfs::unmount $mnt

    ::InstallAPI::SetUpdateWidgets -widgets {}
}
Added lib/Actions/FileActions/WriteTextToFile.action.




































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action WriteTextToFile

Property AddToUninstall boolean "Add to Uninstall" "No"
Help AddToUninstall "If this property is true, any file appended or\
        written by this action will be added to the list of files to be
        uninstalled."

Property AppendNewline boolean "Append Newline" "Yes"
Help AppendNewline "If this property is true, a newline character will be\
    written out at the end of the text to write"

Property Encoding short "Encoding"
Help Encoding "Specifies an encoding to use when writing data to the file"

Property Files short "Files"
Help Files "A list of file names separated by \;\
                (example: foo.txt\;<%Temp%>/bar.txt)"

Property FileOpenAction choice "File Open Action" "Overwrite existing file" \
    {"Append to file" "Overwrite existing file"}

Property LineFeed choice "Line Feed" "Auto" {Auto Unix Windows}
Help LineFeed "The end-of-line character to use when outputting lines"

Text TextToWrite "Text to Write"

proc ::InstallJammer::actions::WriteTextToFile { obj } {
    global info

    $obj properties props -subst 1

    set mode w
    if {$props(FileOpenAction) eq "Append to file"} { set mode a }

    set translation auto
    if {$props(LineFeed) eq "Unix"} {
        set translation lf
    } elseif {$props(LineFeed) eq "Windows"} {
        set translation crlf
    }

    foreach file [split $props(Files) \;] {
        set file [string trim $file]
        if {[file pathtype $file] eq "relative"} {
            set file [file join $info(InstallDir) $file]
        }

        set dir [file dirname $file]
        if {![file exists $dir]} {
            if {$props(AddToUninstall)} {
                ::InstallJammer::CreateDir $dir
            } else {
                file mkdir $dir
            }
        }

        set data [::InstallJammer::GetText [$obj id] TextToWrite]

        set fp [open $file $mode]
        fconfigure $fp -translation $translation
        if {$props(Encoding) ne ""} {
            fconfigure $fp -encoding $props(Encoding)
        }

        if {$props(AppendNewline)} {
            puts $fp $data
        } else {
            puts -nonewline $fp $data
        }

        close $fp

        if {$props(AddToUninstall)} { ::InstallJammer::LogFile $file }
    }
}
Added lib/Actions/GeneralActions/ContinueInstall.action.
























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ContinueInstall "Continue Install"

proc ::InstallJammer::actions::ContinueInstall { {id ""} } {
    ::InstallJammer::ContinueInstall
}
Added lib/Actions/GeneralActions/Exit.action.




















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action Exit "Exit"

Property ExitCode short "Exit Code" ""
Help ExitCode "This property specifies the exit code that should be used\
    when the application exits.  If it is not specified, a default exit\
    code will be used"

Property ExitType choice "Exit Type" "Cancel" {Cancel Finish}
Help ExitType "Whether the running application should exit with a cancel or\
    finish condition"

proc ::InstallJammer::actions::Exit { obj } {
    $obj properties props -subst 1

    lappend opts -exittype [string tolower $props(ExitType)]
    if {$props(ExitCode) ne ""} { lappend opts -exitcode $props(ExitCode) }

    eval ::InstallAPI::Exit $opts
}
Added lib/Actions/GeneralActions/FetchURL.action.




















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action FetchURL "Fetch URL"

Property ProxyHost short "Proxy Host"
Help ProxyHost "The hostname to use as a proxy server if required"

Property ProxyPort short "Proxy Port"
Help ProxyPort "The port to use on the proxy server if required"

Property SaveTo choice "Save To" "file" {file virtualtext}
Help SaveTo "Whether to save the URL to a file or virtual text"

Property Target installedfile "Target" "<%Temp%>"
Help Target "The name of the file or virtual text to store the URL contents in"

Property Timeout short "Timeout" "10000"
Help Timeout "The amount of time to wait for a connection (in milliseconds)"

Property URL shorttext "URL"
Help URL "The full URL path to fetch"

Property ProgressVirtualText short "Progress Virtual Text"
Help ProgressVirtualText "The name of a virtual text variable to track the\
                        progress of the download"

proc ::InstallJammer::actions::FetchURL { obj } {
    global conf
    global info

    package require http

    $obj properties props -subst 1

    ::http::config -proxyhost $props(ProxyHost) -proxyport $props(ProxyPort)

    set list  [split $props(URL) \;]
    set len   [llength $list]
    set total 0

    if {$props(ProgressVirtualText) ne ""} {
        ::InstallAPI::SetVirtualText \
            -virtualtext $props(ProgressVirtualText) -value 0 -autoupdate 1

        foreach url $list {
            set tok [::http::geturl $url -validate 1]
            upvar #0 $tok state
            incr total $state(totalsize)
            ::http::cleanup $tok
        }

        ::InstallJammer::StartProgress \
            ::info($props(ProgressVirtualText)) $total
    }

    set i 0
    foreach url $list {
        incr i
        set url  [string trim $url]
        set opts [list -blocksize 8192]

        if {[string length $props(Timeout)]} {
            #lappend opts -timeout $props(Timeout)
        }

        if {$props(SaveTo) eq "file" && $props(Target) ne ""} {
            set filename [string trim $props(Target)]

            if {[file isdirectory $filename]} {
                set dirname  $filename
                set filename [file join $dirname [::InstallJammer::uuid].part]
            }

            set fp [open $filename w]
            fconfigure $fp -translation binary

            lappend opts -channel $fp
        }

        if {$total > 0} {
            ::InstallJammer::ResetProgress
            lappend opts -progress ::InstallJammer::UpdateProgress
        }

        if {$len == 1} {
            set info(Status) "<%DownloadingFilesText%>"
        } else {
            set info(Status) "<%DownloadingFilesText%> ($i/$len)"
        }

        if {[catch { eval ::http::geturl [list $url] $opts } token]} {
            if {[info exists fp]} { close $fp }
            if {[info exists filename]} { file delete -force $filename }
            return -code error $token
        }

        upvar #0 $token state

        if {$props(SaveTo) eq "file"} {
            close $fp

            if {[info exists dirname]} {
                set name [file join $dirname [file tail $state(url)]]
                file rename -force $filename $name
                unset dirname filename
            }
        }

        if {$props(SaveTo) eq "virtualtext" && $props(Target) ne ""} {
            set ::info($props(Target)) $state(body)
        }

        ::http::cleanup $token
    }

    if {[info exists var]} { set $var 100 }
}
Added lib/Actions/GeneralActions/GenerateUID.action.














































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action GenerateUID "Generate UID"

Property UIDType     choice "UID Type"     "UUID" {GUID UUID}
Property VirtualText short  "Virtual Text"
Help VirtualText "The virtual text variable to store the resulting UID into"

proc ::InstallJammer::actions::GenerateUID { obj } {
    global info

    $obj get UIDType     type
    $obj get VirtualText varName

    if {[string length $varName]} {
        set info($varName) [::InstallJammer::[string tolower $type]]
    }
}
Added lib/Actions/GeneralActions/LaunchFile.action.
































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action LaunchFile

Require xdg-utils/xdg-open

Property Arguments text "Arguments"
Help Arguments "Any command-line arguments to pass after the file name"

Property FileName text "File Name"
Help FileName "The name of a file or URL to launch"

Property WaitForProgram boolean "Wait for Program to Finish Running" "No"
Help WaitForProgram "Whether or not to proceed with the rest of the install\
        or wait for the external program to finish"

Property WorkingDirectory installedfile "Working Directory"
Help WorkingDirectory "The directory to change to before launching this file"

proc ::InstallJammer::actions::LaunchFile { obj } {
    global conf

    $obj properties props -subst {FileName}

    ::InstallJammer::UpdateWidgets -update 1

    set workdir [::InstallJammer::SubstText $props(WorkingDirectory)]
    if {[string length $workdir] && [file exists $workdir]} {
        set pwd [pwd]
        cd $workdir
    }

    set args [::InstallJammer::SubstForEval $props(Arguments)]

    if {$conf(windows)} {
        if {!$props(WaitForProgram)} {
            set cmd [list $::env(COMSPEC) /c start $props(FileName)]
        } else {
            set cmd [list $::env(COMSPEC) /c start /WAIT $props(FileName)]
        }
        eval lappend cmd $args
    } else {
        set cmd [list xdg-open $props(FileName)]
        eval lappend cmd $args

        if {!$props(WaitForProgram)} { lappend cmd & }
    }

    debug "Executing Command Line: $cmd"
    set result [catch { eval exec $cmd } error]

    ::InstallJammer::UpdateWidgets -updateidletasks 1

    if {[info exists pwd]} { cd $pwd }

    if {$result} {
        return -code error $error
    }
}
Added lib/Actions/GeneralActions/LaunchWebBrowser.action.
























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action LaunchWebBrowser "Launch Web Browser"

Require xdg-utils/xdg-open

Property URL shorttext "URL"

proc ::InstallJammer::actions::LaunchWebBrowser { obj } {
    global conf

    $obj properties props -subst 1

    set url [::InstallAPI::EncodeURL -url $props(URL)]

    debug "Launching web browser with URL $url"

    if {$conf(windows)} {
        installkit::Windows::shellExecute open $url
    } else {
        exec xdg-open $url &
    }
}
Added lib/Actions/GeneralActions/LogDebugMessage.action.




























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action LogDebugMessage

Property Message text "Message"

proc ::InstallJammer::actions::LogDebugMessage { obj } {
    debug [$obj get Message]
}
Added lib/Actions/GeneralActions/MessageBox.action.






























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action MessageBox "Message Box"

Property DefaultButton choice "Default Button" "Ok" \
    {Abort Retry Ignore Ok Cancel No Yes}
Property Icon choice "Icon" "info" {error info question warning}
Property Type choice "Type" "Ok" \
    {Abort/Retry/Ignore Ok Ok/Cancel Retry/Cancel Yes/No Yes/No/Cancel}
Property VirtualText short "Virtual Text Field" "Answer"

Text Title
Text Message

proc ::InstallJammer::actions::MessageBox { obj } {
    global info

    if {!$info(GuiMode)} { return }

    set id [$obj id]

    $obj get Icon icon
    $obj get Type type
    $obj get VirtualText varName
    $obj get DefaultButton default

    set list [split $type /]
    if {[lsearch -exact $list $default] < 0} { set default "" }
    set type    [string tolower [join $list ""]]
    set default [string tolower $default]

    set title   [::InstallJammer::GetText $id Title]
    set message [::InstallJammer::GetText $id Message]

    set args [list -icon $icon -type $type -title $title -message $message]
    lappend args -parent [::InstallJammer::TransientParent]
    if {[string length $default]} { lappend args -default $default }

    set info($varName) [eval ::InstallJammer::MessageBox $args]

    return
}
Added lib/Actions/GeneralActions/MessagePanel.action.
















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action MessagePanel "Message Panel"

Property Image image "Image" "<%Icon%>"
Property Anchor anchor "Anchor" center
Property Width short "Width" 400
Property Height short "Height" 60
Property Timeout short "Timeout" 0
Property GrabFocus boolean "Grab Focus" "Yes"
Property LabelAnchor anchor "Label Anchor" w
Property ImagePadX short "Image Pad X" "2 0"
Property ImagePadY short "Image Pad Y" 0
Property LabelPadX short "Label Pad X" 5
Property LabelPadY short "Label Pad Y" 0

Text Message

proc ::InstallJammer::actions::MessagePanel { obj } {
    global info

    if {!$info(GuiMode)} { return }

    set id [$obj id]

    $id window .[$id name]
    set top [$id window]

    $obj properties props

    toplevel     $top -borderwidth 2 -relief raised
    wm withdraw  $top
    wm resizable $top 0 0
    wm transient $top [::InstallJammer::TransientParent]
    wm geometry  $top $props(Width)x$props(Height)
    wm override  $top 1

    if {$props(GrabFocus)} {
        ::InstallJammer::Grab $top
        bind $top <Destroy> [list ::InstallJammer::Grab release $top]
        bind $top <Destroy> "+::InstallJammer::TransientParent $top 1"
    }

    ::InstallJammer::TransientParent $top
    ::InstallJammer::PlaceWindow $id -width $props(Width) -height $props(Height)

    if {[string length $props(Image)]} {
        label $top.image
        pack  $top.image -side left \
            -padx $props(ImagePadX) -pady $props(ImagePadY)
        ::InstallJammer::SetImage $top.image $id Image
    }

    label $top.message -anchor $props(LabelAnchor)
    pack  $top.message -side left -expand 1 -fill both \
        -padx $props(LabelPadX) -pady $props(LabelPadY)
    ::InstallJammer::SetText $top.message $id Message

    focus $top.message

    wm deiconify $top
    update

    if {$props(Timeout) > 0} {
        after [expr {$props(Timeout) * 1000}] [list destroy $top]
    }
}
Added lib/Actions/GeneralActions/ModifyObject.action.




































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ModifyObject

Property ObjectState choice "Object State" "" {"" Active Inactive}
Help Active "Activate or deactivate the given object"

Property ObjectID short "Object ID"

proc ::InstallJammer::actions::ModifyObject { obj } {
    $obj properties props -subst {ObjectID}

    set id [::InstallJammer::ID $props(ObjectID)]

    if {$id eq ""} {
        return -code error "Error in Modify Object:\
            Object ID is blank"
    }

    if {![::InstallJammer::ObjExists $id]} {
        return -code error "Error in Modify Object:\
            Object \"$id\" does not exist"
    }

    if {$props(ObjectState) ne ""} {
        debug "Setting object $id to $props(ObjectState)"
        $id set Active [string equal $props(ObjectState) Active]
    }
}
Added lib/Actions/GeneralActions/PauseInstall.action.
























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action PauseInstall "Pause Install"

proc ::InstallJammer::actions::PauseInstall { {id ""} } {
    ::InstallJammer::PauseInstall
}
Added lib/Actions/GeneralActions/SetInstallPassword.action.






























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action SetInstallPassword

Property Password short "Password"

proc ::InstallJammer::actions::SetInstallPassword { obj } {
    $obj properties props -subst 1
    ::InstallAPI::SetInstallPassword -password $props(Password)
}
Added lib/Actions/GeneralActions/SetObjectProperty.action.








































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action SetObjectProperty

Property ObjectID short "Object ID"
Help ObjectID "The ID or alias of the object to set this property for"

Property Property short "Property"
Help Property "The name of a property to set on the specified object"

Property SubstituteValue boolean  "Substitute Value" "Yes"
Help SubstituteValue "If this is true, InstallJammer will substitute the\
    value for virtual text before setting property value"

Property Value text "Value"
Help Value "The value to set the property to"

proc ::InstallJammer::actions::SetObjectProperty { obj } {
    $obj properties props -subst {SubstituteValue ObjectID Property}

    set id [::InstallJammer::ID $props(ObjectID)]

    set value $props(Value)
    if {$props(SubstituteValue)} {
        set value [::InstallJammer::SubstText $value]
    }

    if {$id eq ""} {
        return -code error "Error in Set Object Property:\
            Object ID is blank"
    }

    if {$props(Property) eq ""} {
        return -code error "Error in Set Object Property:\
            Property is blank"
    }

    if {![::InstallJammer::ObjExists $id]} {
        return -code error "Error in SetObjectProperty: Object \"$id\" does\
                            not exist"
    }

    debug "Setting $props(Property) property on object $id to $value"

    ::InstallAPI::SetObjectProperty -object $id -property $props(Property) \
        -value $value
}
Added lib/Actions/GeneralActions/SetVirtualText.action.


























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action SetVirtualText "Set Virtual Text"

Property AutoUpdate      nullboolean "Auto Update"      ""
Help AutoUpdate "If Auto Update is true, InstallJammer will automatically\
    update the screen whenever this virtual text is modified"

Property Language        language "Language"         "None"
Help Language "The language catalog to set this virtual text in"

Property SubstituteValue boolean  "Substitute Value" "No"
Help SubstituteValue "If this is true, InstallJammer will substitute the\
    value for other virtual text before setting the new virtual text"

Property Value           text     "Value"            ""
Help Value "The value to set the virtual text variable to"

Property VirtualText     short    "Virtual Text"     ""
Help VirtualText "The name of a virtual text variable (without the <% %>)"

proc ::InstallJammer::actions::SetVirtualText { obj } {
    $obj properties props -subst {SubstituteValue VirtualText}

    set value $props(Value)
    if {$props(SubstituteValue)} {
        set value [::InstallJammer::SubstText $value]
    }

    set args [list -subst 0]
    lappend args -language $props(Language)
    lappend args -virtualtext $props(VirtualText)
    lappend args -value $value

    if {$props(AutoUpdate) ne ""} {
        lappend args -autoupdate $props(AutoUpdate)
    }

    eval ::InstallAPI::SetVirtualText $args
}
Added lib/Actions/GeneralActions/StopInstall.action.
























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action StopInstall "Stop Install"

proc ::InstallJammer::actions::StopInstall { {id ""} } {
    ::InstallJammer::StopInstall
}
Added lib/Actions/GeneralActions/TextWindow.action.


































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action TextWindow "Text Window"

Property Anchor anchor "Anchor" center
Property Font short "Font" ""
Property Width short "Width" 400
Property Height short "Height" 300
Property TextFile installedfile "Text File"
Property TextWrap choice "Text Wrap" "word" {char none word}
Property GrabFocus boolean "Grab Focus" "Yes"
Property WaitOnWindow boolean "Wait on Window" "Yes"

Text Title
Text Caption
Text Message
Text CloseButton "Close Button" 1

proc ::InstallJammer::actions::TextWindow { obj } {
    global info

    if {!$info(GuiMode)} { return }

    set wizard [::InstallJammer::Wizard]

    set id [$obj id]

    $id window .[$id name]
    set top [$id window]

    $obj properties props -subst {Font}

    toplevel     $top
    wm withdraw  $top
    wm title     $top [::InstallJammer::GetText $id Title]
    wm transient $top [::InstallJammer::TransientParent]
    wm geometry  $top $props(Width)x$props(Height)

    grid rowconfigure    $top 1 -weight 1
    grid columnconfigure $top 0 -weight 1

    if {$props(GrabFocus)} {
        ::InstallJammer::Grab $top
        bind $top <Destroy> [list ::InstallJammer::Grab release $top]
    }

    ::InstallJammer::PlaceWindow $id -width $props(Width) -height $props(Height)

    if {[string length [::InstallJammer::GetText $id Caption]]} {
        label $top.caption -anchor w
        grid $top.caption -row 0 -column 0 -padx 5 -pady [list 5 10] -sticky w
        $id widget set Caption -widget $top.caption
    }

    text $top.message -bg #FFFFFF -bd 2 -relief sunken -wrap $props(TextWrap) \
        -yscrollcommand [list $top.vs set] -xscrollcommand [list $top.hs set]

    if {$props(Font) ne ""} {
        $top.message configure -font $props(Font)
    }

    grid $top.message -row 1 -column 0 -padx [list 5 0] -sticky news
    $id widget set Message -widget $top.message

    ttk::scrollbar $top.vs -command [list $top.message yview]
    grid $top.vs -row 1 -column 1 -sticky ns -padx [list 0 5]

    ttk::scrollbar $top.hs -command [list $top.message xview] -orient horizontal
    grid $top.hs -row 2 -column 0 -sticky ew -padx [list 5 0] -pady [list 0 5]

    set width [string length [::InstallJammer::GetText $id CloseButton]]
    if {$width < 12} { set width 12 }

    ttk::button $top.close -width $width -command [list destroy $top]
    grid $top.close -row 3 -column 0 -padx 5 -pady 5 -sticky e -columnspan 2
    $id widget set CloseButton -widget $top.close

    set file [::InstallJammer::SubstText $props(TextFile)]
    if {[file exists $file]} {
        $id set Message,subst 0
        ::InstallJammer::SetVirtualText $info(Language) \
            $id Message [read_file $file]
    }

    ::InstallJammer::UpdateWidgets -step $id -updateidletasks 1

    focus $top.message

    wm deiconify $top

    if {$props(WaitOnWindow)} { tkwait window $top }
}
Added lib/Actions/GeneralActions/Wait.action.




































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action Wait "Wait"

Property WaitTime short "Wait Time (in milliseconds)"
Help WaitTime "The amount of time to wait in milliseconds (1000 = 1 second)"

proc ::InstallJammer::actions::Wait { obj } {
    if {[$obj get WaitTime time] && [string length $time]} {
        update
        after $time
    }
}
Added lib/Actions/InstallActions/AddInstallInfo.action.


































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddInstallInfo

Property Key short "Key"

Property Value short "Value"

proc ::InstallJammer::actions::AddInstallInfo { obj } {
    $obj properties props -subst 1
    ::InstallAPI::AddInstallInfo -key $props(Key) -value $props(Value)
}
Added lib/Actions/InstallActions/AddResponseFileInfo.action.










































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddResponseFileInfo

Property VirtualText short "Virtual Text"
Help VirtualText "A list of virtual text fields, separated by \;, that will\
    be added to a response file when it is saved"

proc ::InstallJammer::actions::AddResponseFileInfo { obj } {
    $obj properties props -subst 1
    set vars ""
    foreach var [split $props(VirtualText) \;] {
        lappend vars [string trim $var]
    }
    ::InstallAPI::ResponseFileAPI -do add -virtualtext $vars
}
Added lib/Actions/InstallActions/AddToUninstall.action.
































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddToUninstall "Add To Uninstall"

Property ComponentName installedfile "Component Name"
Property ComponentType choice "Component Type" "File" \
    {File Directory "Windows Registry Key"}
Property ForcefullyRemoveDirectory boolean "Forcefully Remove Directory"
Property RegistryValue shorttext "Registry Value"

proc ::InstallJammer::actions::AddToUninstall { obj } {
    global conf
    global info

    $obj properties props

    set path [::InstallJammer::SubstText $props(ComponentName)]

    set entry [list]
    switch -- $props(ComponentType) {
	"File"	{
            set entry [list :FILE $path]
	}

	"Directory"	{
            set entry [list :DIR $path]
	    if {$props(ForcefullyRemoveDirectory)} { lappend entry "-force" }
	}

	"Windows Registry Key" {
            set entry [list :REGISTRY $path]
            if {$props(RegistryValue) ne ""} {
                lappend entry "$props(RegistryValue)"
            }
	}
    }

    if {$info(RunningInstaller)} {
        ::InstallJammer::InstallLog $entry
    } elseif {$info(RunningUninstaller)} {
        lappend conf(AddToUninstall) $entry
    }
}
Added lib/Actions/InstallActions/CheckForPreviousInstall.action.
























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action CheckForPreviousInstall "Check for Previous Install"

proc ::InstallJammer::actions::CheckForPreviousInstall { obj } {
    ::InstallJammer::ReadPreviousInstall
}
Added lib/Actions/InstallActions/GetPreviousInstallInfo.action.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action GetPreviousInstallInfo

Property ApplicationID short "Application ID" "<%ApplicatonID%>"

Property InstallID short "Install ID"

Property VirtualTextPrefix short "Virtual Text Prefix" "PreviousInstall"

proc ::InstallJammer::actions::GetPreviousInstallInfo { obj } {
    global info

    $obj properties props -subst 1

    set ids [::InstallAPI::ReadInstallInfo -array a \
        -installid $props(InstallID) -applicationid $props(ApplicationID)]

    set id [lindex $ids end]
    foreach {var val} [array get a $id,*] {
        set var [string range $var [string length $id,] end]
        set info($props(VirtualTextPrefix)$var) $val
    }
}
Added lib/Actions/InstallActions/InstallLogFile.action.














































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action InstallLogFile "Install Log File"

Property LogFileLocation installedfile "Log File Location" \
    "<%InstallDir%>/install.log"

proc ::InstallJammer::actions::InstallLogFile { obj } {
    global info

    $obj get LogFileLocation logfile
    set file [file normalize [::InstallJammer::SubstText $logfile]]

    ## Make sure to add ourselves to the log.
    ::InstallJammer::LogFile $file

    ::InstallJammer::CreateInstallLog $file
}
Added lib/Actions/InstallActions/InstallSelectedFiles.action.






































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action InstallSelectedFiles "Install Selected Files"

Property ShowConsoleProgress boolean "Show Console Progress" "Yes"
Property UpdateFileText boolean "Update File Text" "No"
Property UpdateFilePercentage boolean "Update File Percentage" "No"

proc ::InstallJammer::actions::InstallSelectedFiles { obj } {
    global info
    global conf

    update

    if {[string is true -strict $info(Testing)]} { return }

    set setups [SetupTypes children]

    ## If we have no setup types, we have nothing to do.
    if {![llength $setups]} { return }

    set setuptype [::InstallJammer::FindObjByName $info(InstallType) $setups]

    if {$setuptype eq ""} {
        return -code error "Install Selected Files failed:\
            could not find current Setup Type in list of available Setup Types"
    }

    set conf(stop)  [::InstallJammer::TmpDir .stop]
    set conf(pause) [::InstallJammer::TmpDir .pause]

    set id     [$obj id]
    set parent [$obj parent]

    set conf(InstallID) $parent

    set total 0

    set info(FileBeingInstalled)  ""
    set info(GroupBeingInstalled) ""

    set info(Status) "<%InstallPrepareText%>"

    set groups [list]
    foreach component [$setuptype get Components] {
        if {![$component active]} {
            debug "Skipping component $component - [$component name] -\
                        component is inactive" $component
            continue
        }

        if {[info exists done($component)]} { continue }
        set done($component) 1

        foreach filegroup [$component get FileGroups] {
            if {![$filegroup active]} {
                debug "Skipping file group $filegroup - [$filegroup name] -\
                            filegroup is inactive" $component
                continue
            }

            if {[info exists done($filegroup)]} { continue }
            set done($filegroup) 1

            lappend groups $filegroup

            if {$::verbose} {
                debug "Adding file group [$filegroup name] for installation..."
            }

            foreach file [$filegroup children] {
                if {![$file active]} {
                    debug "Skipping file $file - [$file name] -\
                                file is inactive" $component
                    continue
                }

                if {[info exists done($file)]} { continue }
                set done($file) 1

                set total [expr {wide($total) + [$file size]}]

                if {$::verbose} {
                    debug "Adding file [$file name] for installation..."
                }

                lappend files($filegroup) $file
            }
	}
    }

    if {![llength $groups]} {
        ## We didn't find any groups.  We're done.
        set info(InstallFinished) 1
        return
    }

    set info(TotalSize) $total

    if {$info(InstallHasSolidArchives) && !$info(SolidArchivesExtracted)} {
        ::InstallJammer::UnpackSolidArchives 0
        set info(InstallPercentComplete) 0
        set info(Status) "<%InstallPrepareText%>"
    }

    set conf(InstallLog) [file join $info(InstallDir) install.log]

    set unpackBin    [::installkit::base]
    set unpackInf    [::InstallJammer::BuildUnpackInfo $groups files]
    set unpackScript [::InstallJammer::BuildUnpack]

    set info(Installing)     1
    set info(InstallErrors)  ""
    set info(InstallStarted) 1

    set conf(LastPercent)          0
    set conf(UpdateFileText)       [$obj get UpdateFileText]
    set conf(UpdateFilePercent)    [$obj get UpdateFilePercentage]
    set conf(directoryPermissions) {}
    set conf(ShowConsoleProgress)  [$obj get ShowConsoleProgress]

    if {!$info(GuiMode)} {
        set conf(UpdateFileText)       0
        set conf(UpdateFilePercentage) 0
    }

    if {$conf(UpdateFileText)} {
        set info(Status) "<%FileBeingInstalledText%>"
    } else {
        set info(Status) "<%GroupBeingInstalledText%>"
    }

    if {[threaded]} {
        set tid [installkit::newThread thread::wait]
        thread::errorproc ::InstallJammer::HandleThreadError

        set conf(UnpackThread) $tid
        thread::send $tid [list set ::argv [list $unpackInf]]
        thread::send -async $tid [list source $unpackScript]
    } else {
        set cmd "|[list $unpackBin] [list $unpackScript] -- [list $unpackInf]"
        set conf(UnpackBin) $unpackBin
        set conf(UnpackFp)  [open $cmd]

        fconfigure $conf(UnpackFp) -blocking 0
        fileevent  $conf(UnpackFp) readable \
            [list ::InstallJammer::ReadUnpack $parent]
    }

    vwait ::info(Installing)

    set info(Installing)      0
    set info(InstallFinished) 1

    if {$info(InstallErrors) ne ""} {
        set info(InstallStopped) 1
        if {![$obj get IgnoreErrors]} {
            ::InstallAPI::ErrorMessage -subst 1 -message "<%InstallErrorText%>"
        }
    }

    if {$info(InstallStopped)} { return }

    if {$conf(windows)} {
	## Broadcast a message telling Windows that the environment
	## has changed.  This forces any environment variables
	## changed during installation to be updated in all running
	## Windows applications.
        set conf(UpdateWindowsRegistry) 1
    }

    ## If we saved files for rollback, we need to clean them up now.
    ## If the install was stopped in the middle, we don't want to do
    ## anything.  The cleanup routines will take care of that.
    if {$conf(rollback) && $info(InstallStarted)} {
        set info(Status)  "<%CleanupInstallText%>"

	foreach {dir perms} $conf(directoryPermissions) {
	    ::InstallJammer::SetPermissions $dir $perms
	}

        foreach file $conf(rollbackFiles) {
            set roll [::InstallJammer::RollbackName $file]
            if {[file exists $roll]} { file delete -force $roll }
        }
    }

    set info(FileBeingInstalled)  ""
    set info(GroupBeingInstalled) ""
}
Added lib/Actions/InstallActions/InstallUninstaller.action.
































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action InstallUninstaller "Install Uninstaller"

Property Message shorttext "Message" "<%BuildUninstallText%>"
Property UninstallFilename short "Uninstall Filename" "uninstall<%Ext%>"
Property UninstallDirectory installedfile "Uninstall Directory" "<%InstallDir%>"

proc ::InstallJammer::actions::InstallUninstaller { obj } {
    global info
    global conf

    $obj properties props -subst 1

    set info(Status) [$obj get Message]

    set uninstallBin [file join $props(UninstallDirectory) \
        $props(UninstallFilename)]

    set conf(uninstall)   $uninstallBin
    set info(Uninstaller) $uninstallBin

    if {[file exists $uninstallBin]} {
        ## An uninstaller already exists, so we want to check
        ## and see if there are any logs already stored within
        ## it and save those off for later.

        set tmp [::InstallJammer::TmpDir]
        set dir [::InstallJammer::TmpMount]

        if {![catch { installkit::Mount $uninstallBin $dir } error]} {
            foreach pattern {*.info *.log} {
                foreach file [glob -nocomplain -dir $dir $pattern] {
                    file copy -force $file $tmp
                }
            }

            installkit::Unmount $dir
        }
    }

    ::InstallJammer::CreateDir [file dirname $uninstallBin]

    set arrays {
        info
        ::InstallJammer::Properties
        ::InstallJammer::languagecodes
    }

    cd [::InstallJammer::TmpDir]
    set uninstall uninstall.tcl
    set main uninstallMain.tcl

    set fp [open_text $uninstall w -translation lf -encoding utf-8]
    puts $fp "namespace eval ::InstallAPI {}"
    puts $fp "namespace eval ::InstallJammer {}"

    puts $fp "set conf(version) [list $conf(version)]"

    puts $fp "set info(Uninstaller) [list $info(Uninstaller)]"
    
    foreach array $arrays {
        puts $fp "array set $array [list [array get $array]]"
    }

    set filedata [array get ::InstallJammer::files gui.tcl]
    if {!$conf(windows)} {
        eval lappend filedata [array get ::InstallJammer::files console.tcl]
    }

    puts $fp "array set ::InstallJammer::files [list $filedata]"

    foreach file {common.tcl uninstall.tcl} {
        puts $fp $::InstallJammer::files($file)
    }

    close $fp

    set opts [list -noinstall -o $uninstallBin -w [::installkit::base]]

    if {$conf(windows)} {
        set desc "Uninstall <%AppName%> <%Version%>"
        lappend opts -filedescription [::InstallJammer::SubstText $desc]
    }

    set dirs [glob -nocomplain -type d -tails -dir [file join $conf(vfs) lib] *]
    set rem  [list installkit itcl tcl tk thread tile]
    set dirs [eval lremove [list $dirs] $rem]

    foreach dir $dirs {
        lappend opts -package [file join $conf(vfs) lib $dir]
    }

    lappend opts -catalog [file join $conf(vfs) catalogs messages]

    set fp [open $main w]
    puts $fp {encoding system utf-8}
    puts $fp {source [file join $::installkit::root uninstall.tcl]}
    close $fp

    ## Create the uninstall binary.
    eval ::InstallJammer::Wrap $opts [list $main $uninstall]

    ::InstallJammer::SetPermissions $uninstallBin 00755

    return 1
}
Added lib/Actions/InstallActions/InstallWishBinary.action.


























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action InstallWishBinary "Install WISH Binary"

Property BinaryName installedfile "Binary Name" "<%InstallDir%>/wish<%Ext%>"
Property WindowsIcon windowsicon "Windows Icon"

proc ::InstallJammer::actions::InstallWishBinary { obj } {
    global conf
    global info

    $obj properties props

    set binary [::InstallJammer::SubstText $props(BinaryName)]

    set info(FileBeingInstalled) $binary
    set info(Status) "<%BuildFileText%>"

    set opts [list -noinstall -o $binary -w [::installkit::base]]

    if {$conf(windows)} {
        lappend opts -company "InstallJammer.com"
        lappend opts -fileversion $::tk_patchLevel.0
        lappend opts -filedescription "Installkit WISH Shell"

        if {[string length $props(WindowsIcon)]} {
            set icon [file tail $props(WindowsIcon)]
            file copy -force [file join $::installkit::root support $icon] \
                [::InstallJammer::TmpDir]
            lappend opts -icon [::InstallJammer::TmpDir $icon]
        }
    }

    ::InstallJammer::CreateDir [file dirname $binary]
    eval ::InstallJammer::Wrap $opts

    ::InstallJammer::LogFile        $binary
    ::InstallJammer::SetVersionInfo $binary
    ::InstallJammer::SetPermissions $binary 00755
}
Added lib/Actions/InstallActions/InstallWrappedScript.action.
















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action InstallWrappedScript "Install Wrapped Script"

Property BinaryName installedfile "Binary Name" "<%InstallDir%>/"

Property IncludeTWAPI boolean "Include TWAPI" "No"
Help IncludeTWAPI "If this property is true, InstallJammer will wrap the\
        Tcl Windows API (TWAPI) extension in with the target executable\
        on the Windows platform"

Property Installkit projectfile "Installkit" ""
Help Installkit "If this property is specified, it points to the location\
    of an installkit binary to use as the basis for this wrapped script. \
    The default is to use the current installer that is already running."

Property TclStartupScript projectfile "Tcl Startup Script" "<%InstallDir%>/"

Property WindowsIcon windowsicon "Windows Icon"

Property Company shorttext "Company"
Property FileVersion version "File Version"
Property ProductName shorttext "Product Name"
Property ProductVersion shorttext "Product Version"
Property FileDescription shorttext "File Description"

proc ::InstallJammer::actions::InstallWrappedScript { obj } {
    global conf
    global info

    $obj properties props -subst 1

    set binary $props(BinaryName)
    set script $props(TclStartupScript)
    if {![file exists $script]} { return }

    set info(FileBeingInstalled) $binary
    set info(Status) "<%BuildFileText%>"

    set opts [list -noinstall -o $binary -w [::installkit::base]]
    if {$props(Installkit) ne ""} { lappend opts -w $props(Installkit) }

    if {$conf(windows)} {
        set x {Company FileVersion ProductName ProductVersion FileDescription}
        foreach prop $x {
            if {[string length $props($prop)]} {
                lappend opts -[string tolower $prop] $props($prop)
            }
        }

        if {[string length $props(WindowsIcon)]} {
            set icon [file tail $props(WindowsIcon)]
            file copy -force [file join $::installkit::root support $icon] \
                [::InstallJammer::TmpDir]
            lappend opts -icon [::InstallJammer::TmpDir $icon]
        }

        if {$props(IncludeTWAPI)} {
            set pkgdir [file join $::installkit::root lib twapi]
            if {[file exists $pkgdir]} {
                lappend opts -package $pkgdir

                set tmp [::InstallJammer::TmpDir [file tail $script]]
                set fp  [open $tmp w]
                puts $fp {namespace eval ::starkit {}}
                puts $fp {set ::starkit::topdir $::installkit::root}
                puts $fp {package require twapi}
                puts $fp ""
                puts $fp [read_file $script]
                close $fp

                set script $tmp
            }
        }
    }

    ::InstallJammer::CreateDir [file dirname $binary]
    eval ::InstallJammer::Wrap $opts [list $script]

    ::InstallJammer::LogFile        $binary
    ::InstallJammer::SetVersionInfo $binary
    ::InstallJammer::SetPermissions $binary 00755
}
Added lib/Actions/InstallActions/RemoveFromUninstall.action.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action RemoveFromUninstall

Property ComponentName installedfile "Component Name"
Property ComponentType choice "Component Type" "File" \
    {File Directory}

proc ::InstallJammer::actions::RemoveFromUninstall { obj } {
    global conf
    global info

    $obj properties props

    set path [::InstallJammer::SubstText $props(ComponentName)]
    set string [::InstallJammer::Normalize $path forward]
    lappend conf(RemoveFromUninstall) $string
    return
}
Added lib/Actions/InstallActions/UnpackStoredFile.action.


















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action UnpackStoredFile "Unpack Stored File"

Property AddToUninstall boolean "Add to Uninstall" "Yes"
Help AddToUninstall "Whether this file should be added to the uninstaller"

Property FileID shorttext "File ID"
Property TargetDirectory installedfile "Target Directory" "<%Temp%>"
Property TargetFilename  shorttext "Target Filename"

proc ::InstallJammer::actions::UnpackStoredFile { obj } {
    $obj properties props

    set id [::InstallJammer::SubstText $props(FileID)]
    set id [::InstallJammer::ID $id]

    if {![::InstallJammer::ObjExists $id]} {
        return -code error "Could not find File ID '$id' while unpacking\
                                stored file."
    }

    set dir [::InstallJammer::SubstText $props(TargetDirectory)]

    set filename $props(TargetFilename)
    if {![string length $filename]} { set filename [file tail [$id name]] }

    set file [file join $dir $filename]

    debug "Unpacking $file"

    set dir [file dirname $file]
    if {![file exists $dir]} { ::InstallJammer::CreateDir $dir }

    $id installfile $file 0 0 $props(AddToUninstall)
}
Added lib/Actions/JavaActions/GetJavaProperty.action.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action GetJavaProperty "Get Java Property"

Property Property       short         "Property"
Property PropertyFile   installedfile "Property File"
Property VirtualText    short         "Virtual Text"

proc ::InstallJammer::actions::GetJavaProperty { obj } {
    global info

    $obj properties props -subst 1

    set info($props(VirtualText)) ""

    if {$props(Property) eq "" || $props(VirtualText) eq ""
        || ![file exists $props(PropertyFile)]} { return }

    ::InstallAPI::PropertyFileAPI -do read -file $props(PropertyFile) -array a

    if {[info exists a($props(Property))]} {
        set info($props(VirtualText)) $a($props(Property))
    }
}
Added lib/Actions/JavaActions/LocateJavaRuntime.action.














































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action LocateJavaRuntime "Locate Java Runtime"

Property SearchPath text "Search Path" "Default Search Path\;Prompt User"
Help SearchPath "A list of paths to search separated by ;.
Default Search Path tells InstallJammer to look in the most common places.
Prompt User will ask the user if all else fails."

Property MinimumVersion short "Minimum Version"
Help MinimumVersion "The lowest version of Java that is acceptable"

Property MaximumVersion short "Maximum Version"
Help MinimumVersion "The highest version of Java that is acceptable"

Property RequireJDK boolean "Require JDK" "No"
Help RequireJDK "This property tells InstallJammer to look specifically for\
    an installed JDK and not just a JRE.  This is indicated by the presence\
    of the javac binary."

Text PromptMessage
Text StatusMessage

proc ::InstallJammer::actions::LocateJavaRuntime { obj } {
    global conf
    global info

    $obj properties props -subst 1

    set info(Status) [$obj get StatusMessage]

    set info(JavaFound)        0
    set info(JavaHome)         ""
    set info(JavaVersion)      ""
    set info(JavaVersionMajor) ""
    set info(JavaExecutable)   ""
    set info(JavawExecutable)  ""
    set info(JavacExecutable)  ""

    set id [$obj id]

    set minver $props(MinimumVersion)
    set maxver $props(MaximumVersion)

    if {$minver eq ""} { set minver 0 }
    if {$maxver eq ""} { set maxver 100 }

    set paths [list]
    foreach path [split $props(SearchPath) \;] {
        set path [string trim $path]

        if {$path eq "Default Search Path"} {
            if {[info exists ::env(JAVA_HOME)]} {
                lappend paths $::env(JAVA_HOME)
            }

            if {[info exists ::env(JAVAHOME)]} {
                lappend paths $::env(JAVAHOME)
            }

            if {[info exists ::env(JDK_HOME)]} {
                lappend paths $::env(JDK_HOME)
            }

            if {[info exists ::env(JRE_HOME)]} {
                lappend paths $::env(JRE_HOME)
            }

            if {[info exists ::env(JAVA_ROOT)]} {
                lappend paths $::env(JAVA_ROOT)
            }

            if {[info exists ::env(JAVA_BINDIR)]} {
                lappend paths [file dirname $::env(JAVA_BINDIR)]
            }

            set which [auto_execok java]
            if {[string length $which]} {
                ## Strip the bin/java off.
                lappend paths [file dirname [file dirname $which]]
            }

            if {$conf(windows)} {
                set root {HKEY_LOCAL_MACHINE\Software\JavaSoft}

                set keys {"Java Development Kit" "Java Runtime Environment"}
                foreach key $keys {
                    if {[catch { registry keys $root\\$key } keys]} { continue }
                    foreach subkey [lsort -dict -decreasing $keys] {
                        set ver [lindex [split $subkey _-] 0]
                        set key $root\\$key\\$subkey

                        if {[vercmp $ver $minver] >= 0
                            && ![catch {registry get $key JavaHome} path]} {
                            lappend paths $path
                        }
                    }
                }

                foreach dirname {jdk jre} {
                    set dir [::InstallJammer::WindowsDir PROGRAM_FILES]
                    set dir [file join $dir Java]
                    eval lappend paths [glob -nocomplain -dir $dir $dirname*]
                }
            } else {
                lappend paths \
                    /usr/java/jdk \
                    /usr/lib/java \
                    /usr/lib/jvm \
                    /usr/lib/jvm/jre \
                    /usr/lib/java-1.4.0 \
                    /usr/lib/java-1.4.1 \
                    /usr/lib/java-1.4.2 \
                    /usr/lib/java-1.5.0


                if {[vercmp 1.4.1 $minver] >= 0} {
                    lappend paths /opt/IBMJava2-141
                }

                if {[vercmp 1.4 $minver] >= 0} {
                    lappend paths /opt/IBMJava2-14
                }

                if {[vercmp 1.3.1 $minver] >= 0} {
                    lappend paths /opt/IBMJava2-131
                }

                if {[vercmp 1.3 $minver] >= 0} {
                    lappend paths /opt/IBMJava2-13 /opt/java-1.3
                }

                if {[vercmp 1.2.2 $minver] >= 0} {
                    lappend paths /usr/local/jdk1.2.2 /usr/lib/java/jdk1.2.2
                }

                if {[vercmp 1.2 $minver] >= 0} {
                    lappend paths /usr/jdk1.2
                }
            }
        } else {
            lappend paths $path
        }
    }

    set versions [list]

    foreach path $paths {
        if {[info exists done($path)]} { continue }
        set done($path) 1

        if {$path eq "Prompt User" && $info(GuiMode)} {
            set path [::InstallJammer::ChooseDirectory -message \
                [::InstallJammer::GetText $id PromptMessage]]
            update
            if {![string length $path]} { continue }
        }

        set java [file join $path bin java]
        if {$conf(windows)} { append java .exe }

        set javac [file join $path bin javac]
        if {$conf(windows)} { append javac .exe }

        debug "Looking for $java."

        if {[file exists $java]
            && (!$props(RequireJDK) || [file exists $javac])} {
            debug "Found $java.  Checking -version."
            catch { exec $java -version } output
            if {![string match "java version*" $output]} {
                debug "Bad output from $java."
                continue
            }

            set ver [lindex [lindex [split $output \n] 0] end]
            set mver [lindex [split $ver _-] 0]
            lappend versions $ver
            if {[vercmp $ver $minver] >= 0 && [vercmp $ver $maxver] <= 0} {
                debug "Version $ver matched."
                set found $path
                break
            }
            debug "Version $ver did not match."
        }
    }

    set info(JavaAvailableVersions) [lsort -dict -unique $versions]

    if {[info exists found]} {
        set info(JavaFound)        1
        set info(JavaHome)         [file dirname [file dirname $java]]
        set info(JavaVersion)      $ver
        set info(JavaVersionMajor) [join [lrange [split $mver .] 0 1] .]
        set info(JavaVersionMinor) $mver
        set info(JavaExecutable)   $java
        set info(JavawExecutable)  $java

        set javaw [file join [file dirname $java] javaw]
        if {$conf(windows)} { append javaw .exe }

        if {[file exists $javaw]} {
            set info(JavawExecutable) $javaw
        }

        if {[file exists $javac]} {
            set info(JavacExecutable) $javac
        }
    }
}
Added lib/Actions/ShortcutActions/InstallDesktopShortcut.action.












































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action InstallDesktopShortcut "Install Desktop Shortcut"

Include InstallUNIXShortcut
Include InstallWindowsShortcut

Property Description shorttext "Description"
Help Description "Specifies the description of the shortcut.  This is the\
    tooltip the user will see over the shortcut and is stored in the Comments\
    field of the shortcut properties. (Windows only)"

Property FileName short "File Name" "<%ShortAppName%>-desktop"

Property ShortcutName shorttext "Shortcut Name"
Property ShortcutType choice "Shortcut Type" "Application" {Link Application}
Property TargetFileName installedfile "Target File Name"
Property IconPath installedfile "Icon Path"
Property IconPathIndex shorttext "Icon Path Index" "0"
Property WorkingDirectory installedfile "Working Directory"
Property CommandLineArguments shorttext "Command Line Arguments"
Property AdditionalArguments longtext "Additional Arguments"

Property InstallForAllUsers editboolean "Install for All Users" \
        "<%ProgramFolderAllUsers%>"

Property VendorID short "Vendor ID" "<%ApplicationID%>"

Property WindowState choice "Window State" "normal" \
    {hidden maximized minimized normal}

proc ::InstallJammer::actions::InstallDesktopShortcut { obj } {
    global conf

    set allusers [::InstallJammer::SubstText [$obj get InstallForAllUsers]]

    if {$conf(windows)} {
        $obj set ShortcutDirectory <%DESKTOP%>

        if {[string is true -strict $allusers]} {
            $obj set ShortcutDirectory <%COMMON_DESKTOP%>
        }

        ::InstallJammer::actions::InstallWindowsShortcut $obj
    } else {
        $obj set ShortcutLocation Desktop
        ::InstallJammer::actions::InstallUNIXShortcut $obj
    }
}
Added lib/Actions/ShortcutActions/InstallProgramFolderShortcut.action.




































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action InstallProgramFolderShortcut

Include InstallUNIXShortcut
Include InstallWindowsShortcut

Property AdditionalArguments longtext "Additional Arguments"

Property CommandLineArguments shorttext "Command Line Arguments"

Property Description shorttext "Description"
Help Description "Specifies the description of the shortcut.  This is the\
    tooltip the user will see over the shortcut and is stored in the Comments\
    field of the shortcut properties. (Windows only)"

Property FileName short "File Name" "<%ShortAppName%>-program"

Property IconPath installedfile "Icon Path"
Property IconPathIndex shorttext "Icon Path Index" "0"

Property InstallForAllUsers editboolean "Install for All Users" ""
Help InstallForAllUsers "Whether this shortcut should be created for all\
        users on Windows or just the current user.  If this property is blank,\
        it means to take whatever the current value of <%ProgramFolder%> is"

Property ProgramFolderName short "Program Folder Name" "<%ProgramFolderName%>"

Property ShortcutName shorttext "Shortcut Name"

Property ShortcutType choice "Shortcut Type" "Application" {Link Application}

Property TargetFileName installedfile "Target File Name"

Property VendorID short "Vendor ID" "<%ApplicationID%>"

Property WindowState choice "Window State" "normal" \
    {hidden maximized minimized normal}

Property WorkingDirectory installedfile "Working Directory"

proc ::InstallJammer::actions::InstallProgramFolderShortcut { obj } {
    global conf

    set allusers [::InstallJammer::SubstText [$obj get InstallForAllUsers]]

    if {$conf(windows)} {
        set folder [$obj get ProgramFolderName]

        $obj set ShortcutDirectory "<%PROGRAMS%>/$folder"

        if {[string is true -strict $allusers]} {
            $obj set ShortcutDirectory "<%COMMON_PROGRAMS%>/$folder"
        }

        ::InstallJammer::actions::InstallWindowsShortcut $obj
    } else {
        $obj set ShortcutLocation "Program Folder"
        ::InstallJammer::actions::InstallUNIXShortcut $obj
    }
}
Added lib/Actions/ShortcutActions/InstallUNIXProgramFolder.action.


















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action InstallUNIXProgramFolder "Install UNIX Program Folder"

Require xdg-utils/xdg-desktop-menu

Property AdditionalArguments longtext "Additional Arguments"
Help AdditionalArguments "Any additional arguments are appended as lines\
    directly to the .directory file created by the action.  The lines are\
    appended after the main properties have been added to the file"

Property FolderDirectory installedfile "Folder Directory"
Help FolderDirectory "If this folder is being created in a directory instead\
    of within the Program Folder, the Folder Directory specifies which\
    directory the .directory file should be created in."

Property FolderLocation choice "Folder Location" "Program Folder" \
  {Directory "Program Folder"}
Help FolderLocation "Whether to create the program folder in the standard\
    Program Folder location or in a directory"

Property FolderName short "Folder Name" "<%ProgramFolderName%>"
Help FolderName "The name of the folder to create.  If the folder contains\
    multiple directories in the path, each folder will be created with all\
    of the same properties and arguments"

Property IconPath installedfile "Icon Path"
Help IconPath "The full path to the icon image file to use for this folder"

Property VendorID short "Vendor ID" "<%ApplicationID%>"
Help VendorID "Your Vendor ID will be prefixed to every .directory file\
    created for your folder.  Using a common Vendor ID is a good way to\
    put multiple applications from multiple installers into the same folders\
    during installation."

proc ::InstallJammer::actions::InstallUNIXProgramFolder { obj } {
    global conf
    global info

    if {![string match "Linux*" $info(Platform)]
        && ![string match "FreeBSD*" $info(Platform)]} { return }

    $obj properties props -subst 1

    if {$props(FolderLocation) eq "Directory"
        && ![file exists $props(FolderDirectory)]} {
        ::InstallJammer::CreateDir $props(FolderDirectory)
        ::InstallJammer::LogFile $props(FolderDirectory)
    }

    set files {}
    foreach folder [file split $props(FolderName)] {
        set uuid $props(VendorID)-[join $folder ""]
        set file [::InstallJammer::TmpDir $uuid.directory]

        set fp [open $file w]
        puts $fp {[Desktop Entry]}
        puts $fp "Version=1.0"
        puts $fp "Type=Directory"
        puts $fp "Name=$folder"

        if {$props(IconPath) ne ""}  {
            puts $fp "Icon=$props(IconPath)"
        }

        if {$props(AdditionalArguments) ne ""} {
            puts $fp "$props(AdditionalArguments)"
        }

        close $fp

        lappend files $file
    }

    if {[llength $files]} {
        set uuid $props(VendorID)-dummy.desktop
        set fp [open [::InstallJammer::TmpDir $uuid] w]
        puts $fp {[Desktop Entry]}
        puts $fp "Version=1.0"
        puts $fp "Type=Application"
        puts $fp "NoDisplay=true"
        close $fp

        lappend files [::InstallJammer::TmpDir $uuid]

        set mode user
        if {$info(UserIsRoot)} { set mode system }
        catch {
            eval exec xdg-desktop-menu install --mode $mode --novendor $files
        }

        foreach file $files {
            lappend logfiles [file tail $file]
        }

        ::InstallJammer::InstallLog [list :XDGRESOURCE menu $logfiles $mode]
    }

    set conf(RestartGnomePanel) 1
}
Added lib/Actions/ShortcutActions/InstallUNIXShortcut.action.


































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action InstallUNIXShortcut "Install UNIX Shortcut"

Require xdg-utils/xdg-desktop-icon
Require xdg-utils/xdg-desktop-menu

Property AdditionalArguments longtext "Additional Arguments"
Help AdditionalArguments "If this property is specified, the value of the\
    property is appended directly to the .desktop file that is created on\
    the target system.  This can be used to add extra lines of data to the\
    file if you know the format of a .desktop file."

Property CommandLineArguments short "Command Line Arguments"
Help CommandLineArguments "These arguments are directly appended to the\
    Target File Name to create a command line for the shortcut."

Property FileName short "File Name" ""

Property IconPath installedfile "Icon Path"

Property ProgramFolderName short "Program Folder Name" "<%ProgramFolderName%>"

Property ShortcutDirectory installedfile "Shortcut Directory"

Property ShortcutLocation choice "Shortcut Location" "Directory" \
  {Desktop Directory "Program Folder"}

Property ShortcutName shorttext "Shortcut Name"

Property ShortcutType choice "Shortcut Type" "Application" {Link Application}

Property TargetFileName installedfile "Target File Name"

Property VendorID short "Vendor ID" "<%ApplicationID%>"

proc ::InstallJammer::actions::InstallUNIXShortcut { obj } {
    global conf
    global info

    if {![string match "Linux*" $info(Platform)]
        && ![string match "FreeBSD*" $info(Platform)]} { return }

    $obj properties props -subst 1

    if {$props(ShortcutLocation) eq "Directory"} {
        set file [file join $props(ShortcutDirectory) $props(ShortcutName)]

        if {![file exists $props(ShortcutDirectory)]} {
            ::InstallJammer::CreateDir $props(ShortcutDirectory)
        }

        ::InstallJammer::LogFile $file
    } else {
        if {$props(FileName) eq ""} {
            return -code error "File Name property must not be empty"
        }

        set file [::InstallJammer::TmpDir $props(FileName)]
    }

    if {![string match *.desktop $file]} { append file .desktop }

    set fp [open $file w]

    puts $fp {[Desktop Entry]}
    puts $fp "Version=1.0"
    puts $fp "Type=$props(ShortcutType)"
    puts $fp "Name=$props(ShortcutName)"

    if {$props(TargetFileName) ne ""} {
        if {$props(ShortcutType) eq "Link"} {
            set target $props(TargetFileName)
            if {![regexp {[a-z]+://} $target]} { set target "file://$target" }
            puts $fp "URL=$target"
        } else {
            set target $props(TargetFileName)
            if {[string first " " $target] > -1} { set target \"$target\" }
            if {[info exists props(CommandLineArguments)]} {
                append target " $props(CommandLineArguments)"
            }
            puts $fp "Exec=$target"
        }
    }

    if {$props(IconPath) ne ""}  {
        puts $fp "Icon=$props(IconPath)"
    }

    if {$props(AdditionalArguments) ne ""} {
        puts $fp $props(AdditionalArguments)
    }

    close $fp

    if {$props(ShortcutLocation) eq "Desktop"} {
        catch { exec xdg-desktop-icon install --novendor $file }
        set tail [file tail $file]
        ::InstallJammer::InstallLog [list :XDGRESOURCE desktop $tail]
    } elseif {$props(ShortcutLocation) eq "Program Folder"} {
        set files [list]
        foreach folder [file split $props(ProgramFolderName)] {
            set uuid    $props(VendorID)-[join $folder ""]
            set dirfile [::InstallJammer::TmpDir $uuid.directory]

            if {![file exists $dirfile]} {
                set fp [open $dirfile w]
                puts $fp {[Desktop Entry]}
                puts $fp "Version=1.0"
                puts $fp "Type=Directory"
                puts $fp "Name=$folder"
                close $fp
            }

            lappend files $dirfile
        }

        if {![llength $files]
            && ![regexp {Categories\s*=} $props(AdditionalArguments)]} {
            return -code error "You must specify Program Folder Name or\
                include Categories in the Additional Arguments"
        }

        lappend files $file

        set mode user
        if {$info(UserIsRoot)} { set mode system }
        catch {
            eval exec xdg-desktop-menu install --mode $mode --novendor $files
        }

        foreach file $files {
            lappend logfiles [file tail $file]
        }

        ::InstallJammer::InstallLog [list :XDGRESOURCE menu $logfiles $mode]
    }

    set conf(RestartGnomePanel) 1
}
Added lib/Actions/ShortcutActions/InstallWindowsShortcut.action.
































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action InstallWindowsShortcut "Install Windows Shortcut"

Property CommandLineArguments shorttext "Command Line Arguments"
Property Description shorttext "Description"
Help Description "Specifies the description of the shortcut.  This is the\
    tooltip the user will see over the shortcut and is stored in the Comments\
    field of the shortcut properties."
Property IconPath installedfile "Icon Path"
Property IconPathIndex shorttext "Icon Path Index" "0"
Property ShortcutName shorttext "Shortcut Name"
Property ShortcutDirectory installedfile "Shortcut Directory" \
    "<%ProgramFolder%>"
Property TargetFileName installedfile "Target File Name"
Property WindowState choice "Window State" "normal" \
    {hidden maximized minimized normal}
Property WorkingDirectory installedfile "Working Directory"

proc ::InstallJammer::actions::InstallWindowsShortcut { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set a(path) $props(TargetFileName)
    if {![regexp {[a-zA-Z0-9]+://} $a(path)]} {
        set a(path) [file nativename $a(path)]
    }

    if {$props(WorkingDirectory) ne ""} {
        set a(work) $props(WorkingDirectory)
    }

    if {$props(IconPath) ne ""} {
        set a(icon) $props(IconPath)
        set a(idx) $props(IconPathIndex)
    }

    if {$props(CommandLineArguments) ne ""} {
        set a(args) $props(CommandLineArguments)
    }

    set a(show) $props(WindowState)

    set linkPath [file join $props(ShortcutDirectory) $props(ShortcutName)]
    if {![string match *.lnk $linkPath]} { append linkPath .lnk }

    set dir [file dirname $linkPath]
    if {![file exists $dir]} { ::InstallJammer::CreateDir $dir }

    if {$conf(twapi)} {
        if {$a(path) eq ""} { set a(path) "C:/" }
        set args [list $linkPath -path $a(path) -showcmd $a(show)]
        if {[info exists a(args)]} { lappend args -args $a(args) }
        if {[info exists a(work)]} { lappend args -workdir $a(work) }
        if {$props(Description) ne ""} {
            lappend args -desc $props(Description)
        }
        if {[info exists a(icon)]} {
            lappend args -iconpath $a(icon) -iconindex $a(idx)
        }
        debug "Creating shortcut $linkPath with these options: $args"
        eval twapi::write_shortcut $args
    } else {
        set args [list $linkPath -objectpath $a(path) -showcommand $a(show)]
        if {[info exists a(args)]} { lappend args -arguments $a(args) }
        if {[info exists a(work)]} { lappend args -workingdirectory $a(work) }
        if {[info exists a(icon)]} { lappend args -icon $a(icon) $a(idx) }
        debug "Creating shortcut $linkPath with these options: $args"
        eval ::installkit::Windows::createShortcut $args
    }
    ::InstallJammer::LogFile $linkPath
}
Added lib/Actions/SystemActions/AddDirectoryToPath.action.




































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddDirectoryToPath

Include AddEnvironmentVariable

Property AddToUninstall boolean "Add to Uninstall" "Yes"
Help AddToUninstall "If this is true, the directory will be removed\
        automatically from the path during uninstallation"

Property Directory installedfile "Directory"
Help Directory "A full directory path to add to the PATH on the target system"

Property Level choice "Level" "user" {system user}
Help Level "Whether to add this directory to the system PATH or the PATH just\
                for this user.  The user must be root on UNIX systems to\
                add at the system level"

Property Location choice "Location" "end" {beginning end}
Help Location "Whether to add this directory to the end or the beginning of\
                the PATH"

Property NormalizePaths boolean "Normalize Paths" "Yes"
Help NormalizePaths "Whether or not each path should be normalized before\
                        being added to the specified path"

Property Separator short "Separator" "<%PathSeparator%>"
Help Separator "The path separator to use when adding to the specified path"

Property Variable editchoice "Variable" "PATH" {"CLASSPATH" "PATH"}
Help Variable "The environment path variable to add this directory to"

proc ::InstallJammer::actions::AddDirectoryToPath { obj } {
    global conf

    $obj properties props -subst 1

    set var $props(Variable)
    set sep $props(Separator)

    if {$conf(windows)} {
        set conf(UpdateWindowsRegistry) 1

        set key   "<%REG_[string toupper $props(Level)]_ENV%>"
        set key   [::InstallJammer::SubstText $key]
        set path  [::installkit::Windows::GetKey $key $var]
        set list  [split $path $sep]
        set check [split [string tolower $path] $sep]
    } else {
        set list  {}
        set path  $::env(PATH)
        set check [split $path $sep]
    }

    set added {}
    foreach dir [split $props(Directory) \;] {
        if {$props(NormalizePaths)} {
            set dir [::InstallJammer::Normalize $dir platform]
        }

        set chk $dir
        if {$conf(windows)} { set chk [string tolower $dir] }

        if {[lsearch -exact $check $chk] < 0} {
            lappend added $dir
            lappend check $chk

            if {$props(Location) eq "end"} {
                lappend list $dir
                if {![info exists ::env($var)]} {
                    set ::env($var) $dir
                } else {
                    append ::env($var) "$sep$dir"
                }
            } else {
                set list [linsert $list 0 $dir]
                if {![info exists ::env($var)]} {
                    set ::env($var) $dir
                } else {
                    set ::env($var) "$dir$sep$::env($var)"
                }
            }
        }
    }

    if {[llength $added]} {
        if {$conf(windows)} {
            registry set $key $var [join $list $sep] expand_sz

            if {$props(AddToUninstall)} {
                ::InstallJammer::InstallLog [list :PATH $var \
                    [join $added $sep] $props(Level) $sep]
            }
        } else {
            if {$props(Location) eq "end"} {
                $obj set Value "\$$var$sep[join $list $sep]"
                $obj set CSHValue "`printenv $var`$sep[join $list $sep]"
            } else {
                $obj set Value "[join $list $sep]${sep}\$$var"
                $obj set CSHValue "[join $list $sep]${sep}`printenv $var`"
            }

            set save $::env($var)
            ::InstallJammer::actions::AddEnvironmentVariable $obj
            set ::env($var) $save

        }
    }
}
Added lib/Actions/SystemActions/AddEnvironmentVariable.action.




































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddEnvironmentVariable

Property AddToUninstall boolean "Add to Uninstall" "Yes"
Help AddToUninstall "If this is true, the environment will automatically\
                        be removed during uninstallation"

Property Level choice "Level" "user" {system user}
Help Level "Whether to add this environment variable for all users or just\
                for this user.  The user must be root on UNIX systems to add\
                at the system level"

Property RestoreOnUninstall boolean "Restore on Uninstall" "No"
Help RestoreOnUninstall "If this is true, the environment variable will be\
                            restored to its previous value if it already\
                            existed during installation (valid only on Windows)"

Property Value short "Value"
Help Value "The value to give to the environment variable"

Property Variable short "Variable"
Help Variable "The name of the environment variable to add"

proc ::InstallJammer::actions::AddEnvironmentVariable { obj } {
    global conf
    global info

    $obj properties props -subst 1

    if {$props(Variable) eq ""} {
        return -code error "Error in Add Environment Variable:\
            Variable is empty"
    }

    set val $props(Value)
    set var $props(Variable)

    set ::env($var) $val

    if {$conf(windows)} {
        set conf(UpdateWindowsRegistry) 1

        set lvl $props(Level)
        set key "<%REG_[string toupper $props(Level)]_ENV%>"
        set key [::InstallJammer::SubstText $key]

        if {$props(RestoreOnUninstall)} {
            if {[catch { registry get $key $var } oldval]} {
                ::InstallJammer::InstallLog [list :ENV $var $lvl]
            } else {
                ::InstallJammer::InstallLog [list :ENV $var $lvl $oldval]
            }
        } elseif {$props(AddToUninstall)} {
            ::InstallJammer::InstallLog [list :ENV $var $lvl]
        }

        registry set $key $props(Variable) $props(Value)
    } else {
        set files $conf([string toupper $props(Level) 0]RCFiles)

        set line "\; # ADDED BY INSTALLER -\
                    DO NOT EDIT OR DELETE THIS COMMENT -\
                    $info(ApplicationID) $info(InstallID)"

        set found 0
        foreach file $files {
            if {[file exists $file] && ![catch { open $file a+ } fp]} {
                set found 1

                puts $fp ""

                if {[string match "*csh*" $file]} {
                    if {[$obj get CSHValue cshval]} {
                        puts -nonewline $fp "setenv $var $cshval"
                    } else {
                        puts -nonewline $fp "setenv $var $val"
                    }
                } else {
                    puts -nonewline $fp "$var=$val\;export $var"
                }
                
                puts $fp $line

                close $fp
            }
        }

        if {$found && $props(AddToUninstall)} {
            ::InstallJammer::InstallLog [list :ENV $var $props(Level)]
        }
    }
}
Added lib/Actions/SystemActions/DeleteEnvironmentVariable.action.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action DeleteEnvironmentVariable

Property Level choice "Level" "user" {system user}
Help Level "Whether to remove this variable for all users or just for this user"

Property Variable short "Variable"
Help Variable "The environment variable to delete from the target system"

proc ::InstallJammer::actions::DeleteEnvironmentVariable { obj } {
    global conf

    ## Windows-only for now.  We'll add UNIX support later.
    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    if {$props(Variable) eq ""} {
        return -code error "Error in Delete Environment Variable:\
                Variable is empty"
    }

    if {$conf(windows)} {
        set conf(UpdateWindowsRegistry) 1

        set key  "<%REG_[string toupper $props(Level)]_ENV%>"
        set key  [::InstallJammer::SubstText $key]
        registry delete $key $props(Variable)
    }
}
Added lib/Actions/SystemActions/RebootOrShutdownSystem.action.
























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action RebootOrShutdownSystem "Reboot or Shutdown System"

Property ExecuteAsRoot boolean "Execute as Root" "No"

Property Type choice "Type" "reboot" {reboot shutdown}

proc ::InstallJammer::actions::RebootOrShutdownSystem { obj } {
    global conf

    $obj properties props

    if {$conf(windows)} {
        if {$::tcl_platform(osVersion) < 4.0} {
            ## Windows 98 or ME.
            set cmd [file join [::InstallJammer::WindowsDir SYSTEM32] rundll32]
            lappend cmd shell32.dll,SHExitWindowsEx
            if {$props(Type) eq "reboot"} {
                lappend cmd 2
            } else {
                lappend cmd 1
            }
        } else {
            set cmd [file join [::InstallJammer::WindowsDir SYSTEM32] shutdown]
            if {$props(Type) eq "reboot"} { lappend cmd -r }
        }
    } else {
        set cmd /sbin/shutdown
        if {$props(Type) eq "reboot"} { lappend cmd -r }
        lappend cmd "now"
    }

    if {$props(ExecuteAsRoot) && !$conf(windows) && !$info(UserIsRoot)} {
        ::InstallJammer::ExecAsRoot $cmd -wait 1
    } else {
        eval exec $cmd &
    }
}
Added lib/Actions/SystemActions/RegisterPackage.action.




















































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action RegisterPackage

Property PackageName text "Package Name" "<%PackageName%>"

Property PackageDatabases text "Package Databases" "all"

Property DPKGChangelogFile file "DPKG Changelog File"

Property DPKGControlScript text "DPKG Control Script" {Package: <%Property PackageName%>
Version: <%PackageVersion%>-<%PackageRelease%>
Priority: optional
Architecture: all
Maintainer: <%PackageMaintainer%>
Description: <%PackageSummary%>
<%FormatDescription <%PackageDescription%>%>}

Property DPKGCopyrightFile file "DPKG Copyright File"

Property DPKGDebianChangelogFile file "DPKG Debian Changelog File"

Property DPKGPreInstallScript text "DPKG Pre Install Script"

Property DPKGPreUninstallScript text "DPKG Pre Uninstall Script" {#!/bin/sh
set -e
# Automatically added by dh_installdocs
if [ \( "$1" = "upgrade" -o "$1" = "remove" \) -a -L /usr/doc/parted ]; then
  rm -f /usr/doc/parted
fi
# End automatically added section}

Property DPKGPostInstallScript text "DPKG Post Install Script" {#!/bin/sh
set -e
# Automatically added by dh_installdocs
if [ "$1" = "configure" ]; then
  if [ -d /usr/doc -a ! -e /usr/doc/parted -a -d /usr/share/doc/parted ]; then
    ln -sf ../share/doc/parted /usr/doc/parted
  fi
fi
# End automatically added section}

Property DPKGPostUninstallScript text "DPKG Post Uninstall Script" {#!/bin/sh
## Exit if we're being run from another install.
if test -f /tmp/.installjammer.dpkg.<%Property PackageName%>; then
  exit
fi

if test -f "<%Uninstaller%>"; then
  <%Uninstaller%>
fi}

Property RPMSpecScript text "RPM Spec Script" {Name: <%Property PackageName%>
Version: <%PackageVersion%>
Release: <%PackageRelease%>
Group: Applications
Summary: <%PackageSummary%>
License: <%PackageLicense%>
Packager: <%PackagePackager%>

%description
<%PackageDescription%>

%postun
if test -f "<%Uninstaller%>"; then
  ## Tell InstallJammer that we're removing this package.
  touch /tmp/.installjammer.rpm.<%Property PackageName%>
  <%Uninstaller%>
  rm -f /tmp/.installjammer.rpm.<%Property PackageName%>
fi

%files}

proc ::InstallJammer::actions::RegisterPackage { obj } {
    global info

    $obj properties props -subst 1

    set package   $props(PackageName)
    set databases [string trim [string tolower $props(PackageDatabases)]]

    if {$databases eq "all"} {
        set databases [list dpkg rpm]
    } else {
        set databases {}
        foreach db [split $props(PackageDatabases) \;] {
            lappend databases [string trim [string tolower $db]]
        }
    }

    if {[lsearch -exact $databases "rpm"] > -1} {
        set rpmbuild [auto_execok rpmbuild]

        if {$rpmbuild ne ""} {
            set info(Status) "Registering package with RPM database..."

            set dir [::InstallJammer::TmpDir]

            set specfile [::InstallJammer::TmpDir tmp.spec]

            set fp [open $specfile w]
            puts  $fp $props(RPMSpecScript)
            close $fp

            catch { exec $rpmbuild --define "_rpmdir $dir" \
                        --define "_rpmfilename tmp.rpm" --bb $specfile } result

            if {![regexp {Wrote: (.+rpm)} $result -> rpm]} {
                return -code error "Failed to build RPM: $result"
            }

            set cmd [list rpm -i $rpm]

            if {!$info(UserIsRoot)} {
                ::InstallJammer::ExecAsRoot $cmd -wait 1
            } else {
                eval exec $cmd
            }

            ::InstallJammer::InstallLog [list :RPM $package]
        }
    }

    if {[lsearch -exact $databases "dpkg"] > -1} {
        set dpkg [auto_execok dpkg]

        if {$dpkg ne ""} {
            array set files {
                DPKGChangelogFile       changelog.gz
                DPKGCopyrightFile       copyright.gz
                DPKGDebianChangelogFile changelog.Debian.gz
            }

            array set scripts {
                DPKGPreInstallScript    preinst
                DPKGPreUninstallScript  postinst
                DPKGPostInstallScript   prerm
                DPKGPostUninstallScript postrm
            }

            set info(Status) "Registering package with DPKG database..."

            set dir [InstallJammer::TmpDir dpkg]
            file mkdir $dir

            set doc [file join $dir usr share doc $package]
            file mkdir $doc
            
            foreach x [array names files] {
                set file [file join $doc $files($x)]
                if {[file exists $props($x)]} {
                    if {![string match "*.gz" $props($x)]} {
                        miniarc::gzip $props($x) $file
                    } else {
                        file copy -force $props($x) $file
                    }
                } else {
                    close [open $file w]
                }
            }

            set control [file join $dir DEBIAN]
            file mkdir $control

            foreach x [array names scripts] {
                if {$props($x) ne ""} {
                    set file [file join $control $scripts($x)]
                    set fp [open $file w 0755]
                    puts $fp $props($x)
                    close $fp
                }
            }

            set controlfile [file join $control control]

            set fp [open $controlfile w]
            puts  $fp $props(DPKGControlScript)
            close $fp

            set debfile    [::InstallJammer::TmpDir dpkg.deb]
            set scriptfile [::InstallJammer::TmpDir install-debian-package]
            set fp [open $scriptfile w 0777]

            puts $fp "#!/bin/sh"
            puts $fp ""
            puts $fp "chown -R root.root $dir"
            puts $fp ""
            puts $fp "dpkg --build $dir"
            puts $fp ""
            puts $fp "if test -f $debfile\; then"
            puts $fp "    dpkg -i $debfile"
            puts $fp "fi"
            puts $fp ""
            puts $fp "rm -rf $dir $debfile"

            close $fp

            close [open /tmp/.installjammer.dpkg.$package w]

            catch { 
                if {!$info(UserIsRoot)} {
                    ::InstallJammer::ExecAsRoot [list $scriptfile] -wait 1
                } else {
                    exec $scriptfile
                }
            }

            file delete -force /tmp/.installjammer.dpkg.$package

            ::InstallJammer::InstallLog [list :DPKG $package]
        }
    }
}
Added lib/Actions/SystemActions/RemoveDirectoryFromPath.action.


























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action RemoveDirectoryFromPath

Property Directory installedfile "Directory"
Help Directory "A full directory path to remove from the PATH on the\
                target system"

Property Level choice "Level" "user" {system user}
Help Level "Whether to remove this directory from the system PATH or the PATH\
                just for this user"

Property Separator short "Separator" "<%PathSeparator%>"
Help Separator "The path separator to use when removing from the specified path"

Property Variable editchoice "Variable" "PATH" {"CLASSPATH" "PATH"}

proc ::InstallJammer::actions::RemoveDirectoryFromPath { obj } {
    global conf

    ## Windows-only for now.  We'll add UNIX support later.
    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set dir $props(Directory)
    set sep $props(Separator)

    if {$conf(windows)} {
        set key   "<%REG_[string toupper $props(Level)]_ENV%>"
        set key   [::InstallJammer::SubstText $key]
        set path  [::installkit::Windows::GetKey $key $props(Variable)]
        set list  [split $path $sep]
        set lower [string tolower $list]

        set indexes {}
        foreach dir [split $props(Directory) \;] {
            set dir [::InstallJammer::Normalize $dir windows]
            set chk [string tolower $dir]

            eval lappend indexes [lsearch -exact -all $lower $chk]
        }

        if {[llength $indexes]} {
            foreach x [lsort -integer -decreasing $indexes] {
                set list [lreplace $list $x $x]
            }

            set path [join $list $sep]

            registry set $key $props(Variable) $path expand_sz

            set conf(UpdateWindowsRegistry) 1
        }
    }
}
Added lib/Actions/UninstallActions/UninstallLeftoverFiles.action.


























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action UninstallLeftoverFiles "Uninstall Leftover Files"

proc ::InstallJammer::actions::UninstallLeftoverFiles { obj } {
    $obj set ShowConsoleProgress No
    ::InstallJammer::actions::UninstallSelectedFiles $obj 1
}
Added lib/Actions/UninstallActions/UninstallSelectedFiles.action.






























































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action UninstallSelectedFiles "Uninstall Selected Files"

Property ShowConsoleProgress boolean "Show Console Progress" "Yes"

proc ::InstallJammer::actions::UninstallSelectedFiles {obj {forceUninstall 0}} {
    global conf
    global info

    if {[string is true -strict $info(Testing)]} { return }

    set id     [$obj id]
    set parent [$obj parent]

    set info(Errors)                ""
    set info(ErrorDirs)             ""
    set info(ErrorFiles)            ""
    set info(FileBeingUninstalled)  ""
    set info(GroupBeingUninstalled) ""
    set info(Status)                ""

    set conf(ShowConsoleProgress) [$obj get ShowConsoleProgress]

    ::InstallAPI::SetUpdateWidgets -widgets \
        [::InstallJammer::FindUpdateWidgets {Status FileBeingUninstalled \
                GroupBeingUninstalled UninstallPercentComplete}]

    if {!$forceUninstall} {
        set info(Status) "<%UninstallPrepareText%>"

        ::InstallJammer::GetUninstallInfo

	upvar #0 ::uninstall array

        if {[info exists conf(AddToUninstall)]} {
            foreach line $conf(AddToUninstall) {
                lappend array([lindex $line 0]) [lrange $line 1 end]
            }
        }
    } else {
	upvar #0 ::leftovers array
    }

    foreach x {:DIR :FILE :REGISTRY} {
        if {![info exists array($x)]} { set array($x) {} }
    }

    set dirLen  [llength $array(:DIR)]
    set fileLen [llength $array(:FILE)]
    set regLen  [llength $array(:REGISTRY)]
    set conf(total) [expr $fileLen + $dirLen + $regLen]

    set checkRemove 0
    if {[info exists conf(RemoveFromUninstall)]} {
        set checkRemove 1
        set pattern [join $conf(RemoveFromUninstall) |]
    }

    if {$fileLen} {
        set info(GroupBeingUninstalled) "<%String.files%>"
        set info(Status) "<%FileBeingUninstalledText%>"

        for {set i [expr $fileLen -1]} {$i >= 0} {incr i -1} {
            set list [lindex $array(:FILE) $i]
            set file [lindex $list 0]
            set tail [file tail $file]

            if {![file exists $file]} { continue }
            if {[file type $file] eq "directory"} { continue }

            set info(FileBeingUninstalled) $tail
            ::InstallJammer::UpdateUninstallProgress

            if {$checkRemove && [regexp $pattern $file]} {
                if {$::verbose} {
                    debug "$file removed from uninstall by action."
                }
                continue
            }

            if {$::verbose} {
                debug "Uninstalling file $file."
            }

            if {[catch {::InstallJammer::UninstallFile $file} error]} {
                debug "Failed to delete $file."
                lappend ::leftovers(:FILE) $list
                append info(Errors) "$error\n"
                lappend info(ErrorFiles) $file
            }
        }
    }

    ## If we successfully removed all of the files, we want to
    ## go ahead and delete our uninstaller now before the
    ## directories start being deleted, or we'll end up thinking
    ## a directory is not empty.
    if {$info(Errors) eq ""} {
        set conf(UninstallRemoved) 1
        set tmpuninstall [::InstallJammer::TmpDir uninstall$info(Ext)]
        catch {file rename -force $conf(uninstall) $tmpuninstall}
        set conf(UninstallRenamed) [expr {![file exists $conf(uninstall)]}]
        if {$conf(UninstallRenamed)} { set conf(uninstall) $tmpuninstall }
    }

    if {$dirLen} {
        set notEmptyDirs ""
        set info(GroupBeingUninstalled) "<%String.directories%>"
        ::InstallJammer::UpdateWidgets -update 1

        set p $::tcl_platform(platform)
        set installdir [::InstallJammer::Normalize $info(InstallDir)]
        foreach list [lsort -index 0 -decreasing $array(:DIR)] {
            lassign $list dir force

            if {![file exists $dir]} { continue }
            if {[file type $dir] ne "directory"} { continue }

            if {$checkRemove && [regexp $pattern $dir]} {
                if {$::verbose} {
                    debug "$dir removed from uninstall by action."
                }
                continue
            }

            set forceDelete $forceUninstall
            if {$force ne ""} { set forceDelete 1 }
            if {$forceDelete} { set force -force }

            set info(FileBeingUninstalled) [file tail $dir]
            ::InstallJammer::UpdateUninstallProgress

            if {!$forceDelete && ![::InstallJammer::DirIsEmpty $dir]} {
                ## Make a special case for directories named after
                ## the Company.  This is a common thing on Windows,
                ## and we don't want to blow away the whole company
                ## directory even if our program was the one who
                ## installed it.
                if {[lindex [file split $dir] end] eq $info(Company)} {
                    set conf(cleanupCompanyDir) $dir
                } else {
                    lappend ::leftovers(:DIR) $list
                    lappend info(ErrorDirs) [file normalize $dir]
                    lappend notEmptyDirs [file normalize $dir]
                }

                debug "Skipping non-empty directory $dir."

                continue
            }

            if {$::verbose} {
                if {$forceDelete} {
                    debug "Forcefully deleting directory $dir."
                } else {
                    debug "Deleting directory $dir."
                }
            }

            if {[catch {::InstallJammer::UninstallDirectory $dir $force} err]} {
                debug "Failed to delete directory $dir."
                append info(Errors) "$err\n"
                lappend info(ErrorDirs) [file normalize $dir]
            }
        }

        ## Look through our list of non-empty directories and see if one
        ## is a result of our uninstaller not being renamed out of the way.
        ## If so, we don't actually want to report that directory as having
        ## failed since our exit cleanup script should take care of it.
        set uninstallDir [file normalize [file dirname $conf(uninstall)]]
        foreach dir $notEmptyDirs {
            if {!$conf(UninstallRenamed) && $dir eq $uninstallDir} {
                ## If this is the directory the uninstaller was in, and it
                ## only has a single file remaining, it's our uninstaller,
                ## so we don't want to report it as an error.
                set files [glob -nocomplain -dir $dir *]
                eval lappend files [glob -nocomplain -dir $dir -type hidden *]
                if {[llength $files] == 1} { continue }
            }
            set info(Dir) [::InstallJammer::Normalize $dir $p]
            append info(Errors) [sub "<%DirectoryNotEmptyText%>"]
        }
    }

    if {[info exists array(:ENV)]} {
        set info(GroupBeingUninstalled) "<%String.environment.variables%>"
        ::InstallJammer::UpdateWidgets -update 1

        if {$conf(windows)} {
            foreach list [lreverse $array(:ENV)] {
                set conf(UpdateWindowsRegistry) 1

                lassign $list var level
                set key "<%REG_[string toupper $level]_ENV%>"
                set key [::InstallJammer::SubstText $key]

                if {[llength $list] == 3} {
                    set value [lindex $list 2]
		    debug "Restoring environment variable $var to $value"
                    catch { registry set $key $var $value expand_sz }
                } else {
		    debug "Deleting environment variable $var."
                    catch { registry delete $key $var }
                }
            }
        } else {
            set ids $conf(UninstallIDs)

            foreach list $array(:ENV) {
                lappend vars   [lindex $list 0]
                lappend levels [lindex $list 1]
            }

	    set    pat {; # ADDED BY INSTALLER - DO NOT EDIT OR DELETE}
	    append pat { THIS COMMENT - ([A-Z0-9-]+) ([A-Z0-9-]+)}

            foreach level [lsort -unique $levels] {
                set files $conf([string toupper $level 0]RCFiles)

                foreach file $files {
                    if {![file exists $file]} { continue }
                    if {[catch { read_file $file } contents]} { continue }

                    if {[string match "*csh*" $file]} {
                        set varpat {^setenv ([^ ]+)}
                    } else {
                        set varpat {^(.*)=}
                    }

                    set lines {}
                    foreach line [split $contents \n] {
                        if {[regexp $pat $line -> appid instid]
                            && [lsearch -exact $ids $instid] > -1
                            && [regexp $varpat $line -> var]
                            && [lsearch -exact $vars $var] > -1} { continue }

                        ## If the line before the one we just found
                        ## is a blank, go ahead and remove it too.
                        if {[lindex $lines end] eq ""} {
                            set lines [lreplace $lines end end]
                        }
                        lappend lines $line
                    }

                    if {![catch { open $file w } fp]} {
                        puts  $fp [join $lines \n]
                        close $fp
                    }
                }
            }
        }
    }

    if {[info exists array(:PATH)]} {
        ## Paths are specific to Windows.  On UNIX they are treated
        ## as normal environment variables.
        set info(GroupBeingUninstalled) "<%String.environment.variables%>"
        ::InstallJammer::UpdateWidgets -update 1

        foreach list [lreverse $array(:PATH)] {
            set conf(UpdateWindowsRegistry) 1

            lassign $list var dirs level sep
            if {$sep eq ""} { set sep \; }

            set key   "<%REG_[string toupper $level]_ENV%>"
            set key   [::InstallJammer::SubstText $key]
            set path  [::installkit::Windows::GetKey $key $var]
            set list  [split $path $sep]
            set lower [split [string tolower $path] $sep]

            set indexes {}
            foreach dir [split $dirs $sep] {
                set dir [::InstallJammer::Normalize $dir windows]
                set chk [string tolower $dir]

                eval lappend indexes [lsearch -exact -all $lower $chk]
            }

            if {[llength $indexes]} {
                foreach x [lsort -integer -decreasing $indexes] {
                    set list [lreplace $list $x $x]
                }

                set path [join $list $sep]

                registry set $key $var $path expand_sz
            }
        }
    }

    if {$conf(windows)} {
        if {$regLen} {
            set info(GroupBeingUninstalled) "<%String.registry.entries%>"
            ::InstallJammer::UpdateWidgets -update 1

            set command ::InstallJammer::UninstallRegistryKey
            for {set i [expr $regLen -1]} {$i >= 0} {incr i -1} {
                set list [lindex $array(:REGISTRY) $i]
                lassign $list key value
                ::InstallJammer::UpdateUninstallProgress

                if {[catch {eval $command $list} error]} {
                    lappend ::leftovers(:REGISTRY) $list
                    append info(Errors) "Could not remove $list: $error\n"
                }
            }
        }
    } elseif {[info exists array(:XDGRESOURCE)]} {
        set info(GroupBeingUninstalled) "<%String.shortcuts%>"
        ::InstallJammer::UpdateWidgets -update 1

        foreach list [lreverse $array(:XDGRESOURCE)] {
            set which [lindex $list 0]
            set files [lindex $list 1]
            set mode  [lindex $list 2]
            if {$mode eq ""} { set mode "user" }
            if {$which eq "desktop"} {
                catch { eval exec xdg-desktop-icon uninstall --novendor $files }
            } elseif {$which eq "menu"} {
                set dirfiles  [list]
                set deskfiles [list]
                foreach file $files {
                    if {[string match "*.directory" $file]} {
                        lappend dirfiles $file
                    } else {
                        lappend deskfiles $file
                    }
                }

                lappend menuUninstall($mode,$dirfiles) $deskfiles
            }
        }

        foreach {dirfiles deskfiles} [array get menuUninstall] {
            set list     [split $dirfiles ,]
            set mode     [lindex $list 0]
            set dirfiles [join [lrange $list 1 end] ,]
            set files    [concat $dirfiles $deskfiles]
            catch { eval exec xdg-desktop-menu uninstall \
                --novendor --mode $mode $files } res
        }
    }

    set script [::InstallJammer::TmpDir install-cleanup]

    set fp [open $script w 0755]
    puts $fp "#!/bin/sh\n"

    if {[info exists array(:RPM)]} {
        foreach list [lreverse $array(:RPM)] {
            set db RPM
            set package [lindex $list 0]
            if {![file exists /tmp/.installjammer.rpm.$package]} {
                puts $fp "rpm -e $package"
            }
        }
    }

    if {[info exists array(:DPKG)]} {
        foreach list [lreverse $array(:DPKG)] {
            set db DPKG
            set package [lindex $list 0]
            puts $fp "dpkg -P $package"
        }
    }

    close $fp

    if {[info exists db]} {
        set info(FileBeingUninstalled)  "$db <%String.database.entries%>"
        set info(GroupBeingUninstalled) "<%String.package.entries%>"
        ::InstallJammer::UpdateWidgets -update 1

        if {!$info(UserIsRoot)} {
            ::InstallJammer::ExecAsRoot [list $script] -wait 1
        } else {
            catch { exec $script } error
        }
    }

    set conf(RestartGnomePanel) 1

    ## Cleanup the install registry.
    ::InstallJammer::CleanupInstallInfoDirs

    set info(ErrorsOccurred) [expr {[string length $info(Errors)] > 0}]

    ::InstallAPI::SetUpdateWidgets -widgets {}

    return 1
}
Added lib/Actions/WindowsActions/DisableWow64Redirection.action.






























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action DisableWow64Redirection

proc ::InstallJammer::actions::DisableWow64Redirection { obj } {
    global conf
    if {!$conf(windows)} { return }
    set conf(Wow64Disabled) 1
    ::installkit::Windows::disableWow64FsRedirection
}
Added lib/Actions/WindowsActions/RevertWow64Redirection.action.






























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action RevertWow64Redirection

proc ::InstallJammer::actions::RevertWow64Redirection { obj } {
    global conf
    if {!$conf(windows)} { return }
    set conf(Wow64Disabled) 0
    ::installkit::Windows::revertWow64FsRedirection
}
Added lib/Actions/WindowsRegistryActions/AddWindowsFileCommand.action.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddWindowsFileCommand "Add Windows File Command"

Property FileType shorttext "File Type"
Property CommandName shorttext "Command Name"
Property MenuName shorttext "Menu Name"
Property Command installedfile "Command"

proc ::InstallJammer::actions::AddWindowsFileCommand { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set key [::installkit::Windows::FileType command \
        $props(FileType) $props(CommandName) $props(Command)]
    ::InstallJammer::LogRegistry $key

    if {$props(MenuName) ne ""} {
	set key [::installkit::Windows::FileType menu \
            $props(FileType) $props(CommandName) $props(MenuName)]
        ::InstallJammer::LogRegistry $key
    }
}
Added lib/Actions/WindowsRegistryActions/AddWindowsFileExtension.action.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddWindowsFileExtension "Add Windows File Extension"

Property FileType shorttext "File Type"
Property FileExtension shorttext "File Extension"

proc ::InstallJammer::actions::AddWindowsFileExtension { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    ::installkit::Windows::FileExtension set \
        $props(FileExtension) $props(FileType)

    ::InstallJammer::LogRegistry "HKEY_CLASSES_ROOT\\$props(FileExtension)"
}
Added lib/Actions/WindowsRegistryActions/AddWindowsFileType.action.






























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddWindowsFileType "Add Windows File Type"

Property FileType shorttext "File Type"
Property Title shorttext "Title"
Property IconPath installedfile "Icon Path"
Property IconPathIndex shorttext "Icon Path Index" "0"
Property ShowFileExtensions choice "Show File Extensions" \
    "Show file extensions based on user preferences" \
    {"Show file extensions based on user preferences"
     "Always show file extension"
     "Never show file extension"}

proc ::InstallJammer::actions::AddWindowsFileType { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    ::installkit::Windows::FileType set $props(FileType) $props(Title)

    if {$props(IconPath) ne ""} {
	::installkit::Windows::FileType icon $props(FileType) \
                $props(IconPath),$props(IconPathIndex)
    }

    switch -- $props(ShowFileExtensions) {
         "Always show file extension" {
            ::installkit::Windows::FileType showextension \
                $props(FileType) always 1
         }

         "Never show file extension" {
            ::installkit::Windows::FileType showextension \
                $props(FileType) never 1
         }
    }

    ::InstallJammer::LogRegistry "HKEY_CLASSES_ROOT\\$props(FileType)"
}
Added lib/Actions/WindowsRegistryActions/AddWindowsRegistryKey.action.


































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddWindowsRegistryKey "Add Windows Registry Key"

Property AddToUninstall boolean "Add to Uninstall" "Yes"
Help AddToUninstall "Whether this new key should be added to the uninstaller"

Property RootKey choice "Root Key" "HKEY_CURRENT_USER" \
    {HKEY_CLASSES_ROOT HKEY_CURRENT_USER HKEY_LOCAL_MACHINE HKEY_USERS}
Property Key shorttext "Key" "<%GUID%>"
Property Name shorttext "Name"
Property Value shorttext "Value"
Property DataType choice "Data Type" "String" \
    {"Binary Data" "String" "Expand String" "String Array" "Number"
     "Big Endian Number" "Symbolic Link" "Resource List"}

Property RestoreOnUninstall boolean "Restore on Uninstall" "No"
Help RestoreOnUninstall "If this is true, the registry value will be\
                            restored to its previous value if it already\
                            existed during installation"

proc ::InstallJammer::actions::AddWindowsRegistryKey { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set key $props(Key)
    if {![string match "HKEY*" $key]} { set key $props(RootKey)\\$key }

    set name $props(Name)

    switch -- $props(DataType) {
	"None"		    { set type none }
	"Binary Data"	    { set type binary }
	"String"    	    { set type sz }
	"Expand String"	    { set type expand_sz }
	"String Array"	    { set type multi_sz }
	"Number"	    { set type dword }
	"Big Endian Number" { set type dword_big_endian }
	"Symbolic Link"     { set type link }
	"Resource List"     { set type resource_list }
	default		    { set type none }
    }

    set conf(UpdateWindowsRegistry) 1

    if {$props(RestoreOnUninstall) && ![catch { registry get $key }]} {
        if {[catch { registry get $key $name } oldval]} {
            ::InstallJammer::LogRegistry $key $name
        } else {
            ::InstallJammer::LogRegistry $key $name $oldval
        }
    } elseif {$props(AddToUninstall)} {
        ::InstallJammer::LogRegistry $key $name
    }

    registry set $key $name $props(Value) $type
}
Added lib/Actions/WindowsRegistryActions/AddWindowsUninstallEntry.action.


























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddWindowsUninstallEntry "Add Windows Uninstall Entry"

Property RegistryKeyName shorttext "Registry Key Name" "<%ApplicationID%>"
Property UninstallString installedfile "Uninstall String" "<%Uninstaller%>"
Property QuietUninstallString installedfile "Quiet Uninstall String" \
    "<%Uninstaller%> -S"
Property DisplayName shorttext "Display Name" "<%AppName%>"
Property DisplayIcon installedfile "Display Icon" "<%ProgramExecutable%>"
Property DisplayVersion shorttext "Display Version" "<%Version%>"
Property Comments text "Comments"
Property Contact shorttext "Contact"
Property HelpLink shorttext "Help Link"
Property HelpTelephone shorttext "Help Telephone"
Property InstallDate shorttext "Install Date" "<%Date %Y%m%d%>"
Property InstallLocation installedfile "Install Location" "<%InstallDir%>"
Property InstallSource shorttext "Install Source" "<%InstallSource%>"
Property Publisher shorttext "Publisher" "<%Company%>"
Property Readme installedfile "Readme" "<%ProgramReadme%>"
Property URLInfoAbout shorttext "URL Info About" "<%ApplicationURL%>"
Property URLUpdateInfo shorttext "URL Update Info" "<%ApplicationURL%>"

proc ::InstallJammer::actions::AddWindowsUninstallEntry { obj } {
    global conf

    if {!$conf(windows)} { return }

    set properties {
        UninstallString
        QuietUninstallString
        DisplayName
        DisplayIcon
        DisplayVersion
        Comments
        Contact
        HelpLink
        HelpTelephone
        InstallDate
        InstallLocation
        InstallSource
        Publisher
        Readme
        URLInfoAbout
        URLUpdateInfo
    }

    eval $obj properties props -subst 1 [lsort $properties]

    set appkey [::InstallJammer::SubstText [$obj get RegistryKeyName]]
    set key {HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion}
    append key "\\Uninstall\\$appkey"

    ## Try to insert this first value.  If it fails, it's probably
    ## because we don't have permission to write to the Uninstall registry
    ## for the local machine.  We want to switch over and try to write to
    ## the current user's Uninstall registry instead.
    if {[catch { registry set $key NoModify 1 dword } error]} {
        set key {HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion}
        append key "\\Uninstall\\$appkey"

        registry set $key NoModify 1 dword
    }

    registry set $key NoRepair 1 dword

    foreach var [array names props] {
	registry set $key $var $props($var)
    }

    ::InstallJammer::LogRegistry $key
}
Added lib/Actions/WindowsRegistryActions/ImportWindowsRegistryFile.action.


































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ImportWindowsRegistryFile "Import Windows Registry File"

Property PromptUser boolean "Prompt User" "No"
Help PromptUser "If Prompt User is true, the user will be asked by\
                 Windows if they want to import the registry file"

Property RegistryFile installedfile "Registry File"
Help RegistryFile "A Windows .reg file to import on the target system"

proc ::InstallJammer::actions::ImportWindowsRegistryFile { obj } {
    global conf

    if {!$conf(windows)} { return }

    set file [::InstallJammer::SubstText [$obj get RegistryFile]]

    if {[file exists $file]} {
        if {[$obj get PromptUser]} {
            exec [auto_execok regedit] $file &
        } else {
            exec [auto_execok regedit] /s $file &
        }
    }

    set conf(UpdateWindowsRegistry) 1
}
Added lib/Actions/WindowsRegistryActions/RegisterWindowsLibrary.action.




















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action RegisterWindowsLibrary

Property CallDLLInstall boolean "Call DLL Install" "No"
Help CallDLLInstall "Optionally call the DLLInstall function when registering\
        the library."

Property CallDLLRegisterServer boolean "Call DLL Register Server" "Yes"
Help CallDLLRegisterServer "Whether or not to call the DLLRegisterServer\
        function when registering the library.  If this option is false,\
        then Call DLL Install must be true"

Property LibraryFile installedfile "Library File"
Help LibraryFile "The path to the DLL or other library to register"

proc ::InstallJammer::actions::RegisterWindowsLibrary { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set cmd [list [auto_execok regsvr32] /s]

    if {$props(CallDLLInstall)} {
        lappend cmd /i
    }

    if {!$props(CallDLLRegisterServer)} {
        lappend cmd /n
    }

    lappend cmd $props(LibraryFile)

    eval exec $cmd
}
Added lib/Actions/WindowsRegistryActions/RemoveWindowsRegistryKey.action.




































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action RemoveWindowsRegistryKey

Property Key shorttext "Key"

Property Value shorttext "Value"

Property RootKey choice "Root Key" "HKEY_CURRENT_USER" \
    {HKEY_CLASSES_ROOT HKEY_CURRENT_USER HKEY_LOCAL_MACHINE HKEY_USERS}

proc ::InstallJammer::actions::RemoveWindowsRegistryKey { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set conf(UpdateWindowsRegistry) 1

    set key $props(Key)
    if {![string match "HKEY*" $key]} { set key $props(RootKey)\\$key }

    if {$props(Value) eq ""} {
        catch { registry delete $key }
    } else {
        catch { registry delete $key $props(Value) }
    }
}
Added lib/Actions/WindowsRegistryActions/UnregisterWindowsLibrary.action.




















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action UnregisterWindowsLibrary

Property CallDLLUninstall boolean "Call DLL Uninstall" "No"
Help CallDLLUninstall "Optionally call the CallDLLUninstall function when\
        unregistering the library."

Property CallDLLUnregisterServer boolean "Call DLL Unregister Server" "Yes"
Help CallDLLUnregisterServer "Whether or not to call the DLLUnregisterServer\
        function when unregistering the library.  If this option is false,\
        then Call DLL Uninstall must be true"

Property LibraryFile installedfile "Library File"
Help LibraryFile "The path to the DLL or other library to unregister"

proc ::InstallJammer::actions::UnregisterWindowsLibrary { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set cmd [list [auto_execok regsvr32] /s /u]

    if {$props(CallDLLUninstall)} {
        lappend cmd /i
    }

    if {!$props(CallDLLUnregisterServer)} {
        lappend cmd /n
    }

    lappend cmd $props(LibraryFile)

    eval exec $cmd
}
Added lib/Actions/WindowsServiceActions/ContinueWindowsService.action.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ContinueWindowsService

Property Database shorttext "Database"
Property ServiceName shorttext "Service Name"
Property System shorttext "System"
Property Wait short "Wait"

proc ::InstallJammer::actions::ContinueWindowsService { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set service [twapi::get_service_internal_name $props(ServiceName)]

    set cmd [list twapi::continue_service $service]

    if {$props(Wait) ne ""} { lappend cmd -wait $props(Wait) }
    if {$props(System) ne ""} { lappend cmd -system $props(System) }
    if {$props(Database) ne ""} { lappend cmd -database $props(Database) }

    eval $cmd
}
Added lib/Actions/WindowsServiceActions/CreateWindowsService.action.


































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action CreateWindowsService

Property Account shorttext "Account"
Property Command shorttext "Command"
Property Database short "Database"
Property Dependencies shorttext "Dependencies"
Property Description text "Description"
Property DisplayName shorttext "Display Name"
Property ErrorControl choice "Error Control" "Normal" \
  {"Critical" "Ignore" "Normal" "Severe"}
Property Interactive boolean "Interactive" "No"
Property LoadOrderGroup shorttext "Load Order Group"
Property Password short "Password"
Property ServiceName shorttext "Service Name"
Property ServiceType choice "Service Type" "Own Process" \
  {"Own Process" "Shared Process" "File System Driver" "Kernel Driver"}
Property StartType choice "Start Type" "Auto Start" \
  {"Auto Start" "Boot Start" "Demand Start" "Disabled" "System Start"}
Property System short "System"

proc ::InstallJammer::actions::CreateWindowsService { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set cmd [list twapi::create_service $props(ServiceName) $props(Command)]

    if {$props(System) ne ""} { lappend cmd -system $props(System) }
    if {$props(Database) ne ""} { lappend cmd -database $props(Database) }

    lappend cmd -interactive $props(Interactive)

    lappend cmd -servicetype
    if {[string match "*Process*" $props(ServiceType)]} {
        set type [string map {Shared Share} $props(ServiceType)]
        lappend cmd win32_[string tolower [join $type _]]
    } else {
        lappend cmd [string tolower [join $props(ServiceType) _]]
    }

    lappend cmd -starttype [string tolower [join $props(StartType) _]]
    
    lappend cmd -errorcontrol [string tolower $props(ErrorControl)]

    if {$props(DisplayName) ne ""} {
        lappend cmd -displayname $props(DisplayName)
    }

    if {$props(LoadOrderGroup) ne ""} {
        lappend cmd -loadordergroup $props(LoadOrderGroup)
    }

    if {$props(Dependencies) ne ""} {
        lappend cmd -dependencies $props(Dependencies)
    }

    if {$props(Account) ne ""} {
        lappend cmd -account $props(Account)
    }

    if {$props(Password) ne ""} {
        lappend cmd -password $props(Password)
    }

    eval $cmd

    if {$props(Description) ne ""} {
        set key "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services"
        append key "\\$props(ServiceName)"
        registry set $key Description $props(Description)
    }
}
Added lib/Actions/WindowsServiceActions/DeleteWindowsService.action.




































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action DeleteWindowsService

Property Database shorttext "Database"
Property ServiceName shorttext "Service Name"
Property System shorttext "System"

proc ::InstallJammer::actions::DeleteWindowsService { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set service [twapi::get_service_internal_name $props(ServiceName)]

    set cmd [list twapi::delete_service $service]

    if {$props(Database) ne ""} {
        lappend cmd -database $props(Database)
    }

    if {$props(System) ne ""} {
        lappend cmd -system $props(System)
    }

    eval $cmd
}
Added lib/Actions/WindowsServiceActions/PauseWindowsService.action.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action PauseWindowsService

Property Database shorttext "Database"
Property ServiceName shorttext "Service Name"
Property System shorttext "System"
Property Wait short "Wait"

proc ::InstallJammer::actions::PauseWindowsService { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set service [twapi::get_service_internal_name $props(ServiceName)]

    set cmd [list twapi::pause_service $service]

    if {$props(Wait) ne ""} { lappend cmd -wait $props(Wait) }
    if {$props(System) ne ""} { lappend cmd -system $props(System) }
    if {$props(Database) ne ""} { lappend cmd -database $props(Database) }

    eval $cmd
}
Added lib/Actions/WindowsServiceActions/StartWindowsService.action.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action StartWindowsService

Property Database shorttext "Database"
Property ServiceName shorttext "Service Name"
Property System shorttext "System"
Property Wait short "Wait"

proc ::InstallJammer::actions::StartWindowsService { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set service [twapi::get_service_internal_name $props(ServiceName)]

    set cmd [list twapi::start_service $service]

    if {$props(Wait) ne ""} { lappend cmd -wait $props(Wait) }
    if {$props(System) ne ""} { lappend cmd -system $props(System) }
    if {$props(Database) ne ""} { lappend cmd -database $props(Database) }

    eval $cmd
}
Added lib/Actions/WindowsServiceActions/StopWindowsService.action.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action StopWindowsService

Property Database shorttext "Database"
Property ServiceName shorttext "Service Name"
Property System shorttext "System"
Property Wait short "Wait"

proc ::InstallJammer::actions::StopWindowsService { obj } {
    global conf

    if {!$conf(windows)} { return }

    $obj properties props -subst 1

    set service [twapi::get_service_internal_name $props(ServiceName)]

    set cmd [list twapi::stop_service $service]

    if {$props(Wait) ne ""} { lappend cmd -wait $props(Wait) }
    if {$props(System) ne ""} { lappend cmd -system $props(System) }
    if {$props(Database) ne ""} { lappend cmd -database $props(Database) }

    eval $cmd
}
Added lib/Actions/WizardActions/AddPaneToOrder.action.






































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddPaneToOrder

Property Index short "Index" "end"
Help Index "Where in the order to add the pane (end means to append to the end)"

Property Pane window "Pane"
Help Pane "The ID or alias of the pane to be add to the Wizard order"

proc ::InstallJammer::actions::AddPaneToOrder { obj } {
    global info

    $obj properties props -subst 1

    set id  [::InstallJammer::ID $props(Pane)]
    set idx $props(Index)

    if {![string match "end*" $idx] && ![string is integer -strict $idx]} {
        set idx [::InstallJammer::ID $props(Index)]
        if {[::InstallJammer::ObjExists $idx]} {
            set idx [$info(Wizard) index $idx]
        }
    }

    set order [$info(Wizard) order]
    set order [linsert $order $idx $id]

    $info(Wizard) order $order
}
Added lib/Actions/WizardActions/AddWidget.action.






























































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AddWidget "Add Widget"

Property Action short "Action"
Help Action "An action to execute when a button is pressed or a checkbutton\
                or radiobutton is changed"

Property Background color "Background" "system"
Help Background "The background color of the widget (system means use default)"

Property BrowseType choice "Browse Type" "directory" \
    {directory "open file" "save file"}

Property Checked nullboolean "Checked" ""
Help Checked "Whether or not this widget should be checked by default\
                (only valid for radio and check buttons)"

Property Editable boolean "Editable" "Yes"
Help Editable "Whether or not the combobox should be editable so that a value\
                other than the given Values can be entered"

Property FileTypes short "File Types"
Help FileTypes "A list of pairs describing the file types to allow in when\
                the user is browsing for files or directories.  Each type\
                must be a description followed by a list of extensions"
Property Foreground color "Foreground" "system"
Help Foreground "The foreground color of the widget (system means use default)"

Property Height integer "Height"
Help Height "The pixel height of the widget"

Property LabelJustify choice "Label Justify" "left" {center left right}
Help LabelJustify "Which side to justify the labels on"

Property LabelSide choice "Label Side" "top" {left top}
Help LabelSide "The side of the widget the label should appear on"

Property LabelWidth short "Label Width" "0"
Help LabelWidth "The width of the label, in characters, if a label is present\
                    (0 means to be as wide as needed)"

Property OffValue short "Off Value" "0"
Help OffValue "The value of the virtual text for a checkbutton when the\
        checkbutton is not checked or off"

Property OnValue short "On Value" "1"
Help OffValue "The value of the virtual text for a checkbutton when the\
        checkbutton is checked or on"

Property Type addwidgettype "Type" "label" \
  {button "browse entry" checkbutton combobox entry label "label frame"
    "password entry" radiobutton text}
Help Type "The type of widget to add"

Property ValidateEntryOn editchoice "Validate On" "" \
    {Create Focus FocusIn FocusOut Key Select}
Help ValidateEntryOn "This property tells InstallJammer when to execute the\
    associated Action property when validating an entry widget."

Property Value short "Value"
Help Value "The value stored in Virtual Text when the radiobutton is selected"

Property Values short "Values"
Help Values "A list of values to display in the dropdown of the combobox"

Property VirtualText short "Virtual Text"
Help VirtualText "The Virtual Text field to store results in"

Property Width integer "Width"
Help Width "The pixel width of the widget"

Property X integer "X"
Help X "The X coordinate to place this widget at"

Property Y integer "Y"
Help Y "The Y coordinate to place this widget at"

Text Text

proc ::InstallJammer::actions::AddWidget { obj } {
    global info

    set id     [$obj id]
    set parent [$obj parent]
    if {![$parent ispane]} { set parent $info(CurrentPane) }
    set window [$parent window]
    set widget $window.[$obj name]

    if {![info exists ::InstallJammer]} {
        variable ::InstallJammer::UserWidgets
        if {[info exists UserWidgets($id)]} { return }
        set UserWidgets($id) $widget
    }

    $id window $widget

    $obj properties props -subst 1

    set opts {}

    set ttk        1
    set type       ttk::$props(Type)
    set text       [::InstallJammer::GetText $id Text -subst 0]
    set style      T[string totitle $props(Type)]
    set boolean    0
    set command    ""
    set validate   ""
    set varName    ::info($props(VirtualText))
    set setWidget  $widget
    set widgetType text
    set virtualText "<%$props(VirtualText)%>"

    set value $props(Value)

    if {$props(Action) ne ""} {
        set command [list ::InstallJammer::ExecuteActions $props(Action)]
    }

    switch -- $props(Type) {
        "button" {
            lappend opts -command $command
        }

        "browse entry" {
            set type       ttk::entry
            set style      TEntry
            set browse     1
            set varopt     -textvariable
            set widgetType entry
            set validate   $props(ValidateEntryOn)

            if {$text ne ""} { set label $text }
            if {$value ne ""} { set varval $value }
        }

        "checkbutton" {
            set varopt -variable

            set onval   $props(OnValue)
            set offval  $props(OffValue)
            set boolean 1

            lappend opts -onvalue  $onval
            lappend opts -offvalue $offval

            lappend opts -command $command

            if {$props(Checked) ne ""} {
                if {$props(Checked)} {
                    set varval $onval
                } else {
                    set varval $offval
                }
            }
        }

        "combobox" {
            set type       ttk::combobox
            set style      TEntry
            set varopt     -textvariable
            set widgetType entry
            set validate   $props(ValidateEntryOn)

            lappend opts -values $props(Values)

            if {!$props(Editable)} {
                lappend opts -state readonly
            }

            if {$text ne ""} { set label $text }
            if {$value ne ""} { set varval $value }
        }

        "entry" - "password entry" {
            set type       ttk::entry
            set style      TEntry
            set varopt     -textvariable
            set widgetType entry
            set validate   $props(ValidateEntryOn)

            if {$props(Type) eq "password entry"} {
                lappend opts -show *
            }

            if {$text ne ""} { set label $text }
            if {$value ne ""} { set varval $value }
        }

        "label frame" {
            set ttk  0
            set type labelframe
        }

        "radiobutton" {
            set varopt -variable

            lappend opts -value $value
            lappend opts -command $command

            if {[string is true -strict $props(Checked)]} {
                set varval $value
            }
        }

        "text" {
            set ttk        0
            set type       Text
            set varopt     -textvariable
            set widgetType usertext

            if {$text ne ""} { set label $text }
            if {$value ne ""} { set varval $value }
        }
    }

    if {[info exists varopt]} {
        lappend opts $varopt $varName
        if {[info exists varval]} {
            set $varName $varval
        }

        ## Always default the variable to something, even if
        ## it's just a 0 or an empty string.
        if {![info exists $varName]} {
            if {$boolean} {
                set $varName $props(OffValue)
            } else {
                set $varName ""
            }
        } elseif {$boolean && $onval eq "1" && $offval eq "0"} {
            set $varName [string is true [set $varName]]
        }
    }

    ::InstallJammer::SetVirtualText $info(Language) $parent $id $text
    $parent set $id,subst $props(Text,subst)

    set bg $props(Background)
    if {$bg ne "system"} {
        if {$ttk} {
            lappend newStyleOpts -background $bg
        } else {
            lappend opts -background $bg
        }
    }

    set fg $props(Foreground)
    if {$fg ne "system"} {
        if {$ttk} {
            lappend newStyleOpts -foreground $fg
        } else {
            lappend opts -foreground $fg
        }
    }

    if {[info exists newStyleOpts]} {
        eval lappend opts -style $id
        eval [list ::InstallJammer::NewStyle $id $style] $newStyleOpts
    }
    
    set events {}
    foreach event [split $validate \;] {
        lappend events [string trim $event]
    }
    set validate $events
        
    if {[info exists label] || [info exists browse]} {
        set xopts [list]
        if {$bg ne "system"} {
            ::InstallJammer::NewStyle $id-frame TFrame -background $bg
            lappend xopts -style $id-frame
        }

        eval [list ttk::frame $widget] $xopts
        grid rowconfigure    $widget 1 -weight 1
        grid columnconfigure $widget 1 -weight 1

        set row 0
        set col 0

        if {[info exists label]} {
            set widgetType text
	    set width      $props(LabelWidth)

            switch -- $props(LabelSide) {
                "bottom" { set row 2; set col 1; set opt -pady }
                "top"    { set row 0; set col 1; set opt -pady }
                "left"   { set row 1; set col 0; set opt -padx }
                "right"  { set row 1; set col 2; set opt -padx }
            }

	    set anchor center
	    switch -- $props(LabelJustify) {
	    	"left"  { set anchor w }
		"right" { set anchor e }
 	    }

	    set justify $props(LabelJustify)

            set xopts [list -anchor $anchor -justify $justify \
	    		-text $label -width $width]

            if {$bg ne "system"} {
                ::InstallJammer::NewStyle $id-label TLabel -background $bg
                lappend xopts -style $id-label
            }
            eval [list ttk::label $widget.l] $xopts
            grid $widget.l -row $row -column $col -sticky w $opt 2
        }

        eval [list $type $widget.x] $opts
        grid $widget.x -row 1 -column 1 -sticky news
        set bindWidget $widget.x

        if {[info exists browse]} {
            set text [::InstallJammer::SubstText <%Browse%>]

            if {$props(BrowseType) eq "directory"} {
                set cmd [list ::InstallJammer::ChooseDirectory]
            } else {
                set cmd "::InstallJammer::ChooseFile"
                lappend cmd -type [lindex $props(BrowseType) 0]
                if {$props(FileTypes) ne ""} {
                    set filetypes {}
                    foreach {ext desc} $props(FileTypes) {
                        lappend filetypes [list $ext $desc]
                    }
                    lappend cmd -filetypes $filetypes
                }
            }
            lappend cmd -variable $varName
            if {$command ne ""} {
                set x [lsearch -exact $validate "Select"]
                if {$x != -1} {
                    lappend cmd -command $command
                    set validate [lreplace $validate $x $x]
                }
            }

            ttk::button $widget.b -text $text -command $cmd
            grid $widget.b -row 1 -column 2 -padx 2

            $parent widget set $id -widget $widget.b
        }
    } else {
        set bindWidget $widget
        eval [list $type $widget] $opts
    }

    place $widget -in $window -x $props(X) -y $props(Y) \
        -width $props(Width) -height $props(Height)

    bind $widget <Destroy> \
        "+unset -nocomplain ::InstallJammer::UserWidgets($id)"

    if {[llength $validate] && $command ne ""} {
        foreach event $validate {
            if {$event eq "Create"} {
                eval $command
            } else {
                if {$event eq "Select"} {
                    set event "<<ComboboxSelected>>"
                } else {
                    set event <$event>
                }
                set cmd [list after idle $command]
                if {[catch {bind $bindWidget $event $cmd} err]} {
                    return -code error "invalid Validate On event \"$event\""
                }
            }
        }
    }

    $parent widget set $id -widget $setWidget -type $widgetType

    ::InstallJammer::UpdateWidgets -widgets $id -step $parent
}
Added lib/Actions/WizardActions/AppendTextToWidget.action.


















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action AppendTextToWidget

Property AutoScroll boolean "Auto Scroll" "Yes"
Help AutoScroll "If this property is true, the text widget will be\
    automatically scrolled to the bottom once the text is inserted"

Property ClearWidget boolean "Clear Widget" "No"
Help ClearWidget "If this property is true, the text widget will be\
    cleared of any text before the new text is inserted"

Property Widget widget "Widget"
Help Widget "The name of the text widget to append text to"

Text Text

proc ::InstallJammer::actions::AppendTextToWidget { obj } {
    global info

    set id [$obj id]

    $obj properties props -subst 1

    set parent [$obj parent]
    set widget [::InstallAPI::GetWidgetPath -window [$obj parent] \
        -widget $props(Widget)]
    if {[winfo exists $widget]} {
        set state [$widget cget -state]
        $widget configure -state normal
        if {$props(ClearWidget)} { $widget delete 1.0 end }
        $widget insert end [::InstallJammer::GetText $id Text]
        $widget configure -state $state
        if {$props(AutoScroll)} { $widget yview moveto 1.0 }
    }
}
Added lib/Actions/WizardActions/CreateInstallPanes.action.






















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action CreateInstallPanes "Create Install Panes"

proc ::InstallJammer::actions::CreateInstallPanes { obj } {
    global conf
    global info

    set parent      [$obj parent]
    set progressbar [$parent widget get ProgressBar]
    if {![string length $progressbar]} { set progressbar noop }

    set children [$info($conf(mode)) children recursive]
    set total    [llength $children]
    foreach id $children {
        $progressbar configure -value [expr {[incr0 i] * 100 / $total}]
        update
        if {[$id ispane]} {
            $info(Wizard) createstep $id
        }
    }
}
Added lib/Actions/WizardActions/DestroyWidget.action.






























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action DestroyWidget "Destroy Widget"

Property WidgetId widget "Widget ID"

proc ::InstallJammer::actions::DestroyWidget { obj } {
    $obj properties props -subst 1
    ::InstallAPI::DestroyWidget -widgets [split $props(WidgetId) \;]
}
Added lib/Actions/WizardActions/FocusOnWidget.action.
































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action FocusOnWidget "Focus On Widget"

Property WidgetID widget "Widget ID"

proc ::InstallJammer::actions::FocusOnWidget { obj } {
    $obj properties props -subst 1
    set w [::InstallAPI::GetWidgetPath -widget $props(WidgetID)]
    if {[winfo exists $w]} { focus $w }
}
Added lib/Actions/WizardActions/ModifyWidget.action.
































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action ModifyWidget "Modify Widget"

Property Widget widget    "Widget" ""

Property State  choice    "State"  "" {disabled hidden normal readonly}
Help State "Modify the state of the given widget (readonly on applies to\
                entry and text widgets)."

Property Text   shorttext "Text"   ""

proc ::InstallJammer::actions::ModifyWidget { obj } {
    global conf
    global info

    variable hidden

    set id     [$obj id]
    set parent [$obj parent]

    if {![$parent ispane]} {
        set parent $info(CurrentPane)
    }

    $obj properties props

    if {![string length $props(Widget)]} { return }

    set allArgs   {}
    set labelArgs {}

    if {$props(Text) ne ""}  {
    	lappend labelArgs -text $props(Text)
    }

    if {$props(State) ne "" && $props(State) ne "hidden"} {
        lappend allArgs -state $props(State)
    }

    set widgets [split $props(Widget) \;]

    for {set i 0} {$i < [llength $widgets]} {incr i} {
        set name [string trim [lindex $widgets $i]]
        set name [::InstallJammer::ID $name]
        set w [join $name ""]
        set widget $w

        set button 0
        if {[lsearch -exact $conf(ButtonWidgets) $widget] > -1} {
            set button 1
            set w [string tolower [string map {Button ""} $widget]]
        }

        if {$button} {
            set w [$info(Wizard) widget get $w]
        } else {
            set w [$parent widget get $widget]
        }

        if {$w eq ""} {
            return -code error "bad widget \"$name\""
        }

        if {$props(Text) ne ""} {
            ::InstallJammer::SetVirtualText all $parent $widget $props(Text)
        }

	set class [winfo class $w]
	if {$class eq "Frame" || $class eq "TFrame"} {
	    foreach child [winfo children $w] {
		set class [winfo class $child]
		if {$class eq "Label" || $class eq "TLabel"} {
		    eval [list $child configure] $labelArgs
		}
		eval [list $child configure] $allArgs
	    }
	} else {
            if {$class eq "Text"} {
                eval [list $w configure] $allArgs
                if {[llength $labelArgs]} {
                    set state [$w cget -state]
                    $w configure -state normal
                    $w delete 1.0
                    $w insert end $props(Text)
                    $w configure -state $state
                }
            } else {
                eval [list $w configure] $allArgs $labelArgs
            }
	}

        if {$props(State) eq "hidden" && ![info exists hidden($w)]} {
            set manager [winfo manager $w]
            set options [$manager info $w]
            set hidden($w) [concat $manager configure $w $options]
            $manager forget $w
        } elseif {$props(State) eq "normal" && [info exists hidden($w)]} {
            eval $hidden($w)
            unset hidden($w)
        }
    }

    if {$props(Text) ne ""} {
        ::InstallJammer::UpdateWidgets -buttons 1 -updateidletasks 1
    }
}
Added lib/Actions/WizardActions/MoveForward.action.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action MoveForward "Move Forward"

proc ::InstallJammer::actions::MoveForward { obj } {
    global conf
    global info

    set next [$info(Wizard) step next]

    ## If this is the last step, call the action to exit the install.
    if {$next eq ""} {
        debug "No more panes left to move forward... exiting"
        ::InstallAPI::Exit
    } else {
        debug "Moving forward to $next"
        set conf(moveToPane) "next"
    }
}
Added lib/Actions/WizardActions/MoveToPane.action.








































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action MoveToPane "Move to Pane"

Property Pane window "Pane"

proc ::InstallJammer::actions::MoveToPane { obj } {
    global conf
    global info

    $obj properties props -subst 1

    set id [::InstallJammer::ID $props(Pane)]
    set conf(moveToPane) $id
}
Added lib/Actions/WizardActions/PopulateComponents.action.




















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action PopulateComponents

proc ::InstallJammer::actions::PopulateComponents { obj } {
    global conf
    global info

    set step [$obj parent]

    set tree [$step widget get ComponentTree]
    set text [$step widget get DescriptionText]

    if {[lsearch -exact $conf(ComponentTrees) $tree] < 0} {
        lappend conf(ComponentTrees) $tree
    }

    $tree clear

    set setuptype $info(InstallTypeID)

    set new 0
    if {![info exists conf(PopulatedSetupType)]
        || $conf(PopulatedSetupType) ne $setuptype} {
        set new 1
        array unset ::InstallJammer::Components $tree,*
    }

    set conf(PopulatedSetupType) $setuptype

    foreach id [$setuptype get Components] {
        if {![$id get ShowComponent]} { continue }

        set parent [$id parent]
        set group  [$id get ComponentGroup]
        if {$parent eq "Components"} { set parent root }

        ## If our parent doesn't exist in the tree, it's
        ## possible that the parent is not being shown.
        if {![$tree exists $parent]} { continue }

        set varName ::InstallJammer::Components($tree,$id)
        if {$group ne ""} {
            set varName ::InstallJammer::Components($tree,$group)
            if {![info exists $varName]} { set $varName "" }
        }

        set checked  [string is true [$id get Checked]]
        set required [$id get RequiredComponent]

        if {$required} { set checked 1 }

        if {$new} { $id active $checked }

        set text [::InstallAPI::GetDisplayText -object $id]

        if {![$id get Selectable]} {
            ## Draw with no check or radio button.  This is a heading.
            $tree insert end $parent $id -text $text -type none -open 1 \
                -command [list ::InstallJammer::ToggleComponent %W $step %n]
        } elseif {$group eq ""} {
            ## Draw as a checkbutton.
            if {$new} { set $varName $checked }
            $tree insert end $parent $id -text $text -type checkbutton \
                -command [list ::InstallJammer::ToggleComponent %W $step %n] \
                -variable $varName -open 1
        } else {
            ## Draw as a radiobutton.
            $tree insert end $parent $id -text $text -type radiobutton \
                -command [list ::InstallJammer::ToggleComponent %W $step %n] \
                -variable $varName -value $id -open 1
            lappend ::InstallJammer::Components($tree,$group,others) $id

            if {$new && $checked} { set $varName $id }
        }

        if {$required} { $tree itemconfigure $id -state disabled }
    }

    bind $tree <<TreeSelect>> [list ::InstallJammer::SelectComponent $step]

    ## Select the first component in the tree.
    $tree selection set [lindex [$tree nodes root] 0]
    ::InstallJammer::SelectComponent $step
}
Added lib/Actions/WizardActions/PopulateSetupTypes.action.












































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action PopulateSetupTypes

proc ::InstallJammer::actions::PopulateSetupTypes { obj } {
    global conf
    global info

    set step [$obj parent]

    set text    [$step widget get DescriptionText]
    set listbox [$step widget get SetupTypeListBox]

    if {[lsearch -exact $conf(SetupTypeTrees) $listbox] < 0} {
        lappend conf(SetupTypeTrees) $listbox
    }
    
    $listbox clear

    foreach id [SetupTypes children] {
        if {![$id active] || ![$id get ShowSetupType]} { continue }

        set text [::InstallAPI::GetDisplayText -object $id]
        $listbox insert end $id -text $text -data [$id name]
        if {[$id name] eq $info(InstallType)} {
            ::InstallJammer::SelectSetupType $id
        }
    }

    bind $listbox <<ListboxSelect>> {
        ::InstallJammer::SelectSetupType [%W selection get]
    }
}
Added lib/Actions/WizardActions/RemovePaneFromOrder.action.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Action RemovePaneFromOrder

Property Pane window "Pane"
Help Pane "The ID or alias of the pane to be removed from the Wizard order"

proc ::InstallJammer::actions::RemovePaneFromOrder { obj } {
    global info

    $obj properties props -subst 1

    set id [::InstallJammer::ID $props(Pane)]

    set order [$info(Wizard) order]
    set order [lremove $order $id]

    $info(Wizard) order $order
}
Added lib/Actions/WizardActions/SkipPane.action.






















>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
Action SkipPane

Property Pane window "Pane"
Help Pane "The Alias or ID of the pane to be skipped.  If this property is\
    left blank (the default), it means to stop processing any further actions\
    for the current pane and skip forward to the next pane"

proc ::InstallJammer::actions::SkipPane { obj } {
    $obj properties props -subst 1
    ::InstallAPI::SkipPane -pane $props(Pane)
}
Added lib/Actions/WizardActions/Stop.action.










>
>
>
>
>
1
2
3
4
5
Action Stop

proc ::InstallJammer::actions::Stop { obj } {
    ::InstallAPI::Stop
}
Added lib/BWidget/ChangeLog.


































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
2004-04-26  Jeff Hobbs  <jeffh@ActiveState.com>

	* tree.tcl (_update_nodes): align with _draw_nodes code,
	specifically correcting placement of cross on new nodes and anchor
	of changed window/image.

2004-04-23  Jeff Hobbs  <jeffh@ActiveState.com>

	* listbox.tcl (create): don't force -highlightthickness 1 as it
	prevents the user changing it on creation.
	(_draw_item): pass more cached info from _redraw_items for speed.
	(_redraw_selection): correct drawing of selfill for items that
	extend beyond the width of the window.

2004-04-22  Jeff Hobbs  <jeffh@ActiveState.com>

	* tree.tcl (edit): correct inversion of verifycmd emptiness test.
	* listbox.tcl: correct eval/after/lists usage.
	(_redraw_listbox): call _update_select_fill on redraw, otherwise
	the insert of items causes wonkiness.
	(_redraw_items): call update idle after changing cursor.
	(create): Insert $path into the canvas bindings, so that anyone
	binding directly onto the widget will see their bindings activated
	when the canvas has focus. Add slightly modified up/down bindings
	to the canvas, in case it gets the focus (like with -autofocus).

2004-04-21  Jeff Hobbs  <jeffh@ActiveState.com>

	* tree.tcl (_draw_subnodes): Adjust the drawing of the line to the
	first root node to start at the vertical point (not go up).

	* entry.tcl, arrow.tcl, combobox.tcl: better space/list handling

	* entry.tcl: make the icursor not appear for non-editable and/or
	state disabled comboboxes.

2004-03-08  Joe English  <jenglish@users.sourceforge.net>

	* init.tcl: (bugfix) Use <<PrevWindow>> virtual event instead
	of <Shift-Tab> event for back-tab binding.

2004-02-07  Jeff Hobbs  <jeffh@ActiveState.com>

	* progressbar.tcl (ProgressBar::_modify): convert rect coords to
	ints to prevent left-over lines that are likely due to a bug in
	core Tk related to fractional coord refresh.

2004-02-03  Jeff Hobbs  <jeffh@ActiveState.com>

	* scrollw.tcl (ScrolledWindow::create): correctly set -relief and
	-bd at creation time. [Bug #873666]

	* init.tcl: don't modify *Listbox.background and *Button.padY
	options - leave core widgets alone.

	* mainframe.tcl (MainFrame::_create_menubar): set the bg for menus
	only on unix (otherwise disturbs menu native L&F)
	Correct some eval/list issues.

	* BWman/MainFrame.html: 
	* mainframe.tcl (MainFrame::_create_entries): correct 'cascade'
	spelling, but support old 'cascad' as well.

2004-01-28  Reinhard Max  <max@suse.de>

	* configure.in: bumped to v1.7.
	This should have happened before releasing 1.7.0.

	* Makefile.in: fixed support for DESTDIR.

2004-01-05  Damon Courtney  <damon@unreality.com>

	* init.tcl: Added a binding to the Tk spinbox to handle
	traversal as loading BWidgets seems to screw up the default
	handling for Tk.  [Bug #867604]

	* utils.tcl: Fixed a bug that would cause some geometry calculations
	in BWidget::place to behave incorrectly.  This would occasionally
	make it appear as though a drawn dialog would freeze the application.
	[Bug #868315]

2003-12-18  Bob Techentin <techentin@sourceforge.net>

	**** BWIDGET 1.7.0 TAGGED ****

	* README.txt: Changed revision to 1.7.0.  Note that
	1.7.0 does not include 2003-11-26 mod to notebook.tcl.

2003-11-26  Jeff Hobbs  <jeffh@ActiveState.com>

	* notebook.tcl (NoteBook::bindtabs): correct tab name returned.	(groth)

2003-11-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* entry.tcl (Entry::create): add missing line continuation.
	[Patch #843932] (oehlmann)

2003-11-10  Damon Courtney  <damon@unreality.com>

	* entry.tcl: Use a button widget for -disabled options if
	we're using 8.3 [Bug 839469]

2003-11-05  Damon Courtney  <damon@unreality.com>

	* combobox.tcl: Fixed dropdown listbox selection for
	standard Tk listbox [Bug 831496].

2003-11-05  Jeff Hobbs  <jeffh@ActiveState.com>

	* scrollview.tcl (ScrollView::_set_view): correct :canvas to
	renamed :cmd.

2003-10-30  Jeff Hobbs  <jeffh@ActiveState.com>

	* scrollw.tcl (ScrolledWindow::setwidget): check that the old
	widget associated still exists before unconfiguring it. [Bug #833034]

2003-10-27  Damon Courtney  <damon@unreality.com>

	* combobox.tcl, listbox.tcl: Fixed keyboard navigation in the
	combobox drop down [Bug 831496].

	* listbox.tcl: Added curselection subcommand to mimic Tk listbox
	behavior.

	Added keyboard navigation to the listbox.

	* widget.tcl: Added Widget::exists command to return whether a
	widget is a BWidget (based on whether it exists in the _class array).

	Widget::destroy now properly unsets the widget's variable in
	the _class array.

2003-10-27  Joe English  <jenglish@users.sourceforge.net>
	* DragSite.html, DropSite.html: Fix markup errors [Bug #740484]

2003-10-20  Damon Courtney  <damon@unreality.com>
	* arrow.tcl, bitmap.tcl, button.tcl, buttonbox.tcl, color.tcl,
	* combobox.tcl, dialog.tcl, dragsite.tcl, dropsite.tcl, entry.tcl
	* font.tcl, label.tcl, labelentry.tcl, labelframe.tcl, listbox.tcl
	* mainframe.tcl, messagedlg.tcl, notebook.tcl, pagesmgr.tcl
	* panedw.tcl, passwddlg.tcl, progressbar.tcl, progressdlg.tcl
	* scrollframe.tcl, scrollview.tcl, scrollw.tcl, separator.tcl
	* spinbox.tcl, titleframe.tcl, tree.tcl, utils.tcl, widget.tcl
	* xpm2image.tcl: Revamp again to let core Widget commands handle
	most of the esoteric work of creating and destroying widgets
	properly in the BWidget environment.

	The command Widget::define defines a class, its filename and a
	list of classes which it uses.  This command handles creating
	the command to create new widgets, creates a ::use command for
	the class and calls the ::use command for each class included.

	The command Widget::create does the renaming of the widget to
	$path:cmd and creates the proc to redirect the widget commands.

	Widget::destroy now does the rename $path "" that almost all
	widgets do.

	* button.tcl: Added a -state option to configure the state of the
	entire box at once.

	Added new insert and delete subcommands.

	Added an after cancel to stop button repeat upon release.
	[Bug 697022]

	* combobox.tcl: Added -bwlistbox, -listboxwidth and -hottrack options.
	-images option already existed, but now it actually does something.

	Added getlistbox, get, icursor, post and unpost subcommands.

	* dynhelp.tcl: Added add subcommand to replace the (now) deprecated
	register command.  The new command adds for a lot more flexibility
	in applying dynamic help.

	Help popup now comes up -topmost 1 on Windows if available.

	* entry.tcl: Added -disabledbackground option so that the BWidget
	entry more closely resembles the standard Tk entry.
	[Bug 638236].

	* init.tcl: Moved Widget::traverseTo into widget.tcl.

	* label.tcl: Renamed BWLabel class to just Label.

	* listbox.tcl: Added a default -dropcmd so that if -dragenabled
	and -dropenabled are true, drag-and-drop within the same widget
	is possible without any other options.

	Added -autofocus option to specify that clicking within the listbox
	should draw the focus in order to handle mouse wheel events.

	Added -selectfill option for drawing a full selection rectangle
	around selected items instead of just around the item.

	Added getcanvas subcommand.  [Bug 436762].

	bindImage and bindText now map %W to $path in order to get an
	accurate path in events.  This can probably be fixed better
	when we have more control over event parameters.  [Bug 607745]

	Added mouse wheel bindings by default.

	Added <<ListboxSelect>> event when selection changes.

	* mainframe.tcl: Fixed bug for adding CTRL-F items to a mainframe
	[Bug 784269]

	* messagedlg.tcl: Added -buttonwidth option.

	* notebook.tcl: Added dynamic help to tabs.

	Added -tabpady option to specify the padding between the text and
	the tab.

	Notebooks now handle multi-line text properly.  [Bug 565284]

	* scrollview.tcl: Rewritten to use a variable per path instead of
	a big array.

	* tree.tcl: Added -anchor option to nodes to specify the anchor for
	an image or window when displayed.

	Added -crossopenimage, -crosscloseimage, -crossopenbitmap and
	-crossclosebitmap options to change the open / close cross.

	Added mouse wheel bindings by default.

	Added toggle subcommand to toggle a single tree node.

	Added <<TreeSelect>> event when selection changes.

	The characters "& | ^ !" are all converted to | silently in
	node names.  This is to avoid errors because these characters
	are special to the canvas widget.  [Bug 746960]

	bindImage and bindText now map %W to $path in order to get an
	accurate path in events.  This can probably be fixed better
	when we have more control over event parameters.  [Bug 607745]

	* utils.tcl: Added BWidget::wrongNumArgsString command to return
	a standard wrong # args error string.

	Added BWidget::classes command that returns a list of all classes
	required by a given class.

	Added BWidget::inuse command to determine if a given class is inuse.

	Added BWidget::library command to return a body of code that can
	be saved into a project or other code based on the given classes.
	When called with a list of classes, all the classes and code
	necessary to use those classes is returned in a large string which
	can then be written out to a file.

	Added BWidget::write command to write to a given file the current
	set of classes that are in use.

	Added BWidget::bindMouseWheel command to setup default mouse
	bindings on a given widget.

	* widget.tcl: Added a new option type 'Padding' which will accept
	the standard padding arguments in Tcl 8.4+.

	Added Widget::define command to define a new BWidget class.

	Added Widget::create command to create a BWidget properly.

	Widget::destroy now attempts to delete a widget command created
	through Widget::create.

	Added Widget::options command to return the current options of
	a given widget in a style that can be used to serialize a widget.

	Added Widget::getOption command to get options based on children
	having the same option.

	* wizard.tcl: Added new Wizard widget.


2003-10-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* arrow.tcl, bitmap.tcl, button.tcl, buttonbox.tcl, color.tcl,
	* combobox.tcl, dialog.tcl, dragsite.tcl, dropsite.tcl, entry.tcl
	* font.tcl, label.tcl, labelentry.tcl, labelframe.tcl, listbox.tcl
	* mainframe.tcl, messagedlg.tcl, notebook.tcl, pagesmgr.tcl
	* panedw.tcl, passwddlg.tcl, progressbar.tcl, progressdlg.tcl
	* scrollframe.tcl, scrollview.tcl, scrollw.tcl, separator.tcl
	* spinbox.tcl, titleframe.tcl, tree.tcl, utils.tcl, widget.tcl
	* xpm2image.tcl: major revamp to reduce incorrect use of eval and
	other list-safetiness evils.  Also change !strcomp to streq.

2003-08-06  Jeff Hobbs  <jeffh@ActiveState.com>

	* listbox.tcl: Correct Listbox selection drawing [Bug #781652]

2003-07-17  Joe English  <jenglish@users.sourceforge.net>
	* init.tcl, combobox.tcl:  Fix for [Bug 720032] "BWidget
	breaks Tk entry behaviour".  Highlight the entry
	in a <<TraverseIn>> binding, instead of doing so
	on every <FocusIn> event.  Change the global <Tab> 
	and <Shift-Tab> bindings to generate <<TraverseIn>>
	and <<TraverseOut>> events.

2003-07-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* notebook.tcl: Use list with eval for safety.
	Use lsearch -exact instead of default -glob in all uses.

	* listbox.tcl (_multiple_select): correct shift-selection when
	selectmode is multiple.  [Bug 653266]
	Use lsearch -exact instead of default -glob in all uses.
	Use list with eval for safety.

	* BWman/ScrolledWindow.html: clarify management of embedded widget.

2003-06-23  Damon Courtney <damon@unreality.com>
	* combobox.tcl: Added a little better handling of keys in the
	auto-complete.

2003-06-06  Damon Courtney <damon@unreality.com>
	* combobox.tcl: Added a rudimentary auto-complete function
	with option (-autocomplete) that is turned off by default.
	Over time, I'm sure this function can be improved, but I
	think it works pretty well for now.

	* BWman/ComboBox.tcl: Added documentation for -autocomplete.

2003-06-05  Damon Courtney <damon@unreality.com>
	* listbox.tcl: Liberal use of list where appropriate to make
	the code safe for space-containing node names.

2003-05-23  Bob Techentin <techentin@sourceforge.net>

	**** BWIDGET 1.6.0 TAGGED ****

	* README.txt: 

2003-05-18  Jeff Hobbs  <jeffh@ActiveState.com>

	* progressbar.tcl: correctly handle progressbar being quickly
	created and deleted by deleting afters and checking var existence.

2003-05-18  Joe English  <jenglish@users.sourceforge.net>

	* widget.tcl (Widget::focusOK): Don't assume that '-editable' 
	option is always 1 or 0 for all widgets. [Bug 710658]

2003-05-14  Jeff Hobbs  <jeffh@ActiveState.com>

	* demo/tree.tcl: make the tree scrollview make sense in demo.
	[Bug 684462]

	* notebook.tcl: ensure that bd is min 1 at all times. [Bug 688227]
	Correct use of eval with list.

	* tree.tcl: correct node lsearch'ing to use -exact to allow for []
	containing nodes [Bug 628041] (decoster)

2003-05-07  Jeff Hobbs  <jeffh@ActiveState.com>

	* dynhelp.tcl (DynamicHelp::_motion_balloon): correctly listify
	after delayed _show_help callback.

2003-05-06  Jeff Hobbs  <jeffh@ActiveState.com>

	* scrollw.tcl (ScrolledWindow::setwidget): remove any existing
	widget before setting the next.

2003-05-01  Jeff Hobbs  <jeffh@ActiveState.com>

	* tree.tcl (Tree::configure, Tree::_draw_node): add a full-width
	box underneath the text and image/window that will react to the
	node binding if -selectfill is true.  It is an empty box that is
	overly wide, but it could be improved to resize on Configure to
	just the window width and replace the sel box.

2003-04-23  Jeff Hobbs  <jeffh@ActiveState.com>

	* tree.tcl: liberal use of list where appropriate to make the code
	safe for space-containing node names.
	Make use of string equal instead of !string compare.
	(Tree::_redraw_selection): correct -selectfill to include the
	image, in any, in the bbox calculation since it may be larger.

2003-04-15  Damon Courtney <damon@unreality.com>

	* listbox.tcl
	* tree.tcl: Added a #auto substitution for inserting new items
	into a tree or listbox.

	* BWman/ListBox.html
	* BWman/Tree.html: Added documentation for #auto substitution.

2003-04-14  Jeff Hobbs  <jeffh@ActiveState.com>

	* utils.tcl (BWidget::focus): add optional refocus arg
	* combobox.tcl: make droplist use solid 1-pixel relief more in
	accordance with Windows style.  Set topmost attribute on droplist.
	Add bindings that unmap the droplist if we lose focus to another
	application (where [focus] == ""), without refocusing to the entry.

2003-04-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* combobox.tcl (ComboBox::_expand): add tab expansion behavior
	when -expand tab is specified
	(ComboBox::_focus_in): autohighlight full contents only when no
	existing selection exists. [Bug #720024]

	* BWman/ComboBox.html: doc -expand none|tab

2003-03-12  Damon Courtney <damon@unreality.com>

	* listbox.tcl: Added dynamic help support to listbox items.

	* tree.tcl: Fixed a little inconsistency in the tree dynamic help.
	We don't need to save the whole path in the help array, just the
	node.

2003-02-25  Jeff Hobbs  <jeffh@ActiveState.com>

	* scrollw.tcl: add lock around grid remove scrollbar to prevent
	infinite loop in small window situations. (kienzle)

	* pkgIndex.tcl:
	* configure.in: bumped to v1.6

	* scrollw.tcl: complete rewrite of ScrolledWindow widget to
	address infinite loop scrollbar problems.  This one is much
	simpler and does not suffer the infinite loop.  There still seems
	to be an issue with shrinking smaller than one scrollbar width /
	height in size, but that's not common (nor fatal).  Addresses
	[Patch #671821, #520903] [Bug #472718, #564691]
	This may introduce new incompatabilities, but it does work as
	expected for noted bugs and in the demos.

	* widget.tcl: code cleanup
	* scrollframe.tcl: code cleanup

2003-02-24  Jeff Hobbs  <jeffh@ActiveState.com>

	* panedw.tcl (_realize): only allow _realize to be called once the
	Configure binding has triggered once. [Bug #613134]
	[Patch #63500] (decoster)

2003-02-17  Jeff Hobbs  <jeffh@ActiveState.com>

	* font.tcl: comment out the adding of default style bits for bold
	and italic.  The allows setting the font to something like
	"Courier 8", clicking B on and off and getting "Courier 8" back
	again (otherwise gave "Courier 8 normal roman").

2003-02-08  Damon Courtney <damon@unreality.com>
	* BWman/SelectColor.html
	* color.tcl:   Cleaned up some of the documentation of SelectColor
	  and made it actually work like the documentation says it does.

	* BWman/DynamicHelp.html
	* dynhelp.tcl:  Added -topbackground, -padx and -pady options to
	  allow a little more flexibility in the look-and-feel of balloons.

	  Added the ability to bind dynamic help to individual items or tags
	  on a canvas.

	* BWman/Tree.html
	* tree.tcl:  Added -padx and -deltax options to individual nodes
	  within a tree.  Each option defaults to -1, meaning to take its
	  value from the global option of the same name.

	  Added dynamic help to nodes within a tree.  Adds the following
	  options: -helptext, -helptype and -helpvar to each node.

	* BWman/BWidget.html
	* utils.tcl:  Added BWidget::badOptionString utility to return a
	  standard error string when a given option doesn't match a list.

	* BWman/Widget.html
	* widget.tcl:  Added Widget::getVariable proc to create a reference
	  to a variable relative to the given widget path.

2003-01-26  Damon Courtney <damon@unreality.com>
	* BWman/DynamicHelp.html:
	* dynhelp.tcl:  Added -state option to disable help balloons on a
	  global scale.

	* BWman/Tree.html:
	* tree.tcl: Added -crossfill option to allow the + / - bitmap to
	  be filled with a different color than the connecting node lines.
	  -linesfill is now accurate in its help entry and only adjusts
	  the foreground color of the lines between the nodes.

2003-01-24  Joe English  <jenglish@users.sourceforge.net>
	* tree.tcl (Tree::delete, Tree::_subdelete): remove all deleted
	nodes from the the selection [Bug #621178].

2003-01-17  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* labelentry.tcl: fixed -textvariable option [bug #649383]

2002-10-14  Jeff Hobbs  <jeffh@ActiveState.com>

	* pkgIndex.tcl:
	* configure.in: bump version to 1.5

	* button.tcl: remove -repeatdelay and -repeatinterval for 8.4 to
	allow Button to override them. [Bug #620103]

	* combobox.tcl: make -entrybg also control the listbox background.
	[Bug #519189] (chevreux)

	* tree.tcl (_see): change to always show left edge of requested
	item. [Patch #556077] (english)  [NOTE: also included Patch #621331 
	"Allow delete of selected Tree nodes"]

	* dynhelp.tcl: allow variable and balloon help simultaneously.
	[Patch #567982] (decoster)

	* BWman/LabelFrame.html:
	* labelframe.tcl: allow -bitmap -image and -textvariable options
	of the BWLabel component of a LabelFrame. [Patch #620753] (decoster)

	* widget.tcl (_get_tkwidget_options): withdraw toplevel if it is
	the TkResource base widget. [Patch #620754] (decoster)

	* tree.tcl (delete): correct tree deletion with selected nodes.
	[Patch #621331] (decoster)

	* progressbar.tcl (_modify): use updated idletasks instead of
	update. [Patch #622927] (decoster)

2002-09-25  Jeff Hobbs  <jeffh@ActiveState.com>

	* Makefile.in: better DESTDIR/libdir support (steffen)

2002-09-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* color.tcl (SelectColor::menu): added tkwait and update to make
	sure that the grab doesn't fail on Unix.

	* listbox.tcl: corrected multiple selectmode bindings.
	[Patch #483838, Bug #594853] (decoster)

2002-08-23  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* tree.tcl: Modified subcommand 'includes' of the method
	  'selection to properly extract its argument. ... Revamped the
	  whole subcommand to properly extract and check its arguments.

	  (create) Added Control-Button-1 bindings to allow toggling the
	  selection of a node. I will do no bindings for shift-selecting
	  and/or drag-selecting ranges. To complex for me right now.

	  Moved the code executing the -selectcommand callback to an
	  internal procedure, and added calls to that procedure to all
	  subcommands which change the selection. This fixes SF Bwidget
	  Bug #547245.

	* BWman/Tree.html: Documented the 'includes' and 'range'
	  subcommands of the method 'selection' of tree widgets.
	  Documented the node option '-selectable'. Documented that the
	  subcommands extending or setting the selection silently ignore
	  unselectable nodes. Documented new 'toggle' subcommand of method
	  'selection'. Documented option --slectcommand'. Fixed bogus
	  table html in option lists.

2002-06-04  Jeff Hobbs  <jeffh@ActiveState.com>

	**** BWIDGET 1.4.1 TAGGED ****

	* README.txt: 
	* configure.in: 
	* pkgIndex.tcl: up'ed version to 1.4.1

	* listbox.tcl: corrected use of 'end' as move index. [Bug #561391]
	* buttonbox.tcl: 
	* tree.tcl: force frame -padx/-pady to 0 to handle 8.4+ frame
	padding options. [Bug #545119]

	* scrollframe.tcl: corrected scrollregion configuration on
	Configure of frame to use full width/height of canvas when the
	canvas is larger.  This ensures that scrolling "anchors" properly
	to topleft.

	* dialog.tcl: prevent dialog from freezing on Windows with tkwait
	visibility on withdrawn toplevels. [Patch #521386] (chevreux)

	* font.tcl: reworked loadfont to not sort font names unless
	requested.  [Patch #524353] (kienzle, hobbs)

	* panedw.tcl: corrected handling of weighted panes following a
	Configure event. [Patch #513320] (decoster)

	* progressbar.tcl: Fixed display of vertical progressbar.
	[Patch #561403]

2002-05-29  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* combobox.tcl: Changed relief of popup list to ridge, for Win*
	  platforms.

2002-05-09  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* dynhelp.tcl: Accepted patch for bug 528929. Reported by
	  <bach@users.sourceforge.net>, patch also by him.

2002-04-25  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* notebook.tcl: Accepted patch for bug #532246, fixing the
	  appearance of the tabs so that text is always visible
	  completely.

2002-01-26  Pat Thoyts  <patthoyts@users.sourceforge.net>

	* utils.tcl: Modified BWidget::place to support multiple screens
	under Windows. Better support would require Tk modifications.
	* demo/tree.tcl: Fixed for starting on secondary monitor under
	windows.
	* BWMan/BWidget.html: added documentation for BWidget::place.
	
2002-01-22  Jeff Hobbs  <jeffh@ActiveState.com>

	**** BWidget 1.4.0 tagged ****

	* widget.tcl: added Color as an optional type, with _test_color
	test.  [RFE #443124].

2002-01-15  Jeff Hobbs  <jeffh@ActiveState.com>

	* BWman/ComboBox.html: removed reference to label options that
	were removed when the LabelFrame was dropped.  [Bug #477130]

	* listbox.tcl: allowed drop handler to work in empty listbox.
	[Bug #456883]

	* mainframe.tcl: correct unprotected eval calls.  [Patch #501210]
	(chevreux)

2001-12-28  Jeff Hobbs  <jeffh@ActiveState.com>

	* BWman/Dialog.html:
	* dialog.tcl: Added '-transient' and '-place' flags.
	[Patch #483838] (decoster)

	* BWman/Tree.html:
	* tree.tcl: Added a 'recursive' argument to 'Tree::opentree' and
	'Tree::closetree'. [Patch #483838] (decoster)

	* BWman/ProgressBar.html:
	* progressbar.tcl: Added new type 'nonincremental_infinite' and
	modified movement of progressbar when in 'infinite' or
	'nonincremental_infinite' mode. The 'nonincremental_infinite' can
	be used when a certain process monitored by a ProgressBar returns
	a total count and not an increment count. [Patch #483838] (decoster)

	* BWman/PanedWindow.html:
	* panedw.tcl: Added '-weights' flag with possible value 'extra' or
	'available'.  Since BWidget-1.3.1, the meaning of the '-weight'
	flag for the 'PanedWindow::add' command was changed. This made it
	difficult to create a layout where the panes occupy a certain
	amount of the screen. When using the '-weights extra' flag when
	creating a PanedWindow widget, the >=1.3.1 behavior is used: the
	weights for the different panes are only used for extra space.
	When using the '-weights available' flag, the weights for the
	different panes are used to set the size of each panes relative to
	the total available space. [Patch #483838] (decoster)

	* BWman/ListBox.html:
	* listbox.tcl: Added '-selectmode' flag and 2 possible
	select-modes: single and multiple. [Patch #483838] (decoster)

	* widget.tcl: Select element 4 (was 3) from the config-options to
	get value from optiondb. [Patch #483838] (decoster)

	* utils.tcl: added else case to place is called with location
	different from 'at' and 'center' and without a parent.
	[Patch #484123] (decoster)

	* mainframe.tcl: added options -menubarfont, -menuentryfont and
	-statusbarfont at creation time of the widget as well as
	subsequent configures. [Patch #479935] (chevreux)

	* listbox.tcl: added multipleinsert command to allow faster
	inserts of multiple items. [Patch #458446] (chevreux)
	* widget.tcl: added Widget::copyinit. [Patch #458446] (chevreux)

	* BWman/NoteBook.html:
	* notebook.tcl: added options for enhanced tab shape in notebooks.
	[Patch #402466] (haneef)

	* configure.in:
	* pkgIndex.tcl:
	* README.txt: bumped version to 1.4.0 (not released)

	* mainframe.tcl (_create_menubar): start tagstate initially on.
	[Patch #470273] (chevreux)
	(_parse_accelerator): improve F* function key accelerator support.
	[Patch #444172] (venski)

2001-10-14  Jeff Hobbs  <jeffh@ActiveState.com>

	* pagesmgr.tcl: reverted fix of 2001-10-11 - it was bogus.

2001-10-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* pagesmgr.tcl: allowed the ability to specify page by name,
	not just number.

2001-09-11  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* notebook.tcl: Removed 'Canvas' from the list of bindtags for the
	  internal canvas to prevent interference from application
	  specific bindings with our special widget. [459033].

2001-09-06  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* passwddlg.tcl: Accepted change by Bastien Chevreux
	  <bach@users.sourceforge.net> adding a -logineditable option to
	  the password dialog. [436340].

2001-09-05  Andreas Kupries  <andreas_kupries@users.sourceforge.net>

	* panedw.tcl: Added option -activator to allow user to choose sash
	  activator. Reduced minimum allowed sash width. [442474]. Request
	  made by Bastien Chevreux <bach@users.sourceforge.net>.

	* label.tcl: Corrected typo in BWlabel::configure [454505], report
	  and fix by Bastien Chevreux <bach@users.sourceforge.net>.

	* arrow.tcl: Changed containing frame to be more invisible
	  (borderwidth 0). Fixes [458301], by Georgios Petasis
	  <petasis@users.sourceforge.net>.

2001-08-08  Andreas Kupries <andreas_kupries@users.sourceforge.net>

	* tree.tcl (Tree::_keynav): Added code to call the open and close
	  commands when the open-status of a node is toggled with the
	  space bar. Bug [449284].

	* color.tcl: Added the missing definition of the main
	  'SelectColor' procedure. This prevented users from creating
	  these widgets in the documented way. Bug [449276].

2001-06-21  eric melski  <ericm@ajubasolutions.com>

	* tree.tcl: Corrected keyboard navigation so that open/close
	commands are invoked when right/left arrows are used to open/close
	nodes, patch from [Bug #435097].  Also corrected keyboard
	navigation on right arrow press; previously only opened closed
	nodes that had children, but should always open nodes, regardless
	of whether it has children.

2001-06-11  Jeff Hobbs  <jeffh@ActiveState.com>

	* pkgIndex.tcl: bumped version to 1.3.1 and added Tk 8.1.1 package
	require as Tcl 8.1.1 is needed in certain core areas for the new
	string methods.

	* mainframe.tcl: corrected state interpretation.  It doesn't do
	exact argument matching, but it is consistent with the rest of
	BWidget.  [Bug #224476]

	* demo/demo.tcl: fixed demo script to run when called from
	another directory

	* messagedlg.tcl: corrected winfo exists call

	* listbox.tcl: fixed string compare call

	* combobox.tcl: added package require Tk 8.3.

	* passwddlg.tcl: 
	* xpm2image.tcl: 
	* mainframe.tcl: 
	* panedw.tcl: 
	* utils.tcl: 
	* entry.tcl: 
	* dynhelp.tcl: 
	* dragsite.tcl: 
	* color.tcl: added braces to expr where appropriate

2000-10-31  Dan Kuchler  <kuchler@ajubasolutions.com>

        * combobox.tcl: Added the '-exact' option to the 'lsearch'
        commands in the combobox code so that the correct index
        of items will be returned even when there are glob/regexp
        characters.

2000-10-10  Dan Kuchler  <kuchler@ajubasolutions.com>

        * dynhelp.tcl: Added the '-screen' option to the toplevel that
        is created to display the help text to fix a bug reported by
        Tupone Alfredo.

2000-10-01  Eric Melski  <ericm@ajubasolutions.com>

	* notebook.tcl: Fixed typo in _draw_page that incorrectly placed
	images on tabs.

2000-09-17  Eric Melski  <ericm@ajubasolutions.com>

	* widget.tcl (_test_boolean): Altered to return strictly 0 or 1
	(for false and true, respectively), rather than allowing the
	string booleans (false, true, off, on, etc).

2000-09-07  Sven Delmas  <sven@scriptics.com>

	* mainframe.tcl: Fixed the typo of Alt (Atl) as reported in bug #
	6079.

2000-09-05  Eric Melski  <ericm@ajubasolutions.com>

	* label.tcl: Corrected bindtags for BWidgets Label components:
	primary component widget now includes the megawidget pathname in
	its bindtags list, so that bindings on the megawidget pathname are
	applied properly.

2000-08-10  Eric Melski  <ericm@ajubasolutions.com>

	* widget.tcl: Corrected a problem caused by the destruction of the
	special .#BWidget* widgets, which are used by BWidgets for some
	option value validations; formerly, if these were destroyed, it
	could confuse the BWidgets system's internal state, and creating
	BWidgets after destroying these helper widgets would throw an error.

2000-06-14  Dan Kuchler  <kuchler@scriptics.com>

	* dialog.tcl
	* dropsite.tcl
	* dynhelp.tcl
	* scrollview.tcl: Replaced several catch {unset varname} calls with
	if {[info exists varname]} {unset varname}.  This avoids using the
	catch, and also prevents the ::errorInfo corruption that was happening
	in BWidgets.

2000-05-14  Dan Kuchler  <kuchler@scriptics.com>

	* tree.tcl: Fixed a typing error in the Tree::find procedure.
	The procedure wouldn't work because there was a 'llengh' where there
	should have been a 'llength'.

2000-05-08  Dan Kuchler  <kuchler@scriptics.com>

	* titleframe.tcl: Added a '-state' flag that is associated to the
	state of the label.  Now that labels can be disabled (in 8.3 and
	beyond) this allows for the titleframe to have a disabled appearence.

2000-05-02  Eric Melski  <ericm@scriptics.com>

	* tree.tcl: Did some fancy focus footwork [Bug: 4491].  Now you
	can do this: "Tree .t ; bind .t <Button-1> foo", and it will do
	the right thing.  This will enable the use of proper
	focus-on-mouse-click bindings for trees, which in turn will fix
	the focus problem described in 4491.  In addition, I added a
	binding to the canvas widget in the tree that redirects focus when
	it leaves the canvas and goes to the frame, just in case.
	
	* dialog.tcl: Added a -geometry option, to allow the specification
	of geometry for the dialog.  No particular care is taken to
	validate the geometry string, so if it is bogus, you lose. [RFE:
	5188].

2000-04-27  Eric Melski  <ericm@scriptics.com>

	* entry.tcl: Added smarts to handle Copy for non-editable entries
	(it should be allowed, but was not previously) [Bug: 3755].

	* notebook.tcl: Small tweaks for placement of images on tabs.

	* combobox.tcl: Added code to ensure that non-editable (but
	enabled) comboboxes could still be tabbed in to.

2000-04-26  Dan Kuchler  <kuchler@scriptics.com>

	* button.tcl: Fixed the bindings that get setup on buttons with
	an underline specified to be case insensitive (i.e  if 'A' or 'a'
	was the underline character, Alt-A and Alt-a would both be bound
	to the button.

2000-03-29  Sven Delmas  <sven@scriptics.com>

	* tree.tcl:  Added protection for the left arrow key click in case
	we are already at the root node. This used to throw a Tcl error
	(fixes bug # 4619).

2000-03-20  Eric Melski  <ericm@scriptics.com>

	* progressbar.tcl: (configure) Added test for change to -maximum
	value, so that bar is redrawn if maximum changes. [Bug: 4399].

	* BWman/SpinBox.html: Removed references to -label* options.

	* demo/select.tcl: Removed use of -label* options on ComboBox and
	SpinBox. [Bug: 4394].

2000-03-14  Eric Melski  <ericm@scriptics.com>

	* button.tcl: (configure) replaced several hasChanged calls with
	one hasChangedX call.

	* dynhelp.tcl: (sethelp) replaced several hasChanged calls with
	one hasChangedX call.

	* entry.tcl: Replaced stack of hasChanged calls with one
	hasChangedX (in configure); replaced a couple cget's with
	getMegawidgetOption's.

	* spinbox.tcl: Updated _test_options to use setMegawidgetOption,
	and to only do that if it has to, instead of always doing it.

	* tree.tcl: Worked on itemcget; instead of upvar'ing the
	one-time-use variable, just refer to it directly.

	* widget.tcl: One problem with [set
	${class}::${path}:opt($option)] -- if path contains "foo(foo)",
	the command will choke.  Removed that particular
	micro-optimization.  Added setMegawidgetOption to compliment
	getMegawidgetOption; extended hasChangedX to accept multiple
	options to check.  This allows us to compress stacks of hasChanged
	calls into a single call (so there's a single function call, and a
	single upvar...).

2000-03-13  Eric Melski  <ericm@scriptics.com>

	* combobox.tcl: Tweaked bg/background options so that button
	didn't pick up entry background.

	* widget.tcl: Removed dead code; micro-optimizations to initFromODB.

	* tree.tcl: Added option for default -fill of tree nodes on windows.

	* notebook.tcl: Removed commented code.

	* button.tcl: 
	* tree.tcl: 
	* spinbox.tcl: 
	* entry.tcl: 
	* dropsite.tcl: 
	* dragsite.tcl: 
	* arrow.tcl: Replaced selected cget/getoption calls with
	getMegawidgetOption calls.

	* combobox.tcl: Removed LabelFrame from ComboBox (30% faster).

	* widget.tcl: Added getMegawidgetOption function, which allows
	direct access to megawidget-specific options (those that do not
	map to a component widget option).  This is dangerous, because it
	bypasses some checks, and it will only work with options that are
	specific to the megawidget.  However, it is much faster, and
	enables some functions (like visiblenodes) to be much faster.

	* tree.tcl: Reworked visiblenodes function to do a tree walk to
	find visible nodes.  This is faster and more correct than the
	previous implementation, which queried all the nodes in the tree
	for their open bit.
	

2000-03-10  Eric Melski  <ericm@scriptics.com>

	* widget.tcl: Replaced an upvar with a direct reference to the
	variable in initFromODB.

	* dynhelp.tcl: Changed sethelp function to use new hasChangedX
	function instead of hasChanged, which avoids an unneeded upvar,
	for a little better speed.

	* button.tcl: Changed to parseArgs/initFromODB format for a small
	(25%) speedup in creation time.

2000-03-10  Sven Delmas  <sven@scriptics.com>

	* tree.tcl: Changed the allnodes procedure to visiblenodes, and
	also the mechanism of retrieving those nodes. This took care of
	the previously required update.

2000-03-09  Eric Melski  <ericm@scriptics.com>

	* entry.tcl: Added code to re-sync the -text option with the
	contents of the entry widget before doing configuration; this
	fixes [Bug: 4304].

2000-03-09  Sven Delmas  <sven@scriptics.com>

	* tree.tcl: Disabled the update before the find withtag in the
	allnodes procedure. The nodes are apparently created delayed, so
	before this procedure is called, the program has to do an
	update. I don't do this in the procedure anymore, because it
	caused multiple updates, making the app slower.

2000-03-08  Sven Delmas  <sven@scriptics.com>

	* tree.tcl: The new allnodes procedure was not handling the
	"current" tag correctly. This is now stripped of.

2000-03-07  Eric Melski  <ericm@scriptics.com>

	* button.tcl: Added check for -state flag, to initialize it properly.

	* entry.tcl: Changed to parseArgs/initFromODB format; added check
	for -text flag to initialize it properly.

	* labelentry.tcl: Changed to use parseArgs/initFromODB format.

2000-03-03  Eric Melski  <ericm@scriptics.com>

	* spinbox.tcl: Added a call in setvalue to scan the current value into
	a float to trim out any 0 padding on the number (otherwise the zero's 
	make it look like octal to tcl, which chokes on numbers > 8)

2000-03-07  Sven Delmas  <sven@scriptics.com>

	* passwddlg.tcl: Reenabled the <Return> binding to activate the ok
	button. 

	* dragsite.tcl: I added an extra protection into the _begin_drag
	procedure to guard against a motion event that (sometimes) arrives
	before the press event. This fixes bug # 4324.

2000-03-03  Eric Melski  <ericm@scriptics.com>

	* spinbox.tcl: Removed LabelFrame from SpinBox (BACKWARDS
	INCOMPATIBLE) to speed creation; updated configure proc to use
	hasChangedX instead of hasChanged, as it didn't really need the
	values of the options it was checking.

2000-03-01  Eric Melski  <ericm@scriptics.com>

	* spinbox.tcl: Changed bindings to be on class SpinBox instead of
	BwSpinBox, and added class SpinBoxEntry to the bindtags of the
	SpinBox entry component.

	* configure.in:
	* pkgIndex.tcl: Bumped version to 1.3.0.

	* tree.tcl: Changed focus redirect to use {after idle} to avoid
	focus loops.

	* label.tcl: Added -bd 0 -highlight... etc to wrapper frame; moved
	class bindings to the frame instead of the component label.

	* utils.tcl: Added helper function BWidget::refocus, to handle
	focus redirection calls.

	* spinbox.tcl: Changed focus redirect to use {after idle} to avoid
	focus loops.

	* combobox.tcl: Changed init to parseArgs/initFromODB style;
	changed focus redirect to use {after idle} to avoid focus loops.

2000-02-29  Eric Melski  <ericm@scriptics.com>

	* widget.tcl: Added bits to handle
	$path#subclass_that_inherits_from_other_bw_class megawidget names.

	* passwddlg.tcl:
	* progressdlg.tcl: 
	* progressbar.tcl: Changed init to parseArgs/initFromODB style.

	* pkgIndex.tcl: Changed Label -> BWLabel

	* messagedlg.tcl: Changed initialization to parseArgs/initFromODB
	style.  Changed to use tk_messageBox on UNIX.
	
	* labelframe.tcl: Updated to use BWLabel instead of Label.

	* labelentry.tcl: Added -class LabelEntry to widget.

	* label.tcl: Changed class name to BWLabel (to avoid option db
	clashes with tk labels), changed initialization	to
	parseArgs/initFromODB style.

	* init.tcl: dropped obsolete Tree option from init.

	* dialog.tcl: changed initialization to parseArgs/initFromODB style.

	* notebook.tcl: Added -bd 0 -highlightthickness 0 -relief flat to
	the notebook container frame so geometries are correct.

	* entry.tcl: Fixed a conflict with configuring the Entry -text and
	textvariables.

	* dialog.tcl: added a -class option to the dialog, to allow the
	class of the dialog to be set (this enables proper optiondb use
	for things like the PasswdDlg).

2000-02-28  Eric Melski  <ericm@scriptics.com>

	* widget.tcl: Added Widget::varForOption function, which returns a 
	variable name that can be used to trace changes to an option for a
	particular megawidget (such as the -values option of a combobox).
	
	* entry.tcl: Made cget -text a little more efficient by
	shortcircuiting in that case.

	* combobox.tcl: Fixed bug #4248 by making the listbox use a
	-listvariable instead of trying to micromanage the listbox contents.

	* tests/entry.test: tests for the Entry widget.

	* widget.tcl: minor code cleanup.

	* tree.tcl: Was not getting proper default bg color on Windows,
	and keyboard navigation was goofy because of internal structure
	changes.

	* entry.tcl: Fixed an issue with initial foreground color not
	being picked up correctly.

2000-02-28  Sven Delmas  <sven@scriptics.com>

	* tree.tcl: Added a procedure called "allnodes" to retrieve the
	names of all currently defined treenodes. Apparently the internal
	widget structure of tree was changed recently. I adjusted the
	"allnodes" procedure to that.

2000-02-25  Eric Melski  <ericm@scriptics.com>

	* combobox.tcl: Fixed a problem with non-editable comboboxes and
	selecting values.

	* arrow.tcl: 
	Fixed a problem with the invoke method (doing one too many winfo
	parents in some cases)

	* button.tcl: 
	* buttonbox.tcl: 
	* combobox.tcl: 
	* dialog.tcl: 
	* dynhelp.tcl: 
	* entry.tcl: (also fixed validation)
	* label.tcl: 
	* labelframe.tcl: 
	* listbox.tcl: 
	* mainframe.tcl: 
	* notebook.tcl: 
	* pagesmgr.tcl: 
	* panedw.tcl: 
	* progressbar.tcl: 
	* scrollview.tcl: 
	* scrollw.tcl: 
	* separator.tcl: 
	* spinbox.tcl: 
	* titleframe.tcl: 
	* tree.tcl: Updated to new megawidget architecture.

	* widget.tcl: Changed internal architecture.  When possible,
	megawidget options are stored in component widgets instead of in
	an intermediary array.  Also, made use of option database to make
	megawidget creation more efficient.

2000-02-24  Eric Melski  <ericm@scriptics.com>

	* LICENSE.txt: Removed LGPL license; added Tcl-license terms.

2000-02-23  Eric Melski  <ericm@scriptics.com>

	* widget.tcl: Replaced _test_boolean function with a more efficient
	implementation.

2000-02-18  Eric Melski  <ericm@scriptics.com>

	* images/target.xbm: Placeholder for actual icon.

	* color.tcl: Change env(BWIDGET_LIBRARY) to ::BWIDGET::LIBRARY;
	changed proc "dialogue" to "dialog"

	* pkgIndex.tcl: Updated function spec for color.tcl.

	* widget.tcl: Various minor speed tweaks; added a reverse mapping
	from component widget options -> mega-widget options so that
	subcget can be faster.

	* entry.tcl: 
	* dropsite.tcl: 
	* dragsite.tcl: 
	* arrow.tcl: Tcl list'd the specs for Widget::declare calls.

	* combobox.tcl: Removed extraneous ListBox::use call.
	

2000-02-17  Eric Melski  <ericm@scriptics.com>

	* notebook.tcl: Added an extra check to move the leftmost tab a
	touch to the right when it is not selected (again, to make the
	tabs more Windows-like).  Also replaced redundant [string equal]
	checks with a stored pre-check (ie, set foo [string equal ...]).

2000-02-16  Eric Melski  <ericm@scriptics.com>

	* notebook.tcl: Changed appearance of tabs; leftmost tab is now 
	flush with the left of the notebook, and the tabs look more
	Windows-like.

2000-02-16  Sven Delmas  <sven@scriptics.com>

	* dialog.tcl: Added a new parameter to the draw procedure that
	allows me to pass in the desired geometry for the window. This was
	needed to support tracking of dialog window geometries.

	* tree.tcl: Changed the <KeyPress-space> binding to use "+", so it
	will not overwrite existing bindings (if there are any). Also
	added some extra protection in the keynav procedure against the
	user typing <Left> on a root node (this used to cause a stack
	trace).

2000-02-11  Eric Melski  <ericm@scriptics.com>

	* tree.tcl: Integrated changes from Eric Boudaillier:
	[itemconfigure -open ...]
	    optimized to only call redraw_idle 3 if node has subnodes.
	_cross_event:
	    itemconfigure -open called before -opencmd/closecmd; no more
	    call to _redraw_idle (handled by other procedures)
	_over_cmd:
	    allow position {root 0} when tree is empty
	new [find] command:  
	    [find @x,y ?confine?]
	    	    if confine is "confine" returns the node at window
		    coordinate x,y (x,y must be inside the bbox of the
		    node) else returns the node found on the line (in
		    pixel) pixel y
	    [find line]
	            returns the node on the line $line (in -deltay coords)
	new [line] command:
	    [line node]
	            returns the line where node is drawn
	-selectfill option added:
	    if true, selection is draw on full width of tree (instead of
	    just highlighting the bbox of the selected nodes)
	
	* combobox.tcl: Integrated changes from Eric Boudaillier:
	internal widget restructuring.

	* tree.tcl: Added "range" subcommand to selection.  Given two
	nodes, node1 and node2, it will set the selection to the visible
	nodes between (and including) node1 and node2.  If node1 or node2
	is not visible, it will find the first visible ancestor of the
	node and use that as the start/end point instead.

	* listbox.tcl: Integrated changes from Eric Boudaillier:
	_over_cmd: allow position 0 when listbox is empty
	find command, similar to tree find command.
	
	* spinbox.tcl: Integrated changes from Eric Boudaillier:
	cosmetic changes.
	
	* color.tcl: Integrated changes from Eric Boudaillier:
	split widget into two commands: SelectColor::menu and
	SelectColor::dialog.

	* progressbar.tcl: Integrated changes from Eric Boudaillier:
	added -idle option to prevent call to update in case where task is
	done in idle (ie, fileevents)

	* scrollview.tcl: Integrated changes from Eric Boudaillier:
	bindings changed.

	* scrollw.tcl: Integrated changes from Eric Boudaillier:
	-managed option: if true, scrollbar are managed during creation,
	so their size are included in the requested size of the
	ScrolledWindow.  If false, they are not.
	-sides option: specifies the side of the scrollbar.
	-size option: specifies size of scrollbar.
	-ipad option: specifies pad between scrollbar and scrolled widget.

	* mainframe.tcl: Integrated changes from Eric Boudaillier: support
	for function keys in accelerators, support for no modifier in
	accelerators.

	* notebook.tcl: Integrated changes from Eric Boudaillier:
	-internalborderwidth (-ibd) option specifies pad around pages;
	-foreground, -background, -activeforeground, -activebackground,
	-disabledforeground options for each tab.
	Code cleanup.

1999-12-23  Sven Delmas  <sven@scriptics.com>

	* scrollw.tcl: Added "update idletask" to scrollbar update to
	prevent loss of update events.

1999-12-14  Sven Delmas  <sven@scriptics.com>

	* combobox.tcl: When the selected item is changed, the selection
	is now set to the entire string.

1999-12-13  Eric Melski  <ericm@scriptics.com>

	* buttonbox.tcl: Added a getbuttonstate function, which retrieves 
	the value of a tag used on a button in the buttonbox.

1999-12-08  Eric Melski  <ericm@scriptics.com>

	* combobox.tcl: Removed code that cleared entry selection on focus out 
	events, as this crippled exportselection.

1999-10-29  Eric Melski  <ericm@scriptics.com>

	* buttonbox.tcl: Added a gettags function, which allows the user
	to query the tags that are used on buttons in the buttonbox.

1999-10-29  Eric Melski  <ericm@scriptics.com>

	* font.tcl: Added one new flag: -querysystem.  This lets the user 
	control whether the font selector queries the system 
	(via font families) for the list of fonts, or if it uses a preset 
	list of fonts (which is much faster and less likely to crash some 
	systems).

1999-10-25  Eric Melski  <ericm@scriptics.com>

	* font.tcl: Added support for two new flags: -families and -styles; 
	-families allows you to specify one of all, fixed, or variable, to
	limit the choice of fonts to those fonts; -styles allows you to
	specify a list of styles that can be set with the widget (ie,
	bold, italic, etc).

1999-10-22  Eric Melski  <ericm@scriptics.com>

	* tree.tcl: Fixed some problems with keyboard traversal.  Added
	support for left/right arrows a la MS Explorer.
	Added support for keyboard-based scrolling.
	
1999-10-21  Sven Delmas  <sven@scriptics.com>

	* combobox.tcl: Added support for keyboard traversal.  The widget
	will now tab in even when it is not editable.  Also the entry
	widget content will be selected when the user tabs in. The key
	bindings now allow a traversal of the list (<Down> brings up the
	list). The arrow button no longer switches to an up button, but
	instead changes relief. The button is now more Windows NT like
	(for Windows NT).  Changed keyboard bindings:  down/up now
	display/hide the listbox; control-{up|down|prev|next} move through
	the options without displaying the listbox.
	
1999-10-21  Eric Melski  <ericm@scriptics.com>

	* tree.tcl: Added a -selectable option to tree nodes, which
	controls whether or not a given node is selectable (duh).  This
	works with the new -selectcommand option for the tree, and with
	keyboard traversal (also new).  Now, whenever the tree gets a
	"selection set", it calls the given -selectcommand with the name
	of the tree and the list of selected nodes, which makes it easier
	to just drop in place and use.

1999-10-15  Eric Melski  <ericm@scriptics.com>

	* panedw.tcl: Added a -class PanedWindow option to the main frame 
	(the megawidget) of the paned window.

1999-10-15  Eric Melski  <ericm@scriptics.com>

	* dialog.tcl: Added an overrideredirect option to Dialog::draw, which
	allows the user to control the overrideredirect state of the dialog.

1999-09-19  Eric Melski  <ericm@scriptics.com>

	* mainframe.tcl:  Fixed _destroy to unset ALL state variables, so that
	when a new MainFrame of the same name as an old one is created, it
	doesn't pick up residual state from the old one.

1999-09-17  Eric Melski  <ericm@scriptics.com

	* mainframe.tcl: Modified menu creation/setmenustate functions to
	support a new model of menustate.  Instead of enabling/disabling a
	menu item whenever any one of its tags changes state, now it only
	enables menu items if all of its tags are set.  This makes it
	really easy to, say, only enable the "New Action" entry if both a
	project is open and an element is selected.

	* buttonbox.tcl: Added tagging mechanism to buttonbox.  When using
	$bbox add, the first parameter is a list of tags for the button.  Then
	use $bbox setbuttonstate to change the state of a tag.

1999-09-16  Eric Melski  <ericm@scriptics.com>

	* notebook.tcl: Added some (non-functional) code for doing
	tab-notebooks with the tabs on the bottom.

Added lib/BWidget/Makefile.in.






















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# Makefile.in --
#
#	This file is a Makefile for the BLE executable.
#
# Copyright (c) 1999-2000 Ajuba Solutions.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: Makefile.in,v 1.8 2004/01/28 16:51:08 rmax Exp $


BWIDGET_SOURCES = \
	arrow.tcl \
	bitmap.tcl \
	button.tcl \
	buttonbox.tcl \
	color.tcl \
	combobox.tcl \
	dialog.tcl \
	dragsite.tcl \
	dropsite.tcl \
	dynhelp.tcl \
	entry.tcl \
	font.tcl \
	init.tcl \
	label.tcl \
	labelentry.tcl \
	labelframe.tcl \
	listbox.tcl \
	mainframe.tcl \
	messagedlg.tcl \
	notebook.tcl \
	pagesmgr.tcl \
	panedw.tcl \
	passwddlg.tcl \
	progressbar.tcl \
	progressdlg.tcl \
	scrollframe.tcl \
	scrollview.tcl \
	scrollw.tcl \
	separator.tcl \
	spinbox.tcl \
	titleframe.tcl \
	tree.tcl \
	utils.tcl \
	widget.tcl \
	xpm2image.tcl

PKGINDEX_TCL = \
	$(srcdir)/pkgIndex.tcl

#STARTUP_SCRIPT = src/bwidget.tcl

#========================================================================
# Executable name for creating a wrapped application
# We don't currently build a wrapped bwidgets.
#========================================================================

#BWIDGET	= bwidget$(EXEEXT)

#========================================================================
# Nothing of the variables below this line need to be changed.
#========================================================================

SHELL = @SHELL@
EXEEXT	= @EXEEXT@

DESTDIR =

srcdir = @srcdir@
top_srcdir = @top_srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@

libdir = @libdir@
pkglibdir = $(libdir)/@PACKAGE@@VERSION@

top_builddir = .

INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@

PACKAGE = @PACKAGE@
VERSION = @VERSION@
PROWRAP = @PROWRAP@
AUTOCONF = autoconf
CYGPATH=@CYGPATH@
CONFIGDIR = @CONFIGDIR@
mkinstalldirs = $(SHELL) $(CONFIGDIR)/mkinstalldirs

#========================================================================
# TEA TARGETS.  Please note that the "libraries:" target refers to platform
# independent files, and the "binaries:" target inclues executable programs and
# platform-dependent libraries.  Modify these targets so that they install
# the various pieces of your package.  The make and install rules
# for the BINARIES that you specified above have already been done.
#========================================================================

all: binaries libraries doc

binaries:

libraries:

doc:

install: all install-binaries install-libraries install-doc

test:

depend:

install-binaries:

install-libraries:
	$(mkinstalldirs) $(DESTDIR)$(pkglibdir)
	@echo "Installing script files in $(DESTDIR)$(pkglibdir)"
	@for i in $(BWIDGET_SOURCES) ; do \
	    $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(pkglibdir) ; \
	done;
	@echo "Installing language files in $(DESTDIR)$(pkglibdir)/lang"
	$(mkinstalldirs) $(DESTDIR)$(pkglibdir)/lang
	@for i in $(srcdir)/lang/*.rc ; do \
	    $(INSTALL_DATA) $$i $(DESTDIR)$(pkglibdir)/lang ; \
	done;
	@echo "Installing image files in $(DESTDIR)$(pkglibdir)/images"
	$(mkinstalldirs) $(DESTDIR)$(pkglibdir)/images
	@for i in $(srcdir)/images/*.gif $(srcdir)/images/*.xbm ; do \
	    $(INSTALL_DATA) $$i $(DESTDIR)$(pkglibdir)/images ; \
	done;
	$(INSTALL_DATA) $(PKGINDEX_TCL) $(DESTDIR)$(pkglibdir)

install-doc:
	$(mkinstalldirs) $(DESTDIR)$(pkglibdir)/htmldoc
	@echo "Installing html documentation in $(DESTDIR)$(pkglibdir)/htmldoc"
	@for i in $(srcdir)/BWman/*.html ; do \
	    $(INSTALL_DATA) $$i $(DESTDIR)$(pkglibdir)/htmldoc ; \
	done;

clean:  
	-test -z "$(BINARIES)" || rm -f $(BINARIES)
	-rm -f *.o core *.core
	-rm -f *.$(OBJEXT)
	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)

distclean: clean
	-rm -f *.tab.c
	-rm -f Makefile $(CONFIG_CLEAN_FILES)
	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
	-rm -f config.status

Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
	cd $(top_builddir) \
	  && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status

#config.status: $(srcdir)/configure
#	$(SHELL) ./config.status --recheck

#$(srcdir)/configure: $(srcdir)/configure.in
#	cd $(srcdir) && $(AUTOCONF) -l $(srcdir)/../../../sampleextension

.PHONY: all binaries clean depend distclean doc install installdirs \
libraries test

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
Added lib/BWidget/arrow.tcl.




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
# ------------------------------------------------------------------------------
#  arrow.tcl
#  This file is part of Unifix BWidget Toolkit
# ------------------------------------------------------------------------------
#  Index of commands:
#   Public commands
#     - ArrowButton::create
#     - ArrowButton::configure
#     - ArrowButton::cget
#     - ArrowButton::invoke
#   Private commands (redraw commands)
#     - ArrowButton::_redraw
#     - ArrowButton::_redraw_state
#     - ArrowButton::_redraw_relief
#     - ArrowButton::_redraw_whole
#   Private commands (event bindings)
#     - ArrowButton::_destroy
#     - ArrowButton::_enter
#     - ArrowButton::_leave
#     - ArrowButton::_press
#     - ArrowButton::_release
#     - ArrowButton::_repeat
# ------------------------------------------------------------------------------

namespace eval ArrowButton {
    Widget::define ArrowButton arrow DynamicHelp

    Widget::tkinclude ArrowButton button .c \
        include {
            -borderwidth -bd -relief -highlightbackground
            -highlightcolor -highlightthickness -takefocus
        } initialize {
            -relief raised -borderwidth 2 -highlightthickness 1
        }

    Widget::declare ArrowButton {
        {-type               Enum       button  0 {arrow button}}
        {-dir                Enum       top     0 {top bottom left right}}
        {-width              Int        15	0 "%d >= 0"}
        {-height             Int        15	0 "%d >= 0"}
        {-ipadx              Int        0	0 "%d >= 0"}
        {-ipady              Int        0	0 "%d >= 0"}
        {-clean              Int        2	0 "%d >= 0 && %d <= 2"}
        {-activebackground   Color      "SystemButtonFace"	0}
        {-activeforeground   Color      "SystemButtonText"	0}
        {-disabledforeground Color      "SystemDisabledText"	0}
        {-background         Color      "SystemButtonFace"	0}
        {-foreground         Color      "SystemButtonText"	0}
        {-state              Enum       "normal" 0 {active disabled normal}}
        {-troughcolor        Color      "SystemScrollbar"	0}
        {-arrowborderwidth   Int        1	0 "%d >= 0 && %d <= 2"}
        {-arrowrelief        Enum       raised	0 {raised sunken}}
        {-command            String     ""	0}
        {-armcommand         String     ""	0}
        {-disarmcommand      String     ""	0}
        {-repeatdelay        Int        0	0 "%d >= 0"}
        {-repeatinterval     Int        0	0 "%d >= 0"}

        {-fg                 Synonym    -foreground}
        {-bg                 Synonym    -background}
        {-arrowbd            Synonym    -arrowborderwidth}
    }
    
    DynamicHelp::include ArrowButton balloon

    bind BwArrowButton  <Destroy>   [list ArrowButton::_destroy %W]
    bind BwArrowButton  <Configure> [list ArrowButton::_redraw_whole %W %w %h]

    bind BwArrowButtonC <Enter>           [list ArrowButton::_enter %W]
    bind BwArrowButtonC <Leave>           [list ArrowButton::_leave %W]
    bind BwArrowButtonC <ButtonPress-1>   [list ArrowButton::_press %W]
    bind BwArrowButtonC <ButtonRelease-1> [list ArrowButton::_release %W]
    bind BwArrowButtonC <Key-space>       {ArrowButton::invoke %W; break}
    bind BwArrowButtonC <Return>          {ArrowButton::invoke %W; break}

    variable _grab
    variable _moved

    array set _grab {current "" pressed "" oldstate "" oldrelief ""}
}


# -----------------------------------------------------------------------------
#  Command ArrowButton::create
# -----------------------------------------------------------------------------
proc ArrowButton::create { path args } {
    Widget::initArgs ArrowButton $args opts

    # Create the class frame (so we can do the option db queries)
    frame $path -class ArrowButton -borderwidth 0 -highlightthickness 0 
    Widget::initFromODB ArrowButton $path $opts(ArrowButton)

    # Create the canvas with the initial options
    eval [list canvas $path.c] $opts(.c)

    # Compute the width and height of the canvas from the width/height
    # of the ArrowButton and the borderwidth/hightlightthickness.
    set w   [Widget::getoption $path -width]
    set h   [Widget::getoption $path -height]
    set bd  [Widget::cget $path -borderwidth]
    set ht  [Widget::cget $path -highlightthickness]
    set pad [expr {2*($bd+$ht)}]

    $path.c configure -width [expr {$w-$pad}] -height [expr {$h-$pad}]
    bindtags $path   [list $path BwArrowButton [winfo toplevel $path] all]
    bindtags $path.c [list $path.c BwArrowButtonC [winfo toplevel $path.c] all]
    pack $path.c -expand yes -fill both

    DynamicHelp::sethelp $path $path.c 1

    set ::ArrowButton::_moved($path) 0

    return [Widget::create ArrowButton $path]
}


# -----------------------------------------------------------------------------
#  Command ArrowButton::configure
# -----------------------------------------------------------------------------
proc ArrowButton::configure { path args } {
    set res [Widget::configure $path $args]

    set ch1 [expr {[Widget::hasChanged $path -width  w] |
                   [Widget::hasChanged $path -height h] |
                   [Widget::hasChanged $path -borderwidth bd] |
                   [Widget::hasChanged $path -highlightthickness ht]}]
    set ch2 [expr {[Widget::hasChanged $path -type    val] |
                   [Widget::hasChanged $path -ipadx   val] |
                   [Widget::hasChanged $path -ipady   val] |
                   [Widget::hasChanged $path -arrowbd val] |
                   [Widget::hasChanged $path -clean   val] |
                   [Widget::hasChanged $path -dir     val]}]

    if { $ch1 } {
        set pad [expr {2*($bd+$ht)}]
        $path.c configure \
            -width [expr {$w-$pad}] -height [expr {$h-$pad}] \
            -borderwidth $bd -highlightthickness $ht
	set ch2 1
    }
    if { $ch2 } {
        _redraw_whole $path [winfo width $path] [winfo height $path]
    } else {
        _redraw_relief $path
        _redraw_state $path
    }
    DynamicHelp::sethelp $path $path.c

    return $res
}


# -----------------------------------------------------------------------------
#  Command ArrowButton::cget
# -----------------------------------------------------------------------------
proc ArrowButton::cget { path option } {
    return [Widget::cget $path $option]
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::invoke
# ------------------------------------------------------------------------------
proc ArrowButton::invoke { path } {
    if { ![string equal [winfo class $path] "ArrowButton"] } {
	set path [winfo parent $path]
    }
    if { ![string equal [Widget::getoption $path -state] "disabled"] } {
        set oldstate [Widget::getoption $path -state]
        if { [string equal [Widget::getoption $path -type] "button"] } {
            set oldrelief [Widget::cget $path -relief]
            configure $path -state active -relief sunken
        } else {
            set oldrelief [Widget::getoption $path -arrowrelief]
            configure $path -state active -arrowrelief sunken
        }
	update idletasks
        if {[llength [set cmd [Widget::getoption $path -armcommand]]]} {
            uplevel \#0 $cmd
        }
	after 10
        if { [string equal [Widget::getoption $path -type] "button"] } {
            configure $path -state $oldstate -relief $oldrelief
        } else {
            configure $path -state $oldstate -arrowrelief $oldrelief
        }
        if {[llength [set cmd [Widget::getoption $path -disarmcommand]]]} {
            uplevel \#0 $cmd
        }
        if {[llength [set cmd [Widget::getoption $path -command]]]} {
            uplevel \#0 $cmd
        }
    }
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::_redraw
# ------------------------------------------------------------------------------
proc ArrowButton::_redraw { path width height } {
    variable _moved

    set _moved($path) 0
    set type  [Widget::getoption $path -type]
    set dir   [Widget::getoption $path -dir]
    set cbd   [$path.c cget -borderwidth]
    set cht   [$path.c cget -highlightthickness]
    set bd    [expr {$cbd + $cht}]
    set clean [Widget::getoption $path -clean]

    if {[string equal $type "arrow"]} {
        set coords [list $bd $bd [expr {$width-$bd-1}] [expr {$height-$bd-1}]]
        if {[set id [$path.c find withtag rect]] == ""} {
            $path.c create rectangle $coords -tags rect
        } else {
            $path.c coords $id $coords
        }
        $path.c lower rect
        set arrbd [Widget::getoption $path -arrowbd]
        set bd    [expr {$bd+$arrbd-1}]
    } else {
        $path.c delete rect
    }

    # w and h are max width and max height of arrow
    set w [expr {$width  - 2*([Widget::getoption $path -ipadx]+$bd)}]
    set h [expr {$height - 2*([Widget::getoption $path -ipady]+$bd)}]

    if { $w < 2 } {set w 2}
    if { $h < 2 } {set h 2}

    if { $clean > 0 } {
        # arrange for base to be odd
        if { [string equal $dir "top"] || [string equal $dir "bottom"] } {
            if { !($w % 2) } {
                incr w -1
            }
            if { $clean == 2 } {
                # arrange for h = (w+1)/2
                set h2 [expr {($w+1)/2}]
                if { $h2 > $h } {
                    set w [expr {2*$h-1}]
                } else {
                    set h $h2
                }
            }
        } else {
            if { !($h % 2) } {
                incr h -1
            }
            if { $clean == 2 } {
                # arrange for w = (h+1)/2
                set w2 [expr {($h+1)/2}]
                if { $w2 > $w } {
                    set h [expr {2*$w-1}]
                } else {
                    set w $w2
                }
            }
        }
    }

    set x0 [expr {($width-$w)/2}]
    set y0 [expr {($height-$h)/2}]
    set x1 [expr {$x0+$w-1}]
    set y1 [expr {$y0+$h-1}]

    switch $dir {
        top {
            set xd [expr {($x0+$x1)/2}]
            if { [set id [$path.c find withtag poly]] == "" } {
                $path.c create polygon $x0 $y1 $x1 $y1 $xd $y0 -tags poly
            } else {
                $path.c coords $id $x0 $y1 $x1 $y1 $xd $y0
            }
            if { [string equal $type "arrow"] } {
                if { [set id [$path.c find withtag bot]] == "" } {
                    $path.c create line $x0 $y1 $x1 $y1 $xd $y0 -tags bot
                } else {
                    $path.c coords $id $x0 $y1 $x1 $y1 $xd $y0
                }
                if { [set id [$path.c find withtag top]] == "" } {
                    $path.c create line $x0 $y1 $xd $y0 -tags top
                } else {
                    $path.c coords $id $x0 $y1 $xd $y0
                }
                $path.c itemconfigure top -width $arrbd
                $path.c itemconfigure bot -width $arrbd
            } else {
                $path.c delete top
                $path.c delete bot
            }
        }
        bottom {
            set xd [expr {($x0+$x1)/2}]
            if { [set id [$path.c find withtag poly]] == "" } {
                $path.c create polygon $x1 $y0 $x0 $y0 $xd $y1 -tags poly
            } else {
                $path.c coords $id $x1 $y0 $x0 $y0 $xd $y1
            }
            if { [string equal $type "arrow"] } {
                if { [set id [$path.c find withtag top]] == "" } {
                    $path.c create line $x1 $y0 $x0 $y0 $xd $y1 -tags top
                } else {
                    $path.c coords $id $x1 $y0 $x0 $y0 $xd $y1
                }
                if { [set id [$path.c find withtag bot]] == "" } {
                    $path.c create line $x1 $y0 $xd $y1 -tags bot
                } else {
                    $path.c coords $id $x1 $y0 $xd $y1
                }
                $path.c itemconfigure top -width $arrbd
                $path.c itemconfigure bot -width $arrbd
            } else {
                $path.c delete top
                $path.c delete bot
            }
        }
        left {
            set yd [expr {($y0+$y1)/2}]
            if { [set id [$path.c find withtag poly]] == "" } {
                $path.c create polygon $x1 $y0 $x1 $y1 $x0 $yd -tags poly
            } else {
                $path.c coords $id $x1 $y0 $x1 $y1 $x0 $yd
            }
            if { [string equal $type "arrow"] } {
                if { [set id [$path.c find withtag bot]] == "" } {
                    $path.c create line $x1 $y0 $x1 $y1 $x0 $yd -tags bot
                } else {
                    $path.c coords $id $x1 $y0 $x1 $y1 $x0 $yd
                }
                if { [set id [$path.c find withtag top]] == "" } {
                    $path.c create line $x1 $y0 $x0 $yd -tags top
                } else {
                    $path.c coords $id $x1 $y0 $x0 $yd
                }
                $path.c itemconfigure top -width $arrbd
                $path.c itemconfigure bot -width $arrbd
            } else {
                $path.c delete top
                $path.c delete bot
            }
        }
        right {
            set yd [expr {($y0+$y1)/2}]
            if { [set id [$path.c find withtag poly]] == "" } {
                $path.c create polygon $x0 $y1 $x0 $y0 $x1 $yd -tags poly
            } else {
                $path.c coords $id $x0 $y1 $x0 $y0 $x1 $yd
            }
            if { [string equal $type "arrow"] } {
                if { [set id [$path.c find withtag top]] == "" } {
                    $path.c create line $x0 $y1 $x0 $y0 $x1 $yd -tags top
                } else {
                    $path.c coords $id $x0 $y1 $x0 $y0 $x1 $yd
                }
                if { [set id [$path.c find withtag bot]] == "" } {
                    $path.c create line $x0 $y1 $x1 $yd -tags bot
                } else {
                    $path.c coords $id $x0 $y1 $x1 $yd
                }
                $path.c itemconfigure top -width $arrbd
                $path.c itemconfigure bot -width $arrbd
            } else {
                $path.c delete top
                $path.c delete bot
            }
        }
    }
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::_redraw_state
# ------------------------------------------------------------------------------
proc ArrowButton::_redraw_state { path } {
    set state [Widget::getoption $path -state]
    if { [string equal [Widget::getoption $path -type] "button"] } {
        switch $state {
            normal   {set bg -background;       set fg -foreground}
            active   {set bg -activebackground; set fg -activeforeground}
            disabled {set bg -background;       set fg -disabledforeground}
        }
        set fg [Widget::getoption $path $fg]
        $path.c configure -background [Widget::getoption $path $bg]
        $path.c itemconfigure poly -fill $fg -outline $fg
    } else {
        set stipple ""
        switch $state {
            normal   { set bg [Widget::getoption $path -background] }
            active   { set bg [Widget::getoption $path -activebackground] }
            disabled { set stipple #919191; set bg #000000 }
        }
        set thrc [Widget::getoption $path -troughcolor]
        $path.c configure -background [Widget::getoption $path -background]
        $path.c itemconfigure rect -fill $thrc -outline $thrc
        $path.c itemconfigure poly -fill $bg   -outline $bg -stipple $stipple
    }
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::_redraw_relief
# ------------------------------------------------------------------------------
proc ArrowButton::_redraw_relief { path } {
    variable _moved

    if { [string equal [Widget::getoption $path -type] "button"] } {
        if { [string equal [Widget::cget $path -relief] "sunken"] } {
            if { !$_moved($path) } {
                $path.c move poly 1 1
                set _moved($path) 1
            }
        } else {
            if { $_moved($path) } {
                $path.c move poly -1 -1
                set _moved($path) 0
            }
        }
    } else {
        set bg    [Widget::getoption $path -background]
        set col3d [BWidget::get3dcolor $path $bg]
        switch [Widget::getoption $path -arrowrelief] {
            raised {set top [lindex $col3d 1]; set bot [lindex $col3d 0]}
            sunken {set top [lindex $col3d 0]; set bot [lindex $col3d 1]}
        }
        $path.c itemconfigure top -fill $top
        $path.c itemconfigure bot -fill $bot
    }
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::_redraw_whole
# ------------------------------------------------------------------------------
proc ArrowButton::_redraw_whole { path width height } {
    _redraw $path $width $height
    _redraw_relief $path
    _redraw_state $path
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::_enter
# ------------------------------------------------------------------------------
proc ArrowButton::_enter { path } {
    variable _grab
    set path [winfo parent $path]
    set _grab(current) $path
    if { ![string equal [Widget::getoption $path -state] "disabled"] } {
        set _grab(oldstate) [Widget::getoption $path -state]
        configure $path -state active
        if { $_grab(pressed) == $path } {
            if { [string equal [Widget::getoption $path -type] "button"] } {
                set _grab(oldrelief) [Widget::cget $path -relief]
                configure $path -relief sunken
            } else {
                set _grab(oldrelief) [Widget::getoption $path -arrowrelief]
                configure $path -arrowrelief sunken
            }
        }
    }
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::_leave
# ------------------------------------------------------------------------------
proc ArrowButton::_leave { path } {
    variable _grab
    set path [winfo parent $path]
    set _grab(current) ""
    if { ![string equal [Widget::getoption $path -state] "disabled"] } {
        configure $path -state $_grab(oldstate)
        if { $_grab(pressed) == $path } {
            if { [string equal [Widget::getoption $path -type] "button"] } {
                configure $path -relief $_grab(oldrelief)
            } else {
                configure $path -arrowrelief $_grab(oldrelief)
            }
        }
    }
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::_press
# ------------------------------------------------------------------------------
proc ArrowButton::_press { path } {
    variable _grab
    set path [winfo parent $path]
    if { ![string equal [Widget::getoption $path -state] "disabled"] } {
        set _grab(pressed) $path
            if { [string equal [Widget::getoption $path -type] "button"] } {
            set _grab(oldrelief) [Widget::cget $path -relief]
            configure $path -relief sunken
        } else {
            set _grab(oldrelief) [Widget::getoption $path -arrowrelief]
            configure $path -arrowrelief sunken
        }
        if {[llength [set cmd [Widget::getoption $path -armcommand]]]} {
            uplevel \#0 $cmd
            if { [set delay [Widget::getoption $path -repeatdelay]]    > 0 ||
                 [set delay [Widget::getoption $path -repeatinterval]] > 0 } {
                after $delay [list ArrowButton::_repeat $path]
            }
        }
    }
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::_release
# ------------------------------------------------------------------------------
proc ArrowButton::_release { path } {
    variable _grab
    set path [winfo parent $path]
    if { $_grab(pressed) == $path } {
        set _grab(pressed) ""
            if { [string equal [Widget::getoption $path -type] "button"] } {
            configure $path -relief $_grab(oldrelief)
        } else {
            configure $path -arrowrelief $_grab(oldrelief)
        }
        if {[llength [set cmd [Widget::getoption $path -disarmcommand]]]} {
            uplevel \#0 $cmd
        }
        if { $_grab(current) == $path &&
             ![string equal [Widget::getoption $path -state] "disabled"] &&
             [llength [set cmd [Widget::getoption $path -command]]]} {
            uplevel \#0 $cmd
        }
    }
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::_repeat
# ------------------------------------------------------------------------------
proc ArrowButton::_repeat { path } {
    variable _grab
    if { $_grab(current) == $path && $_grab(pressed) == $path &&
         ![string equal [Widget::getoption $path -state] "disabled"] &&
         [llength [set cmd [Widget::getoption $path -armcommand]]]} {
        uplevel \#0 $cmd
    }
    if { $_grab(pressed) == $path &&
         ([set delay [Widget::getoption $path -repeatinterval]] > 0 ||
          [set delay [Widget::getoption $path -repeatdelay]]    > 0) } {
        after $delay [list ArrowButton::_repeat $path]
    }
}


# ------------------------------------------------------------------------------
#  Command ArrowButton::_destroy
# ------------------------------------------------------------------------------
proc ArrowButton::_destroy { path } {
    variable _moved
    Widget::destroy $path
    unset _moved($path)
}
Added lib/BWidget/bitmap.tcl.




























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# ------------------------------------------------------------------------------
#  bitmap.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: bitmap.tcl,v 1.4 2003/10/20 21:23:52 damonc Exp $
# ------------------------------------------------------------------------------
#  Index of commands:
#     - Bitmap::get
#     - Bitmap::_init
# ----------------------------------------------------------------------------
namespace eval Bitmap {
    Widget::define Bitmap bitmap -classonly

    variable path
    variable _bmp
    variable _types {
        photo  .gif
        photo  .ppm
        bitmap .xbm
        photo  .xpm
    }

    proc use {} {}
}


# ----------------------------------------------------------------------------
#  Command Bitmap::get
# ----------------------------------------------------------------------------
proc Bitmap::get { name } {
    variable path
    variable _bmp
    variable _types

    if {[info exists _bmp($name)]} {
        return $_bmp($name)
    }

    # --- Nom de fichier avec extension ---------------------------------
    set ext [file extension $name]
    if { $ext != "" } {
        if { ![info exists _bmp($ext)] } {
            error "$ext not supported"
        }

        if { [file exists $name] } {
            if {[string equal $ext ".xpm"]} {
                set _bmp($name) [xpm-to-image $name]
                return $_bmp($name)
            }
            if {![catch {set _bmp($name) [image create $_bmp($ext) -file $name]}]} {
                return $_bmp($name)
            }
        }
    }

    foreach dir $path {
        foreach {type ext} $_types {
            if { [file exists [file join $dir $name$ext]] } {
                if {[string equal $ext ".xpm"]} {
                    set _bmp($name) [xpm-to-image [file join $dir $name$ext]]
                    return $_bmp($name)
                } else {
                    if {![catch {set _bmp($name) [image create $type -file [file join $dir $name$ext]]}]} {
                        return $_bmp($name)
                    }
                }
            }
        }
    }

    return -code error "$name not found"
}


# ----------------------------------------------------------------------------
#  Command Bitmap::_init
# ----------------------------------------------------------------------------
proc Bitmap::_init { } {
    global   env
    variable path
    variable _bmp
    variable _types

    set path [list "." [file join $::BWIDGET::LIBRARY images]]
    set supp [image types]
    foreach {type ext} $_types {
        if { [lsearch $supp $type] != -1} {
            set _bmp($ext) $type
        }
    }
}


Bitmap::_init
Added lib/BWidget/button.tcl.










































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# ----------------------------------------------------------------------------
#  button.tcl
#  This file is part of Unifix BWidget Toolkit
# ----------------------------------------------------------------------------
#  Index of commands:
#
#   Public Commands
#     - Button::create
#     - Button::configure
#     - Button::cget
#     - Button::invoke
#
#   Private Commands (event bindings)
#     - Button::_destroy
#     - Button::_enter
#     - Button::_leave
#     - Button::_press
#     - Button::_release
#     - Button::_repeat
# ----------------------------------------------------------------------------

namespace eval Button {
    if {[BWidget::using ttk]} {
        Widget::define Button button TTKButton DynamicHelp
    } else {
        Widget::define Button button DynamicHelp
    }

    set remove [list -command -relief -text -textvariable \
        -underline -image -state]
    if {[info tclversion] > 8.3} {
        lappend remove -repeatdelay -repeatinterval
    }

    Widget::tkinclude Button button :cmd remove $remove

    Widget::declare Button {
        {-name                 String     ""      0 }
        {-text                 String     ""      0 }
        {-textvariable         String     ""      0 }
        {-underline            Int        -1      0 "%d >= -1" }
        {-armcommand           String     ""      0 }
        {-disarmcommand        String     ""      0 }
        {-command              String     ""      0 }
        {-state                TkResource ""      0 button }
        {-repeatdelay          Int        0       0 "%d >= 0" }
        {-repeatinterval       Int        0       0 "%d >= 0" }
        {-relief               Enum       raised  0 
                {raised sunken flat ridge solid groove link}}
        {-image                String     ""      0 }
        {-activeimage          String     ""      0 }
        {-pressedimage         String     ""      0 }
        {-disabledimage        String     ""      0 }
    }

    Widget::addmap Button "" :cmd { -text {} -underline {} }

    DynamicHelp::include Button balloon

    variable _current ""
    variable _pressed ""

    bind BwButton <Enter>           {Button::_enter %W}
    bind BwButton <Leave>           {Button::_leave %W}
    bind BwButton <ButtonPress-1>   {Button::_press %W}
    bind BwButton <ButtonRelease-1> {Button::_release %W}
    bind BwButton <Key-space>       {Button::invoke %W; break}
    bind BwButton <Return>          {Button::invoke %W; break}
    bind BwButton <Destroy>         {Widget::destroy %W}
}


# ----------------------------------------------------------------------------
#  Command Button::create
# ----------------------------------------------------------------------------
proc Button::create { path args } {
    if {[BWidget::using ttk]} {
        return [eval [list TTKButton::create $path] $args]
    }

    Widget::initArgs Button $args maps

    eval [list button $path] $maps(:cmd)

    Widget::initFromODB Button $path $maps(Button)

    set var [$path cget -textvariable]
    if {![string length $var]} {
        set desc [BWidget::getname [Widget::getoption $path -name]]
        if {[llength $desc]} {
            set text  [lindex $desc 0]
            set under [lindex $desc 1]
            $path configure -text $text -underline $under
        } else {
            set text  [$path cget -text]
            set under [$path cget -underline]
        }
    } else {
        set text  ""
        set under -1
        $path configure -underline $under
    }

    # Do some extra configuration on the button
    set relief [Widget::getoption $path -relief]
    if {[string equal $relief "link"]} { set relief flat }

    set opts [list]
    lappend opts -text $text -underline $under -textvariable $var
    lappend opts -relief $relief -state [Widget::cget $path -state]
    lappend opts -image [Widget::cget $path -image]

    eval [list $path configure] $opts

    set top [winfo toplevel $path]
    bindtags $path [list $path BwButton $top all]

    set accel1 [string tolower [string index $text $under]]
    set accel2 [string toupper $accel1]
    if {[string length $accel1]} {
        bind $top <Alt-$accel1> [list Button::invoke $path]
        bind $top <Alt-$accel2> [list Button::invoke $path]
    }

    DynamicHelp::sethelp $path $path 1

    return [Widget::create Button $path]
}


# ----------------------------------------------------------------------------
#  Command Button::configure
# ----------------------------------------------------------------------------
proc Button::configure { path args } {
    set oldunder [$path:cmd cget -underline]
    if {$oldunder != -1} {
        set text      [$path:cmd cget -text]
        set oldaccel1 [string tolower [string index $text $oldunder]]
        set oldaccel2 [string toupper $oldaccel1]
    } else {
        set oldaccel1 ""
        set oldaccel2 ""
    }
    set res [Widget::configure $path $args]

    if {[Widget::anyChangedX $path -relief -state]} {
        set state  [Widget::cget $path -state]
        set relief [Widget::cget $path -relief]
        if {[string equal $relief "link"]} {
            if {[string equal $state "active"]} {
                set relief "raised"
            } else {
                set relief "flat"
            }
        }

        $path:cmd configure -relief $relief

        set dimg [Widget::cget $path -disabledimage]
        if {[string equal $state "disabled"] && ![string equal $dimg ""]} {
            $path:cmd configure -image $dimg
        } else {
            $path:cmd configure \
                -state      $state \
                -image      [Widget::cget $path -image] \
                -background [Widget::cget $path -background] \
                -foreground [Widget::cget $path -foreground]
        }
    }

    if {[Widget::hasChanged $path -image image]} {
        $path:cmd configure -image $image
    }

    if {[Widget::anyChangedX $path -textvariable -name -text -underline]} {
	set var   [Widget::cget $path -textvariable]
	set text  [Widget::cget $path -text]
	set under [Widget::cget $path -underline]

        if {![string length $var]} {
            set desc [BWidget::getname [Widget::cget $path -name]]
            if {[llength $desc]} {
                set text  [lindex $desc 0]
                set under [lindex $desc 1]
            }
        } else {
            set under -1
            set text  ""
        }
        set top [winfo toplevel $path]
        if {![string equal $oldaccel1 ""]} {
            bind $top <Alt-$oldaccel1> {}
            bind $top <Alt-$oldaccel2> {}
        }
        set accel1 [string tolower [string index $text $under]]
        set accel2 [string toupper $accel1]
        if {![string equal $accel1 ""]} {
            bind $top <Alt-$accel1> [list Button::invoke $path]
            bind $top <Alt-$accel2> [list Button::invoke $path]
        }
        $path:cmd configure -text $text -underline $under -textvariable $var
    }

    DynamicHelp::sethelp $path $path

    return $res
}


# ----------------------------------------------------------------------------
#  Command Button::cget
# ----------------------------------------------------------------------------
proc Button::cget { path option } {
    Widget::cget $path $option
}


# ----------------------------------------------------------------------------
#  Command Button::invoke
# ----------------------------------------------------------------------------
proc Button::invoke { path } {
    if {[string equal [Widget::cget $path -state] "disabled"]} { return }

    $path:cmd configure -state active -relief sunken
    update idletasks

    set cmd [Widget::getoption $path -armcommand]
    if {![string equal $cmd ""]} {
        uplevel \#0 $cmd
    }
    after 100
    set relief [Widget::getoption $path -relief]
    if {[string equal $relief "link"]} {
        set relief flat
    }
    $path:cmd configure \
        -state  [Widget::getoption $path -state] \
        -relief $relief
    set cmd [Widget::getoption $path -disarmcommand]
    if {![string equal $cmd ""]} {
        uplevel \#0 $cmd
    }
    set cmd [Widget::getoption $path -command]
    if {![string equal $cmd ""]} {
        uplevel \#0 $cmd
    }
}


# ----------------------------------------------------------------------------
#  Command Button::_enter
# ----------------------------------------------------------------------------
proc Button::_enter { path } {
    variable _current
    variable _pressed

    set _current $path
    if {![string equal [Widget::cget $path -state] "disabled"]} {
        $path:cmd configure -state active
        if {[string equal $_pressed $path]} {
            $path:cmd configure -relief sunken
        } elseif {[string equal [Widget::cget $path -relief] "link"]} {
            $path:cmd configure -relief raised
        }

        set image [Widget::cget $path -activeimage]
        if {[string equal $_pressed $path]} {
            set pressedimage [Widget::cget $path -pressedimage]
            if {![string equal $pressedimage ""]} { set image $pressedimage }
        }
        if {![string equal $image ""]} { $path:cmd configure -image $image }
    }
}


# ----------------------------------------------------------------------------
#  Command Button::_leave
# ----------------------------------------------------------------------------
proc Button::_leave { path } {
    variable _current
    variable _pressed

    set _current ""
    if {[string equal [Widget::cget $path -state] "disabled"]} {
        set dimg [Widget::cget $path -disabledimage]
        if {![string equal $dimg ""]} { $path:cmd configure -state normal }
    } else {
        set relief [Widget::cget $path -relief]
        if {[string equal $_pressed $path]} {
            if {[string equal $relief "link"]} {
                set relief raised
            }
        } elseif {[string equal $relief "link"]} {
            set relief flat
        }

        $path:cmd configure \
            -relief $relief \
            -state  [Widget::cget $path -state] \
            -image  [Widget::cget $path -image]
    }
}


# ----------------------------------------------------------------------------
#  Command Button::_press
# ----------------------------------------------------------------------------
proc Button::_press { path } {
    variable _pressed

    if {![string equal [Widget::cget $path -state] "disabled"]} {
        set _pressed $path
	$path:cmd configure -relief sunken

        set img [Widget::cget $path -pressedimage]
        if {![string equal $img ""]} { $path:cmd configure -image $img }

	set cmd [Widget::getoption $path -armcommand]
        if {![string equal $cmd ""]} {
            uplevel \#0 $cmd
	    set repeatdelay [Widget::getoption $path -repeatdelay]
	    set repeatint [Widget::getoption $path -repeatinterval]
            if {$repeatdelay > 0} {
                after $repeatdelay "Button::_repeat $path"
            } elseif {$repeatint > 0} {
                after $repeatint "Button::_repeat $path"
	    }
        }
    }
}


# ----------------------------------------------------------------------------
#  Command Button::_release
# ----------------------------------------------------------------------------
proc Button::_release { path } {
    variable _current
    variable _pressed

    if {[string equal $_pressed $path]} {
        set pressed $_pressed
        set _pressed ""
        set relief [Widget::getoption $path -relief]
	after cancel "Button::_repeat $path"

        if {[string equal $relief "link"]} {
            set relief raised
        }
        
        set image [Widget::cget $path -image]
        if {[string equal $pressed $path]} {
            set activeimage [Widget::cget $path -activeimage]
            if {![string equal $activeimage ""]} { set image $activeimage }
        }

        $path:cmd configure -relief $relief -image $image

	set cmd [Widget::getoption $path -disarmcommand]
        if {![string equal $cmd ""]} {
            uplevel \#0 $cmd
        }

        if {[string equal $_current $path] &&
             ![string equal [Widget::cget $path -state] "disabled"] && \
	     [set cmd [Widget::getoption $path -command]] != ""} {
            uplevel \#0 $cmd
        }
    }
}


# ----------------------------------------------------------------------------
#  Command Button::_repeat
# ----------------------------------------------------------------------------
proc Button::_repeat { path } {
    variable _current
    variable _pressed

    if {$_current == $path && $_pressed == $path &&
         ![string equal [Widget::cget $path -state] "disabled"] &&
         [set cmd [Widget::getoption $path -armcommand]] != ""} {
        uplevel \#0 $cmd
    }
    if { $_pressed == $path &&
         ([set delay [Widget::getoption $path -repeatinterval]] >0 ||
          [set delay [Widget::getoption $path -repeatdelay]] > 0) } {
        after $delay "Button::_repeat $path"
    }
}
Added lib/BWidget/buttonbox.tcl.






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
# ----------------------------------------------------------------------------
#  buttonbox.tcl
#  This file is part of Unifix BWidget Toolkit
# ----------------------------------------------------------------------------
#  Index of commands:
#
#   Public Commands:
#     - ButtonBox::create
#     - ButtonBox::configure
#     - ButtonBox::cget
#     - ButtonBox::add
#     - ButtonBox::itemconfigure
#     - ButtonBox::itemcget
#     - ButtonBox::setfocus
#     - ButtonBox::invoke
#     - ButtonBox::index
#
#   Private Commands:
#     - ButtonBox::_redraw
# ----------------------------------------------------------------------------

namespace eval ButtonBox {
    Widget::define ButtonBox buttonbox Button

    namespace eval Button {
        Widget::declare ButtonBox::Button {
            {-tags              String    ""            0}
            {-hide              Boolean   0             0}
            {-value             String    ""            0}
            {-spacing           Int       -1            0 "%d >= -1"}
        }
    }

    if {[BWidget::using ttk]} {
        Widget::tkinclude ButtonBox ttk::frame :cmd \
            remove { -class -colormap -container -padx -pady -visual }
    } else {
        Widget::tkinclude ButtonBox frame :cmd \
            remove { -class -colormap -container -padx -pady -visual }
    }

    Widget::declare ButtonBox {
        {-orient      Enum       horizontal 0 {horizontal vertical}}
        {-state       Enum       "normal"   0 {disabled normal}}
        {-homogeneous Boolean    1          0}
        {-spacing     Int        10         0 "%d >= 0"}
        {-padx        Int        1          0}
        {-pady        Int        1          0}
        {-default     String     -1         0} 
        {-rows        Int        "0"        0}
        {-columns     Int        "0"        0}
    }

    bind ButtonBox <Map>     [list ButtonBox::_realize %W]
    bind ButtonBox <Destroy> [list ButtonBox::_destroy %W]
}


# ----------------------------------------------------------------------------
#  Command ButtonBox::create
# ----------------------------------------------------------------------------
proc ButtonBox::create { path args } {
    Widget::initArgs ButtonBox $args maps

    if {[BWidget::using ttk]} {
        eval [list ttk::frame $path -class ButtonBox] $maps(:cmd)
    } else {
        eval [list frame $path -class ButtonBox] $maps(:cmd)
    }

    Widget::initFromODB ButtonBox $path $maps(ButtonBox)

    # For 8.4+ we don't want to inherit the padding
    if {![BWidget::using ttk]
        && [info tclversion] >= 8.4} { $path configure -padx 0 -pady 0 }

    Widget::getVariable $path data

    set data(max)      0
    set data(nbuttons) 0
    set data(realized) 0
    set data(buttons)  [list]
    set data(widgets)  [list]
    set data(default)  [Widget::getoption $path -default]

    return [Widget::create ButtonBox $path]
}


# ----------------------------------------------------------------------------
#  Command ButtonBox::configure
# ----------------------------------------------------------------------------
proc ButtonBox::configure { path args } {
    Widget::getVariable $path data

    set res [Widget::configure $path $args]

    if {[Widget::hasChanged $path -default val]} {
        _select_default $path
    }

    if {[Widget::hasChanged $path -state val]} {
	foreach i $data(buttons) {
	    $path.b$i configure -state $val
	}
    }

    set opts [list -rows -columns -orient -homogeneous]
    if {[eval [list Widget::anyChangedX $path] $opts]} { _redraw $path }

    return $res
}


# ----------------------------------------------------------------------------
#  Command ButtonBox::cget
# ----------------------------------------------------------------------------
proc ButtonBox::cget { path option } {
    return [Widget::cget $path $option]
}


# ----------------------------------------------------------------------------
#  Command ButtonBox::add -- (Deprecated.  Use ButtonBox::insert end)
# ----------------------------------------------------------------------------
proc ButtonBox::add { path args } {
    return [eval insert $path end $args]
}


proc ButtonBox::insert { path idx args } {
    Widget::getVariable $path data
    Widget::getVariable $path tags

    set but $path.b$data(nbuttons)

    set class Button
    if {[BWidget::using ttk]} { set class TTKButton }
    array set maps [Widget::splitArgs $args $class ButtonBox::Button]

    Widget::init ButtonBox::Button $but#bbox $maps(ButtonBox::Button)

    set spacing [Widget::getOption -spacing -1 $but#bbox $path]

    ## Save the current spacing setting for this button.  Buttons
    ## appended to the end of the box have their spacing applied
    ## to their left while all other have their spacing applied
    ## to their right.
    if {[string equal $idx "end"] && $data(nbuttons)} {
	set data(spacing,$data(nbuttons)) [list left $spacing]
        lappend data(widgets) $but
	lappend data(buttons) $data(nbuttons)
    } else {
	set data(spacing,$data(nbuttons)) [list right $spacing]
        set data(widgets) [linsert $data(widgets) $idx $but]
        set data(buttons) [linsert $data(buttons) $idx $data(nbuttons)]
    }

    set opts [list]
    if {![BWidget::using ttk]} {
        lappend opts -padx [Widget::getoption $path -padx]
        lappend opts -pady [Widget::getoption $path -pady]
    }

    eval [list Button::create $but] $opts $maps(:cmd) $maps($class)

    foreach tag [Widget::getoption $but#bbox -tags] {
        lappend tags($tag) $but
        if {![info exists tags($tag,state)]} { set tags($tag,state) 1 }
    }

    _redraw_idle $path

    incr data(nbuttons)

    _select_default $path

    return $but
}


proc ButtonBox::delete { path index } {
    Widget::getVariable $path data
    Widget::getVariable $path tags

    set button $path.b$i
    set widget $button#bbox

    set i [lindex $data(buttons) $index]
    set data(buttons) [lreplace $data(buttons) $index $index]
    set data(widgets) [lreplace $data(widgets) $index $index]

    foreach tag [Widget::getoption $widget -tags] {
        set tags($tag) [BWidget::lremove $tags($tag) $button]
        if {![llength $tags($tag)]} {
            unset tags($tag) tags($tag,state)
        }
    }

    Widget::destroy $widget 0

    destroy $button

    _redraw_idle $path
}


proc ButtonBox::buttons { path {first ""} {last ""} } {
    Widget::getVariable $path data
    if {![string length $first]} { return $data(widgets) }
    if {![string length $last]}  { return [lindex $data(widgets) $first] }
    return [lrange $data(widgets) $first $last]
}


# ----------------------------------------------------------------------------
#  Command ButtonBox::itemconfigure
# ----------------------------------------------------------------------------
proc ButtonBox::itemconfigure { path index args } {
    Widget::getVariable $path data

    set idx    [index $path $index]
    set button $path.b$idx

    set class Button
    if {[BWidget::using ttk]} { set class TTKButton }

    if {![llength $args]} {
        set res [${class}::configure $button]
        eval lappend res [Widget::configure $button#bbox [list]]
        return [lsort $res]
    }

    if {[llength $args] == 1} {
        if {[Widget::optionExists Button $args]} {
            return [${class}::configure $button $args]
        } else {
            return [Widget::configure $button#bbox $args]
        }
    }

    array set maps [Widget::splitArgs $args $class ButtonBox::Button]

    if {[info exists maps(ButtonBox::Button)]} {
        set oldtags [Widget::getoption $button#bbox -tags]

        Widget::configure $button#bbox $maps(ButtonBox::Button)

        if {[Widget::hasChanged $button#bbox -tags newtags]} {
            Widget::getVariable $path tags

            foreach tag $oldtags {
                set tags($tag) [BWidget::lremove $tags($tag) $button]
                if {![llength $tags($tag)]} {
                    unset tags($tag) tags($tag,state)
                }
            }

            foreach tag $newtags {
                lappend tags($tag) $button
                if {![info exists tags($tag,state)]} { set tags($tag,state) 1 }
            }
        }

        set redraw 0

        if {[Widget::hasChanged $button#bbox -spacing spacing]} {
            set redraw 1
            set data(spacing,$idx) [lreplace $data(spacing,$idx) 1 1 $spacing]
        }

        if {[Widget::hasChanged $button#bbox -hide hide]} {
            set redraw 1
        }

        if {$redraw} { _redraw_idle $path }
    }

    if {[llength $maps(:cmd)] || [llength $maps($class)]} {
        eval [list ${class}::configure $button] $maps(:cmd) $maps($class)
    }
}


# ----------------------------------------------------------------------------
#  Command ButtonBox::itemcget
# ----------------------------------------------------------------------------
proc ButtonBox::itemcget { path index option } {
    set button $path.b[index $path $index]
    if {[Widget::optionExists Button $option]} {
        return [Button::cget $button $option]
    } else {
        return [Widget::cget $button#bbox $option]
    }
}


# ----------------------------------------------------------------------------
#  Command ButtonBox::setfocus
# ----------------------------------------------------------------------------
proc ButtonBox::setfocus { path index } {
    set but $path.b[index $path $index]
    if {[winfo exists $but]} { focus $but }
}


# ----------------------------------------------------------------------------
#  Command ButtonBox::invoke
# ----------------------------------------------------------------------------
proc ButtonBox::invoke { path index } {
    set but $path.b[index $path $index]
    if {[winfo exists $but]} { $but invoke }
}


# ----------------------------------------------------------------------------
#  Command ButtonBox::index
# ----------------------------------------------------------------------------
proc ButtonBox::index { path index } {
    Widget::getVariable $path data

    set n [expr {$data(nbuttons) - 1}]

    if {[string is integer -strict $index]} {
        set res $index
	if {$index > $n} { set res $n }
        return $res
    }

    if {[string equal $index "default"]} {
        set res [Widget::getoption $path -default]
    } elseif {[string equal $index "end"] || [string equal $index "last"]} {
	set res $n
    } elseif {[set res [lsearch -exact $data(widgets) $index]] > -1} {
        ## They passed us a widget that is in the box.
    } else {
	## Search the text and name of each button in the
        ## box and return the index that matches.
	foreach i $data(buttons) {
	    set w $path.b$i
	    lappend text  [$w cget -text]
	    lappend names [$w cget -name]
	}
        set len [llength $data(buttons)]
	set res [lsearch -exact [concat $names $text] $index]
        if {$res >= $len} { set res [expr {$res - $len}] }
    }
    return $res
}


# ButtonBox::gettags --
#
#	Return a list of all the tags on all the buttons in a buttonbox.
#
# Arguments:
#	path      the buttonbox to query.
#
# Results:
#	taglist   a list of tags on the buttons in the buttonbox

proc ButtonBox::gettags { path } {
    Widget::getVariable $path tags

    set tags [list]

    foreach tag [array names tags] {
        if {![string match "*,state" $tag]} { lappend tags $tag }
    }
    return $tags
}


# ButtonBox::setbuttonstate --
#
#	Set the state of a given button tag.  If this makes any buttons
#       enable-able (ie, all of their tags are TRUE), enable them.
#
# Arguments:
#	path        the button box widget name
#	tag         the tag to modify
#	state       the new state of $tag (0 or 1)
#
# Results:
#	None.

proc ButtonBox::setbuttonstate { path tag state } {
    Widget::getVariable $path tags

    if {![info exists tags($tag)]} { return }

    set tags($tag,state) $state
    foreach button $tags($tag) {
        set expression 1
        foreach buttontag [Widget::getoption $button#bbox -tags] {
            lappend expression && $tags($buttontag,state)
        }

        if {[expr $expression]} {
            set state normal
        } else {
            set state disabled
        }

        $button configure -state $state
    }
}

# ButtonBox::getbuttonstate --
#
#	Retrieve the state of a given button tag.
#
# Arguments:
#	path        the button box widget name
#	tag         the tag to modify
#
# Results:
#	None.

proc ButtonBox::getbuttonstate { path tag } {
    Widget::getVariable $path tags

    if {![info exists tags($tag)]} {
        return -code error "unknown tag \"$tag\""
    }

    return $tags($tag,state)
}


proc ButtonBox::_select_default { path } {
    Widget::getVariable $path data

    set default [Widget::getoption $path -default]
    set data(default) [ButtonBox::index $path $default]

    foreach i $data(buttons) {
        set button $path.b$i
        if {$i == $data(default)} {
            if {[BWidget::using ttk]} {
                $button state focus
            } else {
                $button configure -default active
            }
        } else {
            if {[BWidget::using ttk]} {
                $button state !focus
            } else {
                $button configure -default normal
            }
        }
        incr i
    }
}


proc ButtonBox::_redraw_idle { path } {
    Widget::getVariable $path data

    if {![info exists data(redraw)]} {
        set data(redraw) 1
        after idle [list ButtonBox::_redraw $path]
    }
}


# ----------------------------------------------------------------------------
#  Command ButtonBox::_redraw
# ----------------------------------------------------------------------------
proc ButtonBox::_redraw { path } {
    Widget::getVariable $path data
    Widget::getVariable $path buttons

    set data(redraw) 1

    ## We re-grid the buttons from left-to-right.  As we go through
    ## each button, we check its spacing and which direction the
    ## spacing applies to.  Once spacing has been applied to an index,
    ## it is not changed.  This means spacing takes precedence from
    ## left-to-right.

    set rows [Widget::getoption $path -rows]
    set cols [Widget::getoption $path -columns]

    set idx     0
    set rowidx  0
    set colidx  0
    set idxs [list]
    foreach i $data(buttons) {
	set dir     [lindex $data(spacing,$i) 0]
	set spacing [lindex $data(spacing,$i) 1]
        set but $path.b$i
        if {[string equal [Widget::getoption $path -orient] "horizontal"]} {
            if {![Widget::getoption $but#bbox -hide]} {
                grid $but -column $idx -row $rowidx -sticky nsew
            } else {
                grid remove $but
            }

            if {[Widget::getoption $path -homogeneous]} {
                set req [winfo reqwidth $but]
                if { $req > $data(max) } {
                    grid columnconfigure $path [expr {2*$i}] -minsize $req
                    set data(max) $req
                }
                grid columnconfigure $path $idx -minsize $data(max) -weight 1
            } else {
                grid columnconfigure $path $idx -weight 0
            }

	    set col [expr {$idx - 1}]
	    if {[string equal $dir "right"]} { set col [expr {$idx + 1}] }
	    if {$col > 0 && [lsearch -exact $idxs $col] < 0} {
		lappend idxs $col
		grid columnconfigure $path $col -minsize $spacing
	    }

            incr colidx

            if {$cols > 0 && $colidx >= $cols} {
                set idx -2
                incr rowidx
                set colidx 0
            }
        } else {
            if {![Widget::getoption $but#bbox -hide]} {
                grid $but -column $colidx -row $idx -sticky nsew
            } else {
                grid remove $but
            }

            grid rowconfigure $path $idx -weight 0

	    set row [expr {$idx - 1}]
	    if {[string equal $dir "right"]} { set row [expr {$idx + 1}] }
	    if {$row > 0 && [lsearch -exact $idxs $row] < 0} {
		lappend idxs $row
		grid rowconfigure $path $row -minsize $spacing
	    }

            incr rowidx

            if {$rows > 0 && $rowidx >= $rows} {
                set idx -2
                incr colidx
                set rowidx 0
            }
        }
        incr idx 2
    }

    unset data(redraw)
}


proc ButtonBox::_realize { path } {
    Widget::getVariable $path data

    if {!$data(realized)} {
        set data(realized) 1
        ButtonBox::_redraw $path
    }
}


proc ButtonBox::_destroy { path } {
    Widget::getVariable $path data

    foreach i $data(buttons) {
        set button $path.b$i
        Widget::destroy $button#bbox 0
    }

    Widget::destroy $path
}
Added lib/BWidget/calendar.tcl.
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
#==========================================================
# Index of commands:
#
#   Public commands
#       - Calendar::cget
#       - Calendar::configure
#       - Calendar::create
#       - Calendar::dates
#
#   Private commands (internal helper procs)
#       - Calendar::_flip
#==========================================================

namespace eval Calendar {
    Widget::define Calendar calendar Dialog

    Widget::tkinclude Calendar frame :cmd \
        remove { -bg -background -class -colormap -container -visual }

    Widget::declare Calendar {
        {-title               String      "Select a Date"       0}
        {-background          Color       "SystemButtonFace"    0}
        {-foreground          Color       "SystemButtonText"    0}
        {-disabledforeground  Color       "SystemDisabledText"  0}
        {-font                String      "TkTextFont"          0}
        {-days                String      "S M T W T F S"       0}
        {-selectmode          Enum        "single"    0 {single multiple}}
        {-selectbackground    Color       "SystemHighlight"     0}
        {-selectforeground    Color       "SystemHighlightText" 0}

        {-type                Enum        "dialog"    1 {dialog frame popup}}
        {-format              String      "%D"        0}
        {-dates               String      ""          1}
        {-month               String      ""          0}
        {-year                String      ""          0}

        {-ipadx               Int         "30"        1}
        {-ipady               Int         "5"         1}
        {-place               String      "center"    1}
        {-parent              String      ""          1}
        {-calendarbackground  Color      "SystemButtonFace"  0}
        {-repeatdelay         Int         400         0 "%d >= 0"}
        {-repeatinterval      Int         100         0 "%d >= 0"}

        {-showleaddays        Boolean     "1"         1}
        {-showheader          Boolean     "1"         1}
        {-showseparators      Boolean     "1"         1}
        {-showtitles          Boolean     "1"         1}
        {-titlemenus          Boolean     "1"         1}
        {-hottrack            Boolean     "1"         1}

        {-calendars           Int         1            1 "%d >= 1"}
        {-orient              Enum        "horizontal" 1 {horizontal vertical}}

        {-popupfont           String      "Arial 6"         0}
        {-popupipadx          Int         "10"              1}
        {-popupipady          Int         "3"               1}
        {-popupbackground     String      "#FFFFFF"         0}

        {-bg                  Synonym     -background}
        {-fg                  Synonym     -foreground}
    }

    variable _days
    set _days [list sunday monday tuesday wednesday thursday friday saturday]

    variable _months
    set _months [list January February March April May June July \
                August September October November December]

    Widget::declare Calendar [list \
        [list -months     String $_months  1] \
        [list -startday   Enum   "sunday"  0 $_days] \
    ]

    bind Calendar <Destroy> [list Calendar::_destroy %W]
}


proc Calendar::create { path args } {
    set cal $path#Calendar

    Widget::init Calendar $cal $args

    Widget::getVariable $cal data

    set data(dates)    [list]
    set data(hottrack) [list]
    set data(popup)    [string equal [Widget::getoption $cal -type] "popup"]

    set dates  [Widget::getoption $cal -dates]
    set format [Widget::getoption $cal -format]
    set mode   [Widget::getoption $cal -selectmode]
    if {![llength $dates]} {
        set dates [clock format [clock seconds] -format $format]
    }

    foreach date $dates {
        set secs [clock scan $date]
        if {![info exists data(month)]} {
            set data(month) [clock format $secs -format %B]
        }
        if {![info exists data(year)]} {
            set data(year)  [clock format $secs -format %Y]
        }
        lappend data(dates) $secs

        if {[string equal $mode "single"]} { break }
    }

    set month [Widget::getoption $cal -month]
    if {![string equal $month ""]} { set data(month) $month }

    set year  [Widget::getoption $cal -year]
    if {![string equal $year ""]} { set data(year) $year }

    Widget::setoption $cal -month $data(month)
    Widget::setoption $cal -year  $data(year)

    switch -- [Widget::getoption $cal -type] {
        "popup" {
            set data(bg)     [Widget::getoption $cal -popupbackground]
            set data(font)   [Widget::getoption $cal -popupfont]
            set data(ipadx)  [Widget::getoption $cal -popupipadx]
            set data(ipady)  [Widget::getoption $cal -popupipady]
            set data(header) [Widget::getoption $cal -showheader]

            set list   [list at center left right above below]
            set place  [Widget::getoption $cal -place]
            set parent [Widget::getoption $cal -parent]
            set where  [lindex $place 0]

            if {[lsearch -exact $list $where] < 0} {
                return -code error \
                    [BWidget::badOptionString placement $place $list]
            }

            ## If they specified a parent and didn't pass a second argument
            ## in the placement, set the placement relative to the parent.
            if {[string length $parent]} {
                if {[llength $place] == 1} { lappend place $parent }
            }

            set data(place) $place
        }

        "dialog" - "frame" {
            set data(bg)     [Widget::getoption $cal -calendarbackground]
            set data(font)   [Widget::getoption $cal -font]
            set data(ipadx)  [Widget::getoption $cal -ipadx]
            set data(ipady)  [Widget::getoption $cal -ipady]
            set data(place)  [Widget::getoption $cal -place]
            set data(header) [Widget::getoption $cal -showheader]
        }
    }

    _calculate_font_size $path

    set type [Widget::getoption $cal -type]
    return [eval [list Calendar::_create_$type $path] $args]
}


proc Calendar::cget { path option } {
    return [Widget::cget $path#Calendar $option]
}


proc Calendar::configure { path args } {
    set cal $path#Calendar

    Widget::getVariable $cal data

    set type  [Widget::getoption $cal -type]
    set popup $data(popup)

    set res [Widget::configure $cal $args]

    set redraw [Widget::anyChangedX $cal -foreground \
                    -disabledforeground -days -selectbackground \
                    -selectforeground -calendarbackground -popupfont \
                    -popupbackground]

    if {[Widget::hasChanged $cal -title title]} {
        wm title $path $title
    }

    if {[Widget::hasChanged $cal -background bg]} {
        switch -- $type {
            "dialog" {
                $path.bbox   configure -background $bg
                $path.frame  configure -background $bg
                $path:cmd    configure -background $bg
            }

            "frame" - "popup" {
                $path:cmd configure -background $bg
            }
        }
    }

    if {[Widget::hasChanged $cal -font font]} {
        set redraw 1
    }

    if {[Widget::hasChanged $cal -month month]} {
        set data(month) $month
        set redraw 1
    }

    if {[Widget::hasChanged $cal -year year]} {
        set data(year) $year
        set redraw 1
    }

    if {!$popup && [Widget::anyChangedX $cal -repeatdelay -repeatinterval]} {
        set repdelay [Widget::getoption $cal -repeatdelay]
        set repinter [Widget::getoption $cal -repeatinterval]

        $data(frame).header.back configure \
            -repeatinterval $repinter -repeatdelay $repdelay
        $data(frame).header.next configure \
            -repeatinterval $repinter -repeatdelay $repdelay
    }

    if {$redraw} {
        switch -- $type {
            "popup" {
                set data(bg)     [Widget::getoption $cal -popupbackground]
                set data(font)   [Widget::getoption $cal -popupfont]
            }

            "dialog" - "frame" {
                set data(bg)     [Widget::getoption $cal -calendarbackground]
                set data(font)   [Widget::getoption $cal -font]
            }
        }

        _calculate_font_size $path

        _redraw $path
    }

    return $res
}


proc Calendar::dates { path {inSeconds 0} } {
    set cal $path#Calendar

    Widget::getVariable $cal data

    set dates  [list]
    set format [Widget::getoption $cal -format]
    foreach date [lsort -integer $data(dates)] {
        if {!$inSeconds} { set date [clock format $date -format $format] }
        lappend dates $date
    }

    return $dates
}


proc Calendar::_create_frame { path args } {
    Widget::init Calendar $path $args

    set cal $path#Calendar

    Widget::getVariable $cal data

    set bg [Widget::getoption $cal -background]
    eval [list ::frame $path] [list -bg $bg -class Calendar]
    Widget::create Calendar $path

    set data(frame) $path

    Calendar::_build_calendar $path $data(frame)

    return $path
}


proc Calendar::_create_dialog { path args } {
    set cal $path#Calendar

    Widget::getVariable $cal data

    set args [list -anchor e -separator 1 -class Calendar]
    lappend args -place      [Widget::getoption $cal -place]
    lappend args -title      [Widget::getoption $cal -title]
    lappend args -parent     [Widget::getoption $cal -parent]
    lappend args -background [Widget::getoption $cal -background]

    eval [list Dialog::create $path] $args
    wm resizable $path 0 0

    set data(frame) [Dialog::getframe $path]

    Calendar::_build_calendar $path $data(frame)

    Dialog::add $path -text "OK"     -width 12
    Dialog::add $path -text "Cancel" -width 12

    set res [Dialog::draw $path]

    set dates [list]
    if {!$res} { set dates [Calendar::dates $path] }

    destroy $path

    return $dates
}


proc Calendar::_create_popup { path args } {
    Widget::init Calendar $path $args

    set cal $path#Calendar

    Widget::getVariable $cal data

    toplevel     $path -class Calendar
    wm withdraw  $path
    wm override  $path 1
    wm transient $path [winfo toplevel [winfo parent $path]]

    Widget::create Calendar $path

    set font [Widget::getoption $cal -popupfont]

    if {![string length $font]} {
        set font [Widget::getoption $cal -font]
        array set info [font actual $font]
        set data(font) [list $info(-family) 6]
    }

    set data(frame) $path

    Calendar::_build_calendar $path $data(frame)

    eval [list BWidget::place $path 0 0] $data(place)

    wm deiconify $path
    raise $path

    BWidget::grab set $path
    tkwait variable [Widget::widgetVar $cal data(dates)]
    BWidget::grab release $path

    if {![info exists data(dates)]} { return }

    if {[info exists data(custom)]} {
        set options [Widget::options $cal]
        puts "OPTIONS = $options"
        destroy $path
        return [eval [list Calendar $path] $options -type dialog]
    } else {
        set dates  [Calendar::dates $path]
        destroy $path
        return $dates
    }
}


proc Calendar::_build_calendar { path frame } {
    set cal $path#Calendar

    Widget::getVariable $cal data

    set place    [Widget::getoption $cal -place]
    set title    [Widget::getoption $cal -title]
    set parent   [Widget::getoption $cal -parent]
    set repdelay [Widget::getoption $cal -repeatdelay]
    set repinter [Widget::getoption $cal -repeatinterval]

    if {$data(header)} {
        if {$data(popup)} {
            Button $frame.header -font $data(font) -relief flat -bd 0 \
                -background $data(bg) -style Toolbutton \
                -command [list Calendar::_select_date $path "custom"] \
                -textvariable [Widget::widgetVar $cal data(month)]
            pack $frame.header -fill x
        } else {
            set header [::frame $frame.header -bg $data(bg)]
            pack $header -fill x ;# -pady 5

            grid rowconfigure $header 0 -weight 1

            ArrowButton $header.back -dir left -width 18 \
                -repeatdelay $repdelay -repeatinterval $repinter \
                -armcommand [list Calendar::_flip $path -]
            grid $header.back  -row 0 -column 0 -padx [list 5 0] -sticky ns

            ArrowButton $header.next -dir right -width 18 \
                -repeatdelay $repdelay -repeatinterval $repinter \
                -armcommand [list Calendar::_flip $path +]
            grid $header.next  -row 0 -column 3 -padx [list 0 5] -sticky ns

            set command [list Calendar::_redraw $path]

            ComboBox $header.month \
                -editable 1 -width 16 -height 12 -hottrack 1 \
                -text $data(month) \
                -values [Widget::getoption $cal -months] \
                -textvariable [Widget::widgetVar $cal data(month)] \
                -modifycmd $command
            grid $header.month -row 0 -column 1 -padx 5

            SpinBox $header.year \
                -editable 1 -width 8 -range [list 1492 2525 1] \
                -text $data(year) \
                -textvariable [Widget::widgetVar $cal data(year)] \
                -modifycmd $command -command $command
            grid $header.year  -row 0 -column 2 -padx 5
        }
    }

    if {[Widget::getoption $cal -titlemenus]} { ::menu $path.popup -tearoff 0 }

    set single     [string equal [Widget::getoption $cal -selectmode] "single"]
    set orient     [Widget::getoption $cal -orient]
    set hottrack   [Widget::getoption $cal -hottrack]
    set calendars  [Widget::getoption $cal -calendars]
    set separators [Widget::getoption $cal -showseparators]
    for {set i 0} {$i < $calendars} {incr i} {
        set canvas $frame.calendar$i
        ::canvas $canvas -background $data(bg) -highlightthickness 0
        if {$separators && $i != [expr {$calendars - 1}]} {
            if {[string equal $orient "vertical"]} {
                Separator $frame.sep$i -orient horizontal
            } else {
                Separator $frame.sep$i -orient vertical
            }
        }

        $canvas bind back <1> [list Calendar::_flip $path - $canvas]
        $canvas bind next <1> [list Calendar::_flip $path + $canvas]
        $canvas bind day  <1> [list Calendar::_select_date $path $canvas]

        if {$single
            && ![string equal [Widget::getoption $cal -type] "frame"]} {
            $canvas bind day <Double-1> "
                [list Calendar::_select_date $path $canvas]
                [list Dialog::invoke $path 0]
            "
        }

        if {$hottrack} {
            $canvas bind date <Enter> \
                [list Calendar::_highlight_date $path $canvas]
            $canvas bind date <Leave> \
                [list Calendar::_highlight_date $path $canvas ""]
        }
    }

    Calendar::_redraw $path
}


proc Calendar::_redraw { path } {
    set cal $path#Calendar

    Widget::getVariable $cal data
    set frame $data(frame)

    set month      $data(month)
    set year       $data(year)
    set orient     [Widget::getoption $cal -orient]
    set separators [Widget::getoption $cal -showseparators]

    Widget::setoption $cal -month $data(month)
    Widget::setoption $cal -year  $data(year)

    if {$data(popup) && ![BWidget::using ttk]} {
        $frame.header configure -background $data(bg)
    }

    for {set i 0} {$i < [Widget::getoption $cal -calendars]} {incr i} {
        set calendar $frame.calendar$i

        $calendar configure -background $data(bg)

        set side left
        set fill y
        if {[string equal $orient "vertical"]} { set side top; set fill x }
        pack $calendar -side $side -padx 2 -pady 2

        if {$separators && [winfo exists $frame.sep$i]} {
            pack $frame.sep$i -side $side -fill $fill
        }

        _redraw_calendar $path $frame.calendar$i $month $year $i
        BWidget::lassign [_next_month_year $month $year] month year
    }

    if {[string equal [Widget::getoption $cal -type] "dialog"]} {
        wm geometry $path {}
    }
}


proc Calendar::_redraw_calendar { path canvas month year calnum } {
    variable _days

    set cal $path#Calendar

    Widget::getVariable $cal data
    
    set num    [Widget::getoption $cal -calendars]
    set type   [Widget::getoption $cal -type]
    set start  [Widget::getoption $cal -startday]
    set extra  [Widget::getoption $cal -showleaddays]
    set format [Widget::getoption $cal -format]

    set idx    [lsearch -exact $_days $start]
    set incrX  [expr {$data(sizeX) + $data(ipadx)}]
    set incrY  [expr {$data(sizeY) + $data(ipady)}]
    set startX [expr {$incrX / 2}]
    set startY [expr {$incrY / 2}]
    set width  [expr {$incrX * 7}]
    set height [expr {$incrY * 7}]

    set days  [Widget::getoption $cal -days]
    
    $canvas delete items

    set x $startX
    set y $startY
    set count 0

    if {[Widget::getoption $cal -showtitles]
        && (!$data(header) || ![string equal $type "popup"])} {
        $canvas create text [expr {$width / 2}] $y \
            -text "$month  $year" -font $data(font) -tags [list title items]
        incr y $incrY
        incr height $incrY

        if {[Widget::getoption $cal -titlemenus]} {
            set cmd Calendar::_post_title_menu
            $canvas bind title <1> [list $cmd $path $month $year $calnum %X %Y]
        }
    }

    ## Draw the days of the week across the top.
    for {set i $idx} {$i < [expr {$idx + 7}]} {incr i} {
        set day [lindex $days [expr {$i % 7}]]
        $canvas create text $x $y -text $day -font $data(font) \
            -tags [list header items]
        incr x $incrX
    }

    ## Add a line between the days of the week and the main calendar.
    incr y $startY
    $canvas create line [list 0 $y $x $y] -fill #B8B8B8 -tags items
    incr y $startY

    set start [clock format [clock scan "1-$month-$year"] -format %A]
    set idx   [lsearch -exact $_days [string tolower $start]]

    set dfg [Widget::getoption $cal -disabledforeground]

    if {$extra && (($num == 1) || ($num > 1 && $calnum == 0))} {
        ## Draw the lead days at the head of the month.
        BWidget::lassign [_last_month_year $month $year] lastMonth lastYear
        set x     $startX
        set max   [_days_in_month "1-$lastMonth-$lastYear"]
        set start [expr {$idx - 1}]
        if {$start < 0} { set start 6 }
        for {set i $start} {$i >= 0} {incr i -1; incr count} {
            set day [expr {$max - $i}]
            set date "$day-$lastMonth-$lastYear"
            set date [clock format [clock scan $date] -format %D]
            $canvas create text $x $y -text $day -font $data(font) \
                -tags [list $date disabled back date items] -fill $dfg
            
            incr x $incrX
        }

        if {!$idx} {
            set  x $startX
            incr y $incrY
        }
    } else {
        incr count $idx
        set x [expr {$startX + ($incrX * $idx)}]
    }

    ## Draw all the days in the month.
    set max [_days_in_month "1-$month-$year"]
    for {set i 1; set j [expr {$idx + 1}]} {$i <= $max} {incr i; incr j} {
        set date "$i-$month-$year"
        set date [clock format [clock scan $date] -format %D]
        $canvas create text $x $y -text $i -font $data(font) \
            -tags [list $date day date items]

        incr x $incrX
        if {![expr {$j % 7}]} { set x $startX; incr y $incrY }
        incr count
    }

    if {$extra && (($num == 1) || ($num > 1 && $calnum == [expr {$num - 1}]))} {
        ## Draw the lead days at the end of the month.
        BWidget::lassign [_next_month_year $month $year] nextMonth nextYear
        for {set i 1} {$count < 42} {incr i; incr j; incr count} {
            set date "$i-$nextMonth-$nextYear"
            set date [clock format [clock scan $date] -format %D]
            $canvas create text $x $y -text $i -font $data(font) \
                -tags [list $date disabled next date items] -fill $dfg
            incr x $incrX
            if {![expr {$j % 7}]} { set x $startX; incr y $incrY }
        }
    }

    foreach date $data(dates) {
        set date [clock format $date -format %D]
        _highlight_date $path $canvas $date
    }

    $canvas configure -width $width -height $height
}


proc Calendar::_days_in_month { date } {
    set seconds [clock scan $date]
    BWidget::lassign [clock format $seconds -format "%B %Y"] month year
    BWidget::lassign [_next_month_year $month $year] nextMonth nextYear

    set date "1-$nextMonth-$nextYear - 1 day"
    return [clock format [clock scan $date] -format "%d"]
}


proc Calendar::_last_month_year { month year } {
    set date "1-$month-$year - 1 month"
    return [clock format [clock scan $date] -format "%B %Y"]
}


proc Calendar::_next_month_year { month year } {
    set date "1-$month-$year + 1 month"
    return [clock format [clock scan $date] -format "%B %Y"]
}


proc Calendar::_flip { path dir {canvas ""} } {
    set cal $path#Calendar

    Widget::getVariable $cal data

    set type  [Widget::getoption $cal -type]
    set month $data(month)
    set year  $data(year)

    set day "1-$month-$year"
    set day [clock format [clock scan "$day $dir 1 month"] -format %D]

    set data(month) [clock format [clock scan $day] -format "%B"]
    set data(year)  [clock format [clock scan $day] -format "%Y"]

    Widget::setoption $cal -month $data(month)
    Widget::setoption $cal -year  $data(year)

    set frame $path.calendar
    if {[string equal $type "dialog"]} {
        set frame [Dialog::getframe $path].calendar
        if {![string equal $canvas ""]} { _select_date $path $canvas }
    }

    event generate $path <<CalendarChange>>

    Calendar::_redraw $path
}


proc Calendar::_select_date { path canvas {item current} } {
    set cal $path#Calendar

    Widget::getVariable $cal data
    set frame $data(frame)

    if {[string equal $canvas "custom"]} {
        set data(dates)  [list]
        set data(custom) 1
        return
    }

    set item [$canvas find withtag $item]
    set tags [$canvas gettags $item]

    set date [lindex $tags 0]
    set secs [clock scan $date]

    set fg     [Widget::getoption $cal -foreground]
    set format [Widget::getoption $cal -format]
    if {[string equal [Widget::getoption $cal -selectmode] "multiple"]} {
        if {[lsearch -exact $data(dates) $secs] > -1} {
            set data(dates) [BWidget::lremove $data(dates) $secs]
            $canvas delete select-$date
            $canvas itemconfigure $date -fill $fg
        } else {
            lappend data(dates) $secs
            _highlight_date $path $canvas $item
        }
    } else {
        if {[llength $data(dates)]} {
            set calendars [Widget::getoption $cal -calendars]
            foreach date $data(dates) {
                set date [clock format $date -format %D]
                for {set i 0} {$i < $calendars} {incr i} {
                    $frame.calendar$i delete select-$date
                    $frame.calendar$i itemconfigure $date -fill $fg
                }
            }
        }
        set data(dates) $secs
        _highlight_date $path $canvas $item
    }

    Widget::setoption $cal -dates $data(dates)

    event generate $path <<CalendarSelect>>
}


proc Calendar::_highlight_date { path canvas {item current} } {
    set cal $path#Calendar

    Widget::getVariable $cal data

    set bg [Widget::getoption $cal -selectbackground]
    set fg [Widget::getoption $cal -selectforeground]

    set hottrack 0
    if {[string equal $item "current"]} { set hottrack 1 }
    set item [$canvas find withtag $item]

    if {[string equal $item ""]} {
        $canvas delete hottrack

        ## Reconfigure the previously highlighted item's foreground.
        if {![string equal $data(hottrack) ""]} {
            set tags [$canvas gettags $data(hottrack)]
            if {[lsearch -exact $tags "disabled"] > -1} {
                set fg [Widget::getoption $cal -disabledforeground]
            } elseif {![_is_selected $path $data(hottrack)]} {
                set fg [Widget::getoption $cal -foreground]
            }

            $canvas itemconfigure $data(hottrack) -fill $fg
        }
        return
    }

    BWidget::lassign [$canvas coords $item] x y

    set x2 [expr {$data(sizeX) / 2}]
    set y2 [expr {$data(sizeY) / 2}]
    set x0 [expr {$x - 3 - $x2}]
    set x1 [expr {$x + 3 + $x2}]
    set y0 [expr {$y - 2 - $y2}]
    set y1 [expr {$y + 2 + $y2}]

    set date [lindex [$canvas gettags $item] 0]

    if {!$hottrack} {
        $canvas create rect [list $x0 $y0 $x1 $y1] \
            -fill $bg -tags [list select-$date items]
        $canvas itemconfigure $item -fill $fg
        $canvas lower select-$date
    } else {
        set data(hottrack) $date

        BWidget::lassign [BWidget::get3dcolor $canvas $bg] dark light
        
        set coords [list $x0 $y0 $x1 $y1]
        BWidget::DrawCanvasBorder $canvas rounded $bg $coords \
            -outline $dark -fill $light -tags hottrack

        $canvas itemconfigure $item -fill $fg
        $canvas lower hottrack
    }
}


proc Calendar::_is_selected { path date } {
    set cal $path#Calendar
    Widget::getVariable $cal data
    set secs [clock scan $date]
    return [expr [lsearch -exact $data(dates) $secs] > -1]
}


proc Calendar::_calculate_font_size { path } {
    set cal $path#Calendar
    Widget::getVariable $cal data

    set data(sizeX) 0
    foreach day [Widget::getoption $cal -days] {
        set x [font measure $data(font) $day]
        if {$x > $data(sizeX)} { set data(sizeX) $x }
    }

    for {set i 1} {$i <= 31} {incr i} {
        set x [font measure $data(font) $i]
        if {$x > $data(sizeX)} { set data(sizeX) $x }
    }

    array set tmp [font metrics $data(font)]
    set data(sizeY) $tmp(-linespace)
}


proc Calendar::_post_title_menu { path month year calnum X Y } {
    set cal $path#Calendar

    Widget::getVariable $cal data

    set menu $path.popup

    $menu delete 0 end

    for {set i -3} {$i <= 3} {incr i} {
        if {$i > 0} { set i +$i }
        set secs [clock scan "1-$month-$year $i months"]
        set text [clock format $secs -format "%B %Y"]
        $menu insert end command -label $text -font $data(font) \
            -command [list Calendar::_select_title_month $path $text $calnum]
    }

    update idletasks
    set x [expr {[winfo reqwidth $menu] / 2}]
    $menu activate 3
    set y [expr {[$menu yposition 3] + ($data(sizeY) / 2)}]

    $menu post [expr {$X - $x}] [expr {$Y - $y}]
}


proc Calendar::_select_title_month { path date calnum } {
    set cal $path#Calendar

    Widget::getVariable $cal data

    set date 1-[join $date -]
    set secs [clock scan "$date - $calnum months"]
    BWidget::lassign [clock format $secs -format "%B %Y"] data(month) data(year)

    Widget::setoption $cal -month $data(month)
    Widget::setoption $cal -year  $data(year)

    event generate $path <<CalendarChange>>

    _redraw $path
}


proc Calendar::_destroy { path } {
    Widget::destroy $path
    Widget::destroy $path#Calendar
}
Added lib/BWidget/choosedir.tcl.






































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
namespace eval ChooseDirectory {
    Widget::define ChooseDirectory choosedir Dialog ScrolledWindow \
        Tree IconLibrary

    Widget::bwinclude ChooseDirectory Dialog :cmd

    Widget::declare ChooseDirectory {
        {-name          String   ""        1}
        {-message       String   "Please choose a directory, then select OK." 0}
        {-folders       String   ""        0}
        {-newfoldertext String   "Make New Folder" 0}
        {-oktext        String   ""        0}
        {-canceltext    String   ""        0}
        {-initialdir    String   ""        0}
        {-includevfs    Boolean  "0"       0}
    }

    bind ChooseDirectory <Destroy> [list ChooseDirectory::_destroy %W]
}


proc ChooseDirectory::create { path args } {
    variable dialogs

    BWidget::LoadBWidgetIconLibrary

    set dialog $path#choosedir

    array set maps [Widget::splitArgs $args Dialog ChooseDirectory]

    Widget::initFromODB ChooseDirectory $dialog $maps(ChooseDirectory)

    Widget::getVariable $dialog nodes
    set nodes(count) 0

    eval [list Dialog::create $path -class ChooseDirectory \
        -anchor e -default 1 -cancel 2 -modal local -spacing 5 -homogeneous 0 \
        -title "Browse for Folder"] $maps(:cmd) $maps(Dialog)
    wm minsize  $path 340 300
    wm protocol $path WM_DELETE_WINDOW [list $path cancel]

    Widget::getVariable $path folder

    set frame [Dialog::getframe $path]

    grid rowconfigure    $frame 3 -weight 1
    grid columnconfigure $frame 0 -weight 1

    Label $frame.message -anchor w -autowrap 1 -justify left \
        -text [Widget::getoption $dialog -message]
    grid  $frame.message -row 0 -column 0 -sticky new -pady 5

    if {[BWidget::using ttk]} {
        ttk::entry $frame.e -textvariable [Widget::widgetVar $path folder]
    } else {
        entry $frame.e -textvariable [Widget::widgetVar $path folder]
    }
    grid $frame.e -row 2 -column 0 -sticky ew -pady 2 -padx 1
    trace add variable [Widget::widgetVar $path folder] write \
        [list ChooseDirectory::_update_ok_button $path]

    ScrolledWindow $frame.sw
    grid $frame.sw -row 3 -column 0 -sticky news

    set tree $frame.tree
    Tree $tree -width 35 \
        -opencmd  [list ChooseDirectory::_open_directory $path $tree] \
        -closecmd [list ChooseDirectory::_close_directory $path $tree]

    $frame.sw setwidget $tree

    bind $tree <<TreeSelect>> \
        [list ChooseDirectory::_selection_change $path $tree]

    set text [Widget::getoption $dialog -newfoldertext]
    Dialog::add $path -text " $text " -spacing 20 -state disabled \
        -command [list ChooseDirectory::_create_directory $path $tree]

    set text [Widget::getoption $dialog -oktext]
    if {$text eq ""} {
        Dialog::add $path -name ok -width 12 \
            -command [list ChooseDirectory::_validate_directory $path]
    } else {
        Dialog::add $path -text $text -width 12 \
            -command [list ChooseDirectory::_validate_directory $path]
    }

    set text [Widget::getoption $dialog -canceltext]
    if {$text eq ""} {
        Dialog::add $path -name cancel -width 12
    } else {
        Dialog::add $path -text $text -width 12
    }

    set initdir [Widget::getoption $dialog -initialdir]
    if {$initdir eq ""} {
        set cwd [pwd]
    } else {
        set cwd $initdir
    }
    set cwd [file normalize $cwd]

    set folders [Widget::getoption $dialog -folders]
    if {![llength $folders]} {
        set desktop   [file normalize [file join ~ Desktop]]
        set documents [file normalize [file join ~ Documents]]

        set desktopText   "Desktop"
        set documentsText "Documents"
        if {[info exists ::env(HOME)]} {
            if {$::tcl_platform(platform) eq "windows"} {
                foreach text {"Documents" "My Documents"} {
                    set dir [file join ~ $text]
                    if {[file exists $dir]} {
                        set documents     $dir
                        set documentsText $text
                        break
                    }
                }
            } else {
                lappend folders [list [file normalize ~] "Home"]
            }
        }

        if {[file exists $desktop]} {
            lappend folders [list [file normalize $desktop] $desktopText]
        }

        if {[file exists $documents]} {
            lappend folders [list [file normalize $documents] $documentsText]
        }

        if {$::tcl_platform(platform) eq "windows"} {
            foreach volume [file volumes] {
                set volume [string toupper $volume]
                if {[string match "?:/" $volume]} {
                    lappend volumes $volume
                    lappend folders [list $volume [string range $volume 0 1]]
                }
            }

            set volume [lindex [file split $cwd] 0]
            if {[lsearch -exact $volumes $volume] < 0} {
                lappend folders [list $volume $volume]
            }
        } else {
            lappend folders [list / /]
        }
    }

    foreach list $folders {
        set dir   [lindex $list 0]
        set text  [lindex $list 1]
        set image [lindex $list 2]

        if {![string length $image]} { set image [BWidget::Icon folder16] }

        set nodes(root,$dir) [incr nodes(count)]
        $tree insert end root $nodes(root,$dir) -text $text -image $image \
            -data $dir -drawcross allways
    }

    set name [Widget::getoption $dialog -name]
    if {[info exists dialogs($name)]} { set cwd $dialogs($name) }

    if {[file exists $cwd]} {
        set dirpath [list]
        foreach sub [file split $cwd] {
            if {![llength $dirpath]} {
                set node $nodes(root,$sub)
                set rootNode $node

                lappend dirpath $sub
                $tree itemconfigure $node -open 1
            } else {
                set parent $node
                lappend dirpath $sub
                set subpath [eval file join $dirpath]

                if {![info exists nodes($rootNode,$subpath)]} {
                    set nodes($rootNode,$subpath) [incr nodes(count)]
                    $tree insert end $parent $nodes($rootNode,$subpath) \
                        -open 1 -image [BWidget::Icon folder16] -text $sub \
                        -data $subpath
                }
                set node $nodes($rootNode,$subpath)
            }

            ChooseDirectory::_open_directory $path $tree $node
        }

        _select_directory $path $tree $node
    } elseif {$initdir ne ""} {
        set folder [file nativename [file normalize $initdir]]
    }

    $frame.e selection range 0 end

    set result [Dialog::draw $path $frame.e]

    set dir $folder

    destroy $path

    if {$result == 2} { return }

    if {[string length $name]} { set dialogs($name) $dir }

    return $dir
}


proc ChooseDirectory::_select_directory { path tree node } {
    $tree see $node
    $tree selection set $node
    ChooseDirectory::_selection_change $path $tree
}


proc ChooseDirectory::_selection_change { path tree } {
    Widget::getVariable $path folder

    set node   [$tree selection get]
    set folder [file nativename [$tree itemcget $node -data]]

    [$path getframe].e selection clear

    if {[file writable $folder]} {
        ButtonBox::itemconfigure $path.bbox 0 -state normal
    } else {
        ButtonBox::itemconfigure $path.bbox 0 -state disabled
    }
}


proc ChooseDirectory::_open_directory { path tree node } {
    Widget::getVariable $path#choosedir nodes

    set parent   [$tree parent $node]
    set rootNode $node
    while {$parent ne "root"} {
        set rootNode $parent
        set parent   [$tree parent $parent]
    }

    set sort -ascii
    if {$::tcl_platform(platform) eq "windows"} { set sort -dict }

    set rootdir [$tree itemcget $node -data]

    set dirs [glob -nocomplain -type d -dir $rootdir *]
    eval lappend dirs [glob -nocomplain -type {d hidden} -dir $rootdir *]

    set found 0
    set include [Widget::getoption $path#choosedir -includevfs]
    foreach dir [lsort $sort $dirs] {
        if {!$include && [string match "*vfs*" [file system $dir]]} { continue }
        set tail [file tail $dir]
        if {$tail eq "." || $tail eq ".."} { continue }

        set found 1
        if {![info exists nodes($rootNode,$dir)]} {
            set nodes($rootNode,$dir) [incr nodes(count)]
            $tree insert end $node $nodes($rootNode,$dir) \
                -drawcross allways -image [BWidget::Icon folder16] \
                -text [file tail $dir] -data $dir
        }
    }

    set opts [list -open 1 -image [BWidget::Icon folderopen16]]

    if {!$found} { lappend opts -drawcross never }
    eval [list $tree itemconfigure $node] $opts
}


proc ChooseDirectory::_close_directory { path tree node } {
    $tree itemconfigure $node -image [BWidget::Icon folder16]
}


proc ChooseDirectory::_next_directory { root text } {
    set i 1
    set dir [file join $root $text]
    while {[file exists $dir]} {
        set dir [file join $root "$text ([incr i])"]
    }
    return $dir
}


proc ChooseDirectory::_create_directory { path tree } {
    Widget::getVariable $path folder
    Widget::getVariable $path#choosedir nodes

    set sel [lindex [$tree selection get] 0]
    $tree itemconfigure $sel -open 1

    set text [_next_directory $folder "New Folder"]
    set i [$tree insert end $sel new#auto -text [file tail $text] \
        -image [BWidget::Icon folder16]]

    $tree edit $i [file tail $text] \
        [list ChooseDirectory::_verify_new_directory $path $tree $i] 1

    set dir [file join $folder [$tree itemcget $i -text]]

    set parent   [$tree parent $sel]
    set rootNode $sel
    while {$parent ne "root"} {
        set rootNode $parent
        set parent   [$tree parent $parent]
    }

    set nodes($rootNode,$dir) [incr nodes(count)]
    set node $nodes($rootNode,$dir)

    $tree delete $i
    $tree insert end $sel $node -text [file tail $dir] -data $dir \
        -image [BWidget::Icon folder16]

    _select_directory $path $tree $node

    file mkdir $dir
}


proc ChooseDirectory::_verify_new_directory { path tree node newtext } {
    Widget::getVariable $path folder

    set txt [$tree itemcget $node -text]
    if {![string length $newtext]} { set newtext $txt }

    set dir [file join $folder $newtext]

    if {[regexp {[/\\:\*\?\"<>|]} $newtext]} {
        set title  "Error Renaming File or Folder"
        set msg "A directory name cannot contain any of the following\
            characters:\n\t\\ / : * ? \" < > |"
        tk_messageBox -parent $path -icon error -title $title -message $msg
        return 0
    }

    if {[file exists $dir]} {
        set title  "Error Renaming File or Folder"
        set    msg "Cannot rename $txt: A file with the name you specified "
        append msg "already exists. Specify a different file name."
        tk_messageBox -parent $path -icon error -title $title -message $msg
        return 0
    }

    $tree itemconfigure $node -text $newtext
    return 1
}


proc ChooseDirectory::_update_ok_button { path args } {
    if {[Widget::exists $path]} {
        Widget::getVariable $path folder
        if {[string trim $folder] eq ""} {
            ButtonBox::itemconfigure $path.bbox 1 -state disabled
        } else {
            ButtonBox::itemconfigure $path.bbox 1 -state normal
        }
    }
}


proc ChooseDirectory::_validate_directory { path } {
    Widget::getVariable $path folder

    set dir $folder
    if {[file pathtype $dir] eq "relative"} {
        set dir [file join [pwd] $dir]
    }
    set dirs [file split $dir]
    if {$::tcl_platform(platform) eq "windows"} {
        set drive [lindex $dirs 0]
        if {[string match {[a-zA-Z]:/} $drive]} {
            set dirs [lrange $dirs 1 end]
        }
    }

    foreach dir $dirs {
        if {[regexp {[:\*\?\"<>|]} $dir]} {
            set title  "Error in Folder Name"
            set msg "A directory name cannot contain any of the following\
                characters:\n\t\\ / : * ? \" < > |"
            tk_messageBox -parent $path -icon error -title $title -message $msg
            return
        }
    }

    set folder [file normalize $folder]

    $path enddialog 1
}


proc ChooseDirectory::_destroy { path } {
    Widget::destroy $path#choosedir
    Widget::destroy $path
}
Added lib/BWidget/choosefile.tcl.


































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
## TODO
##
## Need to handle details view.  Turn on the view menubutton when we do.
##
## Need to handle the autoposting and type-ahead on the file combobox.
## Turn it back into a combobox when we do.
##

namespace eval ChooseFile {
    if {[BWidget::using ttk]} {
        Widget::define ChooseFile choosefile Dialog ScrolledWindow \
            ListBox IconLibrary
    } else {
        Widget::define ChooseFile choosefile Dialog ScrolledWindow \
            ComboBox ListBox IconLibrary
    }

    Widget::bwinclude ChooseFile Dialog :cmd

    Widget::declare ChooseFile {
        {-name             String   ""         1}
        {-type             Enum     "open"     0 {open save}}
        {-folders          String   ""         0}
        {-restrictdir      Boolean  0          0}
        {-defaultextension String   ""         0}
        {-filetypes        String   ""         0}
        {-initialdir       String   ""         0}
        {-initialfile      String   ""         0}
        {-multiple         Boolean  0          0}
        {-message          String   ""         0}
        {-title            String   ""         0}
        {-includevfs       Boolean  0          0}
    }

    bind ChooseFile <Map>     [list ChooseFile::_map %W]
    bind ChooseFile <Destroy> [list ChooseFile::_destroy %W]
}


proc ChooseFile::create { path args } {
    variable dialogs

    BWidget::LoadBWidgetIconLibrary

    set dialog $path#choosefile

    array set maps [Widget::splitArgs $args Dialog ChooseFile]

    Widget::initFromODB ChooseFile $dialog $maps(ChooseFile)

    Widget::getVariable $dialog data

    set data(histidx)    0
    set data(history)    [list]
    set data(realized)   0
    set data(showHidden) 0

    set n [expr {20 / [set x [font measure TkTextFont " "]]}]
    if {$x * $n < 20} { incr n }
    set data(comboSpaces) $n
    set data(listboxPadx) [expr {$n * $x}]

    set type [Widget::getoption $dialog -type]

    array set _args $args
    if {![info exists _args(-title)]} {
        if {$type eq "open"} {
            set title "Open"
        } elseif {$type eq "save"} {
            set title "Save As"
        }
    } else {
        set title $_args(-title)
    }

    Widget::setoption $dialog -title $title

    eval [list Dialog::create $path -class ChooseFile -geometry 400x250 \
        -modal local -title $title] $maps(:cmd) $maps(Dialog)
    wm minsize  $path 400 250
    wm protocol $path WM_DELETE_WINDOW [list ChooseFile::enddialog $path 0]
    bind $path <Escape> [list ChooseFile::enddialog $path 0]

    set frame [Dialog::getframe $path]

    grid rowconfigure    $frame 2 -weight 1
    grid columnconfigure $frame 1 -weight 1

    set pady 2
    set message [Widget::getoption $dialog -message]

    if {[string length $message]} {
        set pady 0
        Label $frame.message -anchor w -autowrap 1 -justify left -text $message
        grid  $frame.message -row 0 -column 1 -sticky new -pady {0 5}
    }

    set f [frame $frame.top -height 26]
    grid $f -row 1 -column 1 -sticky ew -padx 5 -pady $pady

    label $f.l -text "Look in:"
    pack  $f.l -side left

    set data(FolderCombo) $f.cb

    if {[BWidget::using ttk]} {
        set comboBoxCmd   ttk::combobox
        set comboBoxEvent <<ComboboxSelected>>
        set opts [list -style Toolbutton]
	set bwidth ""

        $comboBoxCmd $data(FolderCombo) -state readonly \
            -textvariable [Widget::widgetVar $dialog data(dirtail)]

        set popdown ::tile::combobox::PopdownShell
        if {![string length [info commands $popdown]]} {
            set popdown ::ttk::combobox::PopdownShell
        }
        set shell [$popdown $data(FolderCombo)]
        set listbox $shell.l
        destroy $listbox $shell.sb

        bind $shell <Unmap> [list after idle [list focus $frame.listbox]]

        ScrolledWindow $shell.sw
        grid $shell.sw -row 0 -column 0 -sticky news

        ListBox $listbox -borderwidth 2 -relief flat -deltay 18 \
            -highlightthickness 0 -selectmode single -selectfill 1 \
            -yscrollcommand [list $shell.sb set] -padx $data(listboxPadx)
        $shell.sw setwidget $listbox

        $listbox bindText  <1> \
            [list ChooseFile::_select_folder $path $data(FolderCombo)]
        $listbox bindImage <1> \
            [list ChooseFile::_select_folder $path $data(FolderCombo)]

        $listbox bindText  <Enter> [list $listbox selection set]
        $listbox bindImage <Enter> [list $listbox selection set]

        set data(FolderListBox) $listbox
    } else {
        set comboBoxCmd   ComboBox
        set comboBoxEvent <<ComboBoxSelected>>
        set opts [list -relief link]
	set bwidth 12

        $comboBoxCmd $data(FolderCombo) -editable 0 -usebwlistbox 1 \
            -hottrack 1 -textvariable [Widget::widgetVar $dialog data(dirtail)]

        set data(FolderListBox) [$data(FolderCombo) getlistbox]
        $data(FolderListBox) configure -deltay 18 -padx $data(listboxPadx)

        bind $data(FolderCombo) <<ComboBoxSelected>> \
            [list ChooseFile::_select_folder $path $data(FolderCombo)]
    }
    pack $data(FolderCombo) -side left -padx 5 -expand 1 -fill both

    set data(FolderIconLabel) [label $path.icon -bg #FFFFFF]

    ButtonBox $f.bbox -spacing 1
    pack $f.bbox -side left

    eval [list $f.bbox add -image [BWidget::Icon actback16] \
        -command [list ChooseFile::_back $path] \
        -helptext "Go To Last Folder Visited"] $opts

    eval [list $f.bbox add -image [BWidget::Icon actup16] \
        -command [list ChooseFile::_up $path] \
        -helptext "Up One Level"] $opts

    eval [list $f.bbox add -image [BWidget::Icon foldernew16] \
        -command [list ChooseFile::_create_directory $path] \
        -helptext "Create New Folder"] $opts

    if 0 {
    menu $path.viewPopup -tearoff 0
    $path.viewPopup add radiobutton -label "List"
    $path.viewPopup add radiobutton -label "Details"

    if {[BWidget::using ttk]} {
        ttk::menubutton $f.view -menu $path.viewPopup
    } else {
        menubutton $f.view -menu $path.viewPopup
    }
    $f.view configure -image [BWidget::Icon viewmulticolumn16]
    pack $f.view -side left
    } ; # if 0

    ScrolledWindow $frame.sw
    grid $frame.sw -row 2 -column 1 -sticky news -padx 5 -pady {2 5}

    set selectmode single
    if {[Widget::getoption $dialog -type] eq "open"
        && [Widget::getoption $dialog -multiple]} { set selectmode multiple }

    ListBox $frame.listbox -deltay 18 -multicolumn 1 -selectmode $selectmode
    $frame.sw setwidget $frame.listbox

    bind $frame.listbox <<ListboxSelect>> \
        [list ChooseFile::_update_selection $path]

    $frame.listbox bindText  <Double-1> [list ChooseFile::_double_click $path]
    $frame.listbox bindImage <Double-1> [list ChooseFile::_double_click $path]

    ttk::checkbutton $frame.hiddencb -text "Show hidden directories" \
        -variable [Widget::widgetVar $dialog data(showHidden)] \
        -command  [list ChooseFile::_refresh_view $path]
    grid $frame.hiddencb -row 3 -column 1 -sticky nw -padx 10 -pady 2

    set f [frame $frame.bottom]
    grid $f -row 4 -column 1 -sticky ew -padx 5

    grid columnconfigure $f 1 -weight 1

    label $f.fileNameL -text "File name:"
    grid  $f.fileNameL -row 0 -column 0 -pady 2

    set data(FileEntry) $f.fileNameCB

    #$comboBoxCmd $data(FileEntry) \
            #-textvariable [Widget::widgetVar $dialog data(filetail)]
    if {[BWidget::using ttk]} {
        ttk::entry $data(FileEntry) \
            -textvariable [Widget::widgetVar $dialog data(filetail)]
    } else {
        entry $data(FileEntry) \
            -textvariable [Widget::widgetVar $dialog data(filetail)]
    }
    grid $data(FileEntry) -row 0 -column 1 -padx 20 -pady 2 -sticky ew

    bind $data(FileEntry) <Return> [list ChooseFile::enddialog $path 1]

    focus $data(FileEntry)

    Button $f.ok -text [string totitle $type] -width $bwidth \
    	-command [list ChooseFile::enddialog $path 1]
    grid $f.ok -row 0 -column 2 -pady 2 -sticky ew

    label $f.fileTypeL -text "Files of type:"
    grid  $f.fileTypeL -row 1 -column 0 -pady 2

    $comboBoxCmd $f.fileTypeCB -state readonly \
        -textvariable [Widget::widgetVar $dialog data(filetype)]
    grid $f.fileTypeCB -row 1 -column 1 -pady 2 -padx 20 -sticky ew

    bind $f.fileTypeCB $comboBoxEvent [list ChooseFile::_select_filetype $path]

    Button $f.cancel -text "Cancel" -width $bwidth \
	-command [list ChooseFile::enddialog $path 0]
    grid $f.cancel -row 1 -column 2 -pady 2 -sticky ew

    ## Initialize the directory.
    set name       [Widget::getoption $dialog -name]
    set initialdir [Widget::getoption $dialog -initialdir]

    if {![string length $initialdir]} {
        if {[info exists dialogs($name)]} {
            set initialdir [lindex $dialogs($name) 0]
        } else {
            set initialdir [pwd]
        }
    }

    set initialfile [Widget::getoption $dialog -initialfile]
    if {![string length $initialfile]} {
        if {[info exists dialogs($name)]} {
            set initialfile [lindex $dialogs($name) 1]
        }
    }

    if {[string length $initialfile]} {
        set initialdir [file dirname $initialfile]
    }

    Widget::setoption $dialog -initialdir  [file normalize $initialdir]
    Widget::setoption $dialog -initialfile [file normalize $initialfile]

    ## Populate the filetypes combobox.
    set filetypes [Widget::getoption $dialog -filetypes]
    if {![llength $filetypes]} {
        set filetypes {{"All Files" *}}
    }

    foreach typelist $filetypes {
        set txt [lindex $typelist 0]
        foreach ext [lindex $typelist 1] {
        if {[string index $ext 0] ne "."} { set ext .$ext }
            set ext [file extension $ext]
        if {![info exists exts($txt)]} { lappend exts(list) $txt }
        lappend exts($txt) *$ext
    }
    }

    set first   1
    set default [Widget::getoption $dialog -defaultextension]
    foreach txt $exts(list) {
        set text "$txt ([join [lsort $exts($txt)] ,])"
        lappend values $text

        foreach ext $exts($txt) {
            set ext [file extension $ext]
            lappend data(filetype,$text) [string tolower $ext]
            if {$::tcl_platform(platform) ne "windows" && $ext ne ".*"} {
                lappend data(filetype,$text) [string toupper $ext]
            }
        }

        if {![info exists data(filetype)]} {
            if {[string length $default]} {
                foreach ext $exts($txt) {
                    if {$ext eq "*$default"} {
                        set data(filetype) $text
                    }
                }
            } else {
                if {$first} {
                    set first 0
                    set data(filetype) $text
                }
            }
        }
    }
    $f.fileTypeCB configure -values $values

    set result [Dialog::draw $path]

    set file ""
    if {$result} { set file $data(file) }

    destroy $path

    return $file
}


proc ChooseFile::enddialog { path result } {
    set dialog $path#choosefile
    Widget::getVariable $dialog data

    if {$result} {
        if {![info exists data(filetail)]} { return }

        set type [Widget::getoption $dialog -type]
        if {$type eq "save"} {
            set file [file join $data(directory) $data(filetail)]

            set ext [Widget::getoption $dialog -defaultextension]
            if {![string length [file extension $file]]} {
                set filetype [lindex $data(filetype,$data(filetype)) 0]
                if {$filetype ne ".*"} {
                    set ext [string range $filetype 1 end]
                }
                append file .$ext
            }

            if {[file exists $file]} {
                set title   [Widget::getoption $dialog -title]
                set message "$file already exists.\nDo you want to replace it?"
                set res [MessageDlg $path.__replaceFile -type yesno \
                    -icon warning -title $title -message $message]
                if {$res eq "no"} {
                    focus $data(FileEntry)
                    return
                }
            }

            set data(file) $file
        } elseif {$type eq "open"} {
            ## If it doesn't begin and end with a quote, it's a single file.
            if {![string match {"*"} $data(filetail)]} {
                set file [file join $data(directory) $data(filetail)]

                if {![file exists $file]} {
                    set tail    [file tail $file]
                    set title   [Widget::getoption $dialog -title]
                    set message "$tail\nFile not found.\nPlease\
                        verify the correct file name was given."
                    set res [MessageDlg $path.__replaceFile -type ok \
                        -icon warning -title $title -message $message]
                    focus $data(FileEntry)
                    return
                }

                if {[Widget::getoption $dialog -multiple]} {
                    set data(file) [list $file]
                } else {
                    set data(file) $file
                }
            } else {
                foreach tail $data(filetail) {
                    set file [file join $data(directory) $tail]

                    if {![file exists $file]} {
                        set title   [Widget::getoption $dialog -title]
                        set message "$tail\nFile not found.\nPlease\
                            verify the correct file name was given."
                        set res [MessageDlg $path.__replaceFile -type ok \
                            -icon warning -title $title -message $message]
                        focus $data(FileEntry)
                        return
                    }

                    lappend files $file
                }

                set data(file) $files
            }
        }
    }

    set [Widget::widgetVar $path data(result)] $result
}


proc ChooseFile::getlistbox { path } {
    return [Dialog::getframe $path].listbox
}


proc ChooseFile::_update_folders { path } {
    set dialog $path#choosefile

    Widget::getVariable $dialog data

    $data(FolderListBox) clear

    set folders  [Widget::getoption $dialog -folders]
    set restrict [Widget::getoption $dialog -restrictdir]
    if {!$restrict && ![llength $folders]} {
        set desktop     [file normalize [file join ~ Desktop]]
        set myDocuments [file normalize [file join ~ Documents]]
        if {[info exists ::env(HOME)]} {
            set desktopText Desktop

            if {$::tcl_platform(platform) eq "windows"} {
                set myDocumentsText "My Documents"
            } else {
                set myDocumentsText "Documents"
            }

            set desktop     [file join $::env(HOME) $desktopText]
            set myDocuments [file join $::env(HOME) $myDocumentsText]
        }

        if {$::tcl_platform(platform) ne "windows" && [file exists ~]} {
            lappend folders [list [file normalize ~] "Home"]
        }

        if {[file exists $desktop]} {
            lappend folders [list $desktop "Desktop"]
        }

        if {[file exists $myDocuments]} {
            lappend folders [list $myDocuments $myDocumentsText]
        }

        foreach volume [file volumes] {
            if {![string match "*vfs" [lindex [file system $volume] 0]]} {
                lappend folders [list $volume $volume]
            }
        }
    }

    if {!$restrict} {
        set i 0
        foreach list $folders {
            set dir   [file normalize [lindex $list 0]]
            set text  [lindex $list 1]
            set image [lindex $list 2]

            if {![string length $image]} { set image [BWidget::Icon folder16] }

            $data(FolderListBox) insert end #auto -text $text \
                -data $dir -image $image
            lappend values $text

            set folderdirs($dir) $i
            incr i
        }
    }

    set i       0
    set idx     end
    set dirlist [list]
    foreach x [file split $data(directory)] {
        lappend dirlist $x
        if {[info exists folderdirs($x)]} {
            set idx $folderdirs($x)
        } else {
            set dir [file normalize [eval file join $dirlist]]
            $data(FolderListBox) insert $idx #auto -text $x \
                -data $dir -indent [expr {$i * 20}] \
                -image [BWidget::Icon folder16]
            lappend values $x
        }

        incr i

        if {[string is integer $idx]} { incr idx }
    }

    if {[BWidget::using ttk]} {
        $data(FolderCombo) configure -values $values
    }
}


proc ChooseFile::_update_selection { path {item ""} } {
    Widget::getVariable $path#choosefile data

    set listbox [ChooseFile::getlistbox $path]
    if {[string length $item]} {
        set sel [list $item]
        $listbox selection set $item
    } else {
        set sel [$listbox selection get]
    }

    set files [list]
    foreach item $sel {
        if {![$listbox exists $item]} { continue }

        set file [$listbox itemcget $item -data]

        if {[file isfile $file]} {
            if {[llength $sel] == 1} {
                set files [file tail $file]
            } else {
            lappend files \"[file tail $file]\"
        }
    }
    }

    set data(filetail) [join $files " "]
}


proc ChooseFile::_double_click { path item } {
    Widget::getVariable $path#choosefile data

    set listbox [ChooseFile::getlistbox $path]

    set file [$listbox itemcget $item -data]

    if {[file isfile $file]} {
        set data(file)     [file normalize $file]
        set data(filetail) [file tail $data(file)]
        ChooseFile::enddialog $path 1
    } else {
        ChooseFile::_select_directory $path $file
    }
}


proc ChooseFile::_refresh_view { path } {
    Widget::getVariable $path#choosefile data
    ChooseFile::_select_directory $path $data(directory)
}


proc ChooseFile::_select_directory { path directory {appendHistory 1} } {
    set dialog $path#choosefile

    Widget::getVariable $dialog data

    set directory  [file normalize $directory]
    set initialdir [Widget::getoption $dialog -initialdir]

    ## Configure the up button.  If -restrictdir is true, the user
    ## can only go up as far as the -initialdir.
    [Dialog::getframe $path].top.bbox.b1 configure -state normal
    if {[Widget::getoption $dialog -restrictdir]} {
        if {$directory eq $initialdir} {
            [Dialog::getframe $path].top.bbox.b1 configure -state disabled
        }

        ## If this directory isn't underneath our initial directory,
        ## restrict them back to the initialdir.
        if {![string match $initialdir* $directory]} {
            set directory $initialdir
        }
    }

    ## If we're at the top of the drive, disable the up button.
    if {[file dirname $directory] eq $directory} {
        [Dialog::getframe $path].top.bbox.b1 configure -state disabled
    }

    set data(directory) $directory
    set data(dirtail)   [file tail $data(directory)]
    if {![string length $data(dirtail)]} { set data(dirtail) $directory }

    if {$appendHistory} {
        lappend data(history) $data(directory)
        set data(histidx) [expr {[llength $data(history)] - 1}]
    }

    ## Configure the back button.
    if {$data(histidx) == 0} {
        [Dialog::getframe $path].top.bbox.b0 configure -state disabled
    } else {
        [Dialog::getframe $path].top.bbox.b0 configure -state normal
    }

    ## Set the combobox value with enough room to the left
    ## to place our icon.
    set n $data(comboSpaces)
    set data(dirtail) [string repeat " " $n]$data(dirtail)
    if {![BWidget::using ttk]} {
        $data(FolderCombo).e selection clear
    }

    ChooseFile::_update_folders $path

    ## Place a label with the icon for this folder over the top
    ## of the folder combobox to the left of the directory.
    place forget $data(FolderIconLabel)
    foreach item [$data(FolderListBox) items] {
        if {$directory eq [$data(FolderListBox) itemcget $item -data]} {
            $data(FolderIconLabel) configure \
                -image [$data(FolderListBox) itemcget $item -image]
            set y [expr {[winfo height $data(FolderCombo)] / 2}]
            place $data(FolderIconLabel) -x 4 -y $y -anchor w \
                -in $data(FolderCombo)
            break
        }
    }

    set listbox [ChooseFile::getlistbox $path]

    $listbox clear

    set sort -ascii
    if {$::tcl_platform(platform) eq "windows"} { set sort -dict }

    set dirs [glob -nocomplain -dir $directory -type d *]
    if {$data(showHidden)} {
        eval lappend dirs [glob -nocomplain -dir $directory -type {d hidden} *]
    }

    set include [Widget::getoption $dialog -includevfs]
    foreach dir [lsort $sort $dirs] {
        if {!$include && [string match "*vfs*" [file system $dir]]} { continue }
        set tail [file tail $dir]
        if {$tail eq "." || $tail eq ".."} { continue }
        $listbox insert end #auto -text [file tail $dir] -data $dir \
            -image [BWidget::Icon folder16]
    }

    set windows [expr {$::tcl_platform(platform) eq "windows"}]
    set files [list]

    if {$data(filetype,$data(filetype)) eq ".*"} {
        set patt *
    } else {
        set patt "*\{[join $data(filetype,$data(filetype)) ,]\}"
    }

    eval lappend files [glob -nocomplain -dir $directory -type f $patt]
    eval lappend files [glob -nocomplain -dir $directory -type {f hidden} $patt]

    set initialfile [Widget::getoption $dialog -initialfile]
    foreach file [lsort $sort $files] {
        set tail [file tail $file]
        if {$windows && [file extension $tail] eq ".lnk"} {
            set tail [file root $tail]
        }
        set i [$listbox insert end #auto -text $tail \
            -data $file -image [BWidget::Icon mimeunknown16]]
        if {!$data(realized) && $file eq $initialfile} {
            $listbox selection set $i
        }
    }
}


proc ChooseFile::_select_folder { path combo {item ""} } {
    Widget::getVariable $path#choosefile data

    set listbox $data(FolderListBox)
    if {![string length $item]} { set item [$listbox selection get] }
    ChooseFile::_select_directory $path [$listbox itemcget $item -data]

    if {[BWidget::using ttk]} {
        set unpost ::tile::combobox::Unpost
        if {![string length [info commands $unpost]]} {
            set unpost ::ttk::combobox::Unpost
        }
        $unpost $data(FolderCombo)
    }

    focus [ChooseFile::getlistbox $path]
}


proc ChooseFile::_select_filetype { path } {
    Widget::getVariable $path#choosefile data
    ChooseFile::_select_directory $path $data(directory)
}


proc ChooseFile::_back { path } {
    Widget::getVariable $path#choosefile data
    incr data(histidx) -1
    ChooseFile::_select_directory $path [lindex $data(history) $data(histidx)] 0
}


proc ChooseFile::_up { path } {
    Widget::getVariable $path#choosefile data
    ChooseFile::_select_directory $path [file dirname $data(directory)]
}


proc ChooseFile::_next_directory { root text } {
    set i 1
    set dir [file join $root $text]
    while {[file exists $dir]} {
        set dir [file join $root "$text ([incr i])"]
    }
    return $dir
}


proc ChooseFile::_create_directory { path } {
    Widget::getVariable $path#choosefile data

    set listbox [ChooseFile::getlistbox $path]

    set i    [$listbox insert end #auto -image [BWidget::Icon folder16]]
    set text [_next_directory $data(directory) "New Folder"]

    while {1} {
        set result [$listbox edit $i [file tail $text] \
            [list ChooseFile::_verify_directory $path $listbox $i]]

        if {![string length $result]} {
            set dir $text
            break
        }

        set txt [$listbox itemcget $i -text]
        set dir [file join $data(directory) [$listbox itemcget $i -text]]

        if {[file exists $dir]} {
            set title  "Error Renaming File or Folder"
            set    msg "Cannot rename [file tail $text]: A file with the name "
            append msg "you specified already exists. Specify a different "
            append msg "file name."
            MessageDlg $path.__error -type ok -icon error \
                -title $title -message $msg
            continue
        }

        break
    }

    ChooseFile::_update_selection $path $i

    file mkdir $dir
}


proc ChooseFile::_verify_directory { path listbox node newtext } {
    $listbox itemconfigure $node -text $newtext
    return 1
}


proc ChooseFile::_map { path } {
    Widget::getVariable $path#choosefile data

    update idletasks
    ChooseFile::_select_directory $path \
        [Widget::getoption $path#choosefile -initialdir]

    set data(realized) 1
}


proc ChooseFile::_destroy { path } {
    Widget::destroy $path#choosefile
    Widget::destroy $path
}
Added lib/BWidget/color.tcl.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
# Black Brown "Olive Green" "Dark Green" "Dark Teal" "Dark Blue" Indigo Gray80
# "Dark Red" Orange "Dark Yellow" Green Teal Blue "Blue Gray" Gray50
# Red "Light Orange" Lime "Sea Green" Aqua "Light Blue" Violet Gray40
# Pink Gold Yellow "Bright Green" Turquoise "Sky Blue" Plum Gray25
# Rose Tan "Light Yellow" "Light Green" "Light Turquoise" "Pale Blue" Lavender White

# "Olive Green" "Dark Teal" Indigo "Dark Yellow" Teal "Blue Gray"
# "Light Orange" Lime Aqua "Bright Green" Rose "Light Turquoise" "Pale Blue"

namespace eval SelectColor {
    Widget::define SelectColor color Dialog IconLibrary

    Widget::declare SelectColor {
        {-title          String     "Select a Color" 0}
        {-parent         String     ""        0}
        {-color          Color      "SystemButtonFace"  0}
	{-type           Enum       "dialog"  1 {dialog popup}}
	{-placement      String     "center"  1}
        {-highlightcolor Color      "SystemHighlight"   0}
        {-paletteimage   String     ""        0}
    }

    BWidget::LoadBWidgetIconLibrary

    set image [BWidget::Icon actcolorize16]
    Widget::declare SelectColor [list [list -paletteimage String $image 0]]

    variable _baseColors {
        \#0000ff \#00ff00 \#00ffff \#ff0000 \#ff00ff \#ffff00
        \#000099 \#009900 \#009999 \#990000 \#990099 \#999900
        \#000000 \#333333 \#666666 \#999999 \#cccccc \#ffffff
    }

    variable _userColors {
        \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff
        \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff
    }

    variable _selectype
    variable _selection
    variable _wcolor
    variable _image
    variable _hsv
}

proc SelectColor::create { path args } {
    BWidget::LoadBWidgetIconLibrary

    Widget::init SelectColor $path $args

    set type [Widget::cget $path -type]

    switch -- [Widget::cget $path -type] {
	"dialog" {
	    return [eval [list SelectColor::dialog $path] $args]
	}

	"popup" {
	    set list      [list at center left right above below]
	    set placement [Widget::cget $path -placement]
	    set where     [lindex $placement 0]

	    if {[lsearch $list $where] < 0} {
		return -code error \
		    [BWidget::badOptionString placement $placement $list]
	    }

	    ## If they specified a parent and didn't pass a second argument
	    ## in the placement, set the placement relative to the parent.
	    set parent [Widget::cget $path -parent]
	    if {[string length $parent]} {
		if {[llength $placement] == 1} { lappend placement $parent }
	    }
	    return [eval [list SelectColor::menu $path $placement] $args]
	}
    }
}

proc SelectColor::menu {path placement args} {
    variable _baseColors
    variable _userColors
    variable _wcolor
    variable _selectype
    variable _selection

    Widget::init SelectColor $path $args

    set top    [toplevel $path]
    set parent [winfo toplevel [winfo parent $top]]
    wm withdraw  $top
    wm transient $top $parent
    wm overrideredirec $top 1
    catch { wm attributes $top -topmost 1 }

    set c [canvas $top.c -highlightthickness 0 -width 115 -height 98]
    pack $c -expand 1 -fill both
    bind $c <FocusOut> [list set SelectColor::_selection ""]

    set i [$c create rect 0 0 114 96 -width 0]
    $c bind $i <ButtonPress-1> [list set SelectColor::_selection ""]

    set x      6
    set y      6
    set col    0
    set row    0
    set size   11
    set space  18
    set colors [concat $_baseColors $_userColors]
    foreach color $colors {
        set i [$c create rect $x $y [expr {$x + $size}] [expr {$y + $size}] \
            -fill $color -width 1 -tags [list color $color] -outline #B8B8B8]
        $c bind $i <Enter> [list SelectColor::_highlight_color $path $i]
        $c bind $i <Leave> [list SelectColor::_highlight_color $path ""]
        $c bind $i <ButtonRelease-1> \
            [list SelectColor::_select_color $path $color]

        incr x $space

        if {[incr col] == 6} {
            set x   6
            set col 0
            incr row
            incr y $space
        }
    }

    set image [Widget::getoption $path -paletteimage]

    set i [$c create image $x $y -anchor nw -image $image]
    $c bind $i <Enter> [list SelectColor::_highlight_color $path $i]
    $c bind $i <Leave> [list SelectColor::_highlight_color $path ""]
    $c bind $i <ButtonRelease-1> [list set SelectColor::_selection custom]

    eval [list BWidget::place $top 0 0] $placement

    wm deiconify $top
    raise $top
    if {$::tcl_platform(platform) == "unix"} {
	tkwait visibility $top
	update
    }

    BWidget::SetFocusGrab $top $c

    tkwait variable SelectColor::_selection
    BWidget::RestoreFocusGrab $top $c destroy
    Widget::destroy $top
    if {[string equal $_selection "custom"]} {
        if {[BWidget::using ttk]} {
            array set opts {
                -parent -parent
                -title  -title
                -color  -initialcolor
            }

            set native 1
            set nativecmd [list tk_chooseColor -parent $parent]
            foreach {key val} $args {
                if {![info exists opts($key)]} {
                    set native 0
                    break
                }
                lappend nativecmd $opts($key) $val
            }

            if {$native} {
                return [eval $nativecmd]
            }
        }

        return [eval [list dialog $path] $args]
    } else {
        return $_selection
    }
}


proc SelectColor::dialog {path args} {
    variable top
    variable _hsv
    variable _image
    variable _widget
    variable _baseColors
    variable _userColors
    variable _base_selection
    variable _user_selection
    variable _user_next_index

    set widg $path:SelectColor

    Widget::init SelectColor $widg $args
    set top   [Dialog::create $path \
                   -title  [Widget::cget $path:SelectColor -title]  \
                   -parent [Widget::cget $path:SelectColor -parent] \
                   -separator 1 -default 0 -cancel 1 -anchor e]
    wm resizable $top 0 0
    set dlgf  [$top getframe]  
    set fg    [frame $dlgf.fg]
    set desc  [list \
               base _baseColors "Basic colors" \
               user _userColors "Custom colors"]

    foreach {type varcol defTitle} $desc {
        set col   0
        set lin   0
        set count 0
        set title [lindex [BWidget::getname "${type}Colors"] 0]
        if {![string length $title]} {
            set title $defTitle
        }
        set titf [LabelFrame $fg.$type -text $title -side top -anchor w]
        set subf [$titf getframe]
        foreach color [set $varcol] {
            set fround [frame $fg.round$type$count \
                            -highlightthickness 1 \
                            -relief sunken -borderwidth 2]
            set fcolor [frame $fg.color$type$count -width 18 -height 14 \
                            -highlightthickness 0 \
                            -relief flat -borderwidth 0 -background $color]
            pack $fcolor -in $fround
            grid $fround -in $subf -row $lin -column $col -padx 1 -pady 1

            set script [list SelectColor::_select_rgb $count $type]
            bind $fround <ButtonPress-1> $script
            bind $fcolor <ButtonPress-1> $script

            set script [list SelectColor::_select_rgb $count $type 1]
	    bind $fround <Double-1> $script
	    bind $fcolor <Double-1> $script

            incr count
            if {[incr col] == 6} {
                incr lin
                set  col 0
            }
        }
        pack $titf -anchor w -pady 2
    }

    frame $fg.border
    pack  $fg.border -anchor e

    label $fg.border.newL -text "New"
    pack  $fg.border.newL

    set color [Widget::getoption $widg -color]

    frame $fg.color -width 50 -height 25 -bd 1 -relief sunken
    pack $fg.color -in $fg.border

    frame $fg.old -width 50 -height 25 -bd 1 -relief sunken -background $color
    pack  $fg.old -in $fg.border

    label $fg.border.oldL -text "Current"
    pack  $fg.border.oldL

    set fd  [frame $dlgf.fd]
    set c1  [canvas $fd.c1 -width 200 -height 200 \
        -bd 2 -relief sunken -highlightthickness 0]
    set c2  [canvas $fd.c2 -width 15  -height 200 \
        -bd 2 -relief sunken -highlightthickness 0]

    for {set val 0} {$val < 40} {incr val} {
        set tags [list val[expr {39 - $val}]]
        $c2 create rectangle 0 [expr {5*$val}] 15 [expr {5*$val+5}] -tags $tags
    }
    $c2 create polygon 0 0 10 5 0 10 -fill #000000 -outline #FFFFFF -tags target

    grid $c1 -row 0 -column 0 -padx 10
    grid $c2 -row 0 -column 1 -padx 10

    pack $fg $fd -side left -anchor n -fill y

    bind $c1 <ButtonPress-1> [list SelectColor::_select_hue_sat %x %y]
    bind $c1 <B1-Motion>     [list SelectColor::_select_hue_sat %x %y]

    bind $c2 <ButtonPress-1> [list SelectColor::_select_value %x %y]
    bind $c2 <B1-Motion>     [list SelectColor::_select_value %x %y]

    if {![info exists _image] || [catch {image type $_image}]} {
        set _image [image create photo -width 200 -height 200]
        for {set x 0} {$x < 200} {incr x 4} {
            for {set y 0} {$y < 200} {incr y 4} {
                set hue [expr {$x / 196.0}]
                set sat [expr {(196 - $y) / 196.0}]
                set val "0.85"
                set hex [rgb2hex [hsvToRgb $hue $sat $val]]
                $_image put $hex -to $x $y [expr {$x+4}] [expr {$y+4}]
            }
        }
    }
    $c1 create image  0 0 -anchor nw -image $_image
    $c1 create bitmap 0 0 \
        -bitmap @[file join $::BWIDGET::LIBRARY "images" "target.xbm"] \
        -anchor nw -tags target

    if 0 {
        set f [frame $fd.info]
        grid $f -row 1 -column 0 -columnspan 2 -sticky se -padx 10 -pady 5

        label $f.hueL -text "Hue:"
        grid  $f.hueL -row 0 -column 0
        entry $f.hue  -textvariable SelectColor::data(hue) -width 5 \
            -state readonly
        grid  $f.hue  -row 0 -column 1

        label $f.satL -text "Sat:"
        grid  $f.satL -row 1 -column 0
        entry $f.sat  -textvariable SelectColor::data(sat) -width 5 \
            -state readonly
        grid  $f.sat  -row 1 -column 1

        label $f.lumL -text "Lum:"
        grid  $f.lumL -row 2 -column 0
        entry $f.lum  -textvariable SelectColor::data(lum) -width 5 \
            -state readonly
        grid  $f.lum  -row 2 -column 1

        label $f.redL -text "Red:"
        grid  $f.redL -row 0 -column 2
        entry $f.red  -textvariable SelectColor::data(red) -width 5 \
            -state readonly
        grid  $f.red  -row 0 -column 3

        label $f.greenL -text "Green:"
        grid  $f.greenL -row 1 -column 2
        entry $f.green  -textvariable SelectColor::data(green) \
            -width 5 -state readonly
        grid  $f.green  -row 1 -column 3

        label $f.blueL -text "Blue:"
        grid  $f.blueL -row 2 -column 2
        entry $f.blue  -textvariable SelectColor::data(blue) \
            -width 5 -state readonly
        grid  $f.blue  -row 2 -column 3
    }

    Button $fd.addCustom -text "Add to Custom Colors" -underline 0 \
        -command [list SelectColor::_add_custom_color $path]

    grid $fd.addCustom -row 2 -column 0 -columnspan 2 -sticky ew \
        -padx 10 -pady 5

    set _base_selection  -1
    set _user_selection  -1
    set _user_next_index -1

    set _widget(fcolor) $fg
    set _widget(chs)    $c1
    set _widget(cv)     $c2
    set color           [Widget::cget $path:SelectColor -color]
    set rgb             [winfo rgb $path $color]
    set _hsv            [eval rgbToHsv $rgb]

    _set_rgb     [rgb2hex $rgb]
    _set_hue_sat [lindex $_hsv 0] [lindex $_hsv 1]
    _set_value   [lindex $_hsv 2]

    $top add -name ok -width 12
    $top add -name cancel -width 12
    set res [$top draw]
    if {$res == 0} {
        set color [$fg.color cget -background]
    } else {
        set color ""
    }
    destroy $top
    return $color
}

proc SelectColor::setcolor { idx color } {
    variable _userColors
    set _userColors [lreplace $_userColors $idx $idx $color]
}


proc SelectColor::_select_color { path color } {
    variable _selection
    set _selection [rgb2hex [winfo rgb $path $color]]
}


proc SelectColor::_add_custom_color { path } {
    variable _widget
    variable _baseColors
    variable _userColors
    variable _user_selection
    variable _user_next_index

    set frame $_widget(fcolor)

    set bg  [$frame.color cget -bg]
    set idx $_user_selection
    if {$idx < 0} { set idx [incr _user_next_index] }

    if {![winfo exists $frame.coloruser$idx]} {
        set idx 0
        set _user_next_index 0
    }

    $frame.coloruser$idx configure -background $bg
    set _userColors [lreplace $_userColors $idx $idx $bg]
}

proc SelectColor::_select_rgb { count type {double 0} } {
    variable top
    variable _hsv
    variable _widget
    variable _selection
    variable _baseColors
    variable _userColors
    variable _base_selection
    variable _user_selection

    upvar 0 _${type}_selection _selection

    set frame $_widget(fcolor)
    if {$_selection >= 0} {
        $frame.round$type$_selection configure -background [$frame cget -bg]
    }
    $frame.round$type$count configure -background #000000

    set _selection $count
    set bg   [$frame.color$type$count cget -background]

    set _hsv [eval rgbToHsv [winfo rgb $frame.color$type$count $bg]]
    _set_hue_sat [lindex $_hsv 0] [lindex $_hsv 1]
    _set_value   [lindex $_hsv 2]
    $frame.color configure -background $bg

    if {$double} { $top invoke 0 }
}


proc SelectColor::_set_rgb {rgb} {
    variable data
    variable _widget

    set frame $_widget(fcolor)
    $frame.color configure -background $rgb

    BWidget::lassign [winfo rgb $frame $rgb] data(red) data(green) data(blue)
}


proc SelectColor::_select_hue_sat {x y} {
    variable _widget
    variable _hsv

    if {$x < 0} {
        set x 0
    } elseif {$x > 200} {
        set x 200
    }
    if {$y < 0 } {
        set y 0
    } elseif {$y > 200} {
        set y 200
    }
    set hue  [expr {$x/200.0}]
    set sat  [expr {(200-$y)/200.0}]
    set _hsv [lreplace $_hsv 0 1 $hue $sat]
    $_widget(chs) coords target [expr {$x-9}] [expr {$y-9}]
    _draw_values $hue $sat
    _set_rgb [rgb2hex [eval hsvToRgb $_hsv]]
    _set_hue_sat [lindex $_hsv 0] [lindex $_hsv 1]
}


proc SelectColor::_set_hue_sat {hue sat} {
    variable data
    variable _widget

    set data(hue) $hue
    set data(sat) $sat

    set x [expr {$hue*200-9}]
    set y [expr {(1-$sat)*200-9}]
    $_widget(chs) coords target $x $y
    _draw_values $hue $sat
}



proc SelectColor::_select_value {x y} {
    variable _widget
    variable _hsv

    if {$y < 0} {
        set y 0
    } elseif {$y > 200} {
        set y 200
    }
    $_widget(cv) coords target 0 [expr {$y-5}] 10 $y 0 [expr {$y+5}]
    set _hsv [lreplace $_hsv 2 2 [expr {(200-$y)/200.0}]]
    _set_rgb [rgb2hex [eval hsvToRgb $_hsv]]
    _set_value   [lindex $_hsv 2]
}


proc SelectColor::_draw_values {hue sat} {
    variable _widget

    for {set val 0} {$val < 40} {incr val} {
        set l   [hsvToRgb $hue $sat [expr {$val/39.0}]]
        set col [rgb2hex $l]
        $_widget(cv) itemconfigure val$val -fill $col -outline $col
    }
}


proc SelectColor::_set_value {value} {
    variable data
    variable _widget

    set data(lum) $value

    set y [expr {int((1-$value)*200)}]
    $_widget(cv) coords target 0 [expr {$y-5}] 10 $y 0 [expr {$y+5}]
}


proc SelectColor::_highlight_color { path item } {
    set c $path.c

    if {[string equal $item ""]} {
        $c delete hottrack
        return
    }

    set select [Widget::getoption $path -highlightcolor]
    BWidget::lassign [BWidget::get3dcolor $c $select] dark light

    set x 2
    if {[string equal [$c type $item] "image"]} { set x 0 }

    foreach [list x0 y0 x1 y1] [$c bbox $item] {break}
    set coords [list [expr {$x0 - 2}] [expr {$y0 - 2}] \
        [expr {$x1 + $x}] [expr {$y1 + $x}]]

    BWidget::DrawCanvasBorder $c rounded $select $coords \
        -outline $dark -fill $light -tags hottrack
    $c lower hottrack
}


proc SelectColor::rgb2hex { rgb } {
    return [eval format "\#%04x%04x%04x" $rgb]
}


# --
#  Taken from tk8.0/demos/tcolor.tcl
# --
# The procedure below converts an HSB value to RGB.  It takes hue, saturation,
# and value components (floating-point, 0-1.0) as arguments, and returns a
# list containing RGB components (integers, 0-65535) as result.  The code
# here is a copy of the code on page 616 of "Fundamentals of Interactive
# Computer Graphics" by Foley and Van Dam.

proc SelectColor::hsvToRgb {hue sat val} {
    set v [expr {round(65535.0*$val)}]
    if {$sat == 0} {
	return [list $v $v $v]
    } else {
	set hue [expr {$hue*6.0}]
	if {$hue >= 6.0} {
	    set hue 0.0
	}
	set i [expr {int($hue)}]
	set f [expr {$hue-$i}]
	set p [expr {round(65535.0*$val*(1 - $sat))}]
        set q [expr {round(65535.0*$val*(1 - ($sat*$f)))}]
        set t [expr {round(65535.0*$val*(1 - ($sat*(1 - $f))))}]
        switch $i {
	    0 {return [list $v $t $p]}
	    1 {return [list $q $v $p]}
	    2 {return [list $p $v $t]}
	    3 {return [list $p $q $v]}
	    4 {return [list $t $p $v]}
            5 {return [list $v $p $q]}
        }
    }
}


# --
#  Taken from tk8.0/demos/tcolor.tcl
# --
# The procedure below converts an RGB value to HSB.  It takes red, green,
# and blue components (0-65535) as arguments, and returns a list containing
# HSB components (floating-point, 0-1) as result.  The code here is a copy
# of the code on page 615 of "Fundamentals of Interactive Computer Graphics"
# by Foley and Van Dam.

proc SelectColor::rgbToHsv {red green blue} {
    if {$red > $green} {
	set max $red.0
	set min $green.0
    } else {
	set max $green.0
	set min $red.0
    }
    if {$blue > $max} {
	set max $blue.0
    } else {
	if {$blue < $min} {
	    set min $blue.0
	}
    }
    set range [expr {$max-$min}]
    if {$max == 0} {
	set sat 0
    } else {
	set sat [expr {($max-$min)/$max}]
    }
    if {$sat == 0} {
	set hue 0
    } else {
	set rc [expr {($max - $red)/$range}]
	set gc [expr {($max - $green)/$range}]
	set bc [expr {($max - $blue)/$range}]
	if {$red == $max} {
	    set hue [expr {.166667*($bc - $gc)}]
	} else {
	    if {$green == $max} {
		set hue [expr {.166667*(2 + $rc - $bc)}]
	    } else {
		set hue [expr {.166667*(4 + $gc - $rc)}]
	    }
	}
	if {$hue < 0.0} {
	    set hue [expr {$hue + 1.0}]
	}
    }
    return [list $hue $sat [expr {$max/65535}]]
}

Added lib/BWidget/combobox.tcl.












































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
# ----------------------------------------------------------------------------
#  combobox.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: combobox.tcl,v 1.30 2004/04/21 22:26:28 hobbs Exp $
# ----------------------------------------------------------------------------
#  Index of commands:
#     - ComboBox::create
#     - ComboBox::configure
#     - ComboBox::cget
#     - ComboBox::setvalue
#     - ComboBox::getvalue
#     - ComboBox::_create_popup
#     - ComboBox::_mapliste
#     - ComboBox::_unmapliste
#     - ComboBox::_select
#     - ComboBox::_modify_value
# ----------------------------------------------------------------------------

# ComboBox uses the 8.3 -listvariable listbox option
package require Tk 8.3

namespace eval ComboBox {
    Widget::define ComboBox combobox ArrowButton Entry ListBox

    Widget::tkinclude ComboBox frame :cmd \
	include {
            -relief -borderwidth -bd -background
        } initialize {
            -relief sunken -borderwidth 2
        }

    Widget::bwinclude ComboBox Entry .e \
	remove {
            -relief -bd -borderwidth -bg
        } rename {
            -background -entrybg
        }

    Widget::declare ComboBox {
        {-data          String     ""   0}
	{-height        Int        10   0}
	{-values        String	   ""   0}
	{-images        String	   ""   0}
	{-indents       String	   ""   0}
	{-postcommand   String	   ""   0}
	{-modifycommand String	   ""   0}
	{-expand        Enum	   none 0 {none tab}}
	{-autocomplete  Boolean	   0    1}
        {-usetable      Boolean    0    1}
        {-tablecolumn   Int        0    0}
        {-usebwlistbox  Boolean    0    1}
        {-dropdownwidth Int        0    0}
        {-hottrack      Boolean    1    1}

        {-postcmd       Synonym    -postcommand}
        {-modifycmd     Synonym    -modifycommand}
        {-bwlistbox     Synonym    -usebwlistbox}
    }

    Widget::addmap ComboBox ArrowButton .a {
	-background {} -foreground {} -disabledforeground {} -state {}
    }

    Widget::syncoptions ComboBox Entry .e { -text {} }

    ::bind ComboBox <FocusIn>       [list after idle {BWidget::refocus %W %W.e}]
    ::bind ComboBox <<TraverseIn>>  [list ComboBox::_traverse_in %W]
    ::bind ComboBox <ButtonPress-1> [list ComboBox::_unmapliste %W]

    ::bind ComboBoxEntry <Key-Up> [list ComboBox::_keyboard_command %W up]
    ::bind ComboBoxEntry <Key-Down> [list ComboBox::_keyboard_command %W down]
    ::bind ComboBoxEntry <Control-Up> [list ComboBox::_keyboard_command %W prev]
    ::bind ComboBoxEntry <Control-Down> \
        [list ComboBox::_keyboard_command %W next]
    ::bind ComboBoxEntry <Control-Prior> \
        [list ComboBox::_keyboard_command %W first]
    ::bind ComboBoxEntry <Control-Next> \
        [list ComboBox::_keyboard_command %W last]

    if {[string equal $::tcl_platform(platform) "windows"]} {
        ::bind ComboBoxEntry <FocusOut>      [list ComboBox::_focus_out %W]
    }

    ::bind ListBoxHotTrack <Motion> {
        %W selection clear 0 end
        %W activate @%x,%y
        %W selection set @%x,%y
    }
}


# ComboBox::create --
#
#	Create a combobox widget with the given options.
#
# Arguments:
#	path	name of the new widget.
#	args	optional arguments to the widget.
#
# Results:
#	path	name of the new widget.

proc ComboBox::create { path args } {
    Widget::initArgs ComboBox $args opts

    eval [list frame $path] $opts(:cmd) \
	 [list -highlightthickness 0 -takefocus 0 -class ComboBox]
    Widget::initFromODB ComboBox $path $opts(ComboBox)

    if {[Widget::getoption $path -usetable]} {
        package require Tktable
    }

    set entry [eval [list Entry::create $path.e] $opts(.e) \
              [list -relief flat -borderwidth 0 -takefocus 1]]
    bindtags $entry [concat [bindtags $entry] ComboBoxEntry]

    Widget::getVariable $path data
    set data(index) -1

    if {[Widget::getoption $path -autocomplete]} {
	::bind $entry <KeyRelease> [list $path _auto_complete %K]
    }

    set ipadx  2
    set width  15
    set height [winfo reqheight $entry]
    set arrow [eval [list ArrowButton::create $path.a] $opts(.a) \
		   -width $width -height $height \
		   -highlightthickness 0 -borderwidth 1 -takefocus 0 \
		   -dir	  bottom \
		   -type  button \
		   -ipadx $ipadx \
		   -command [list [list ComboBox::_mapliste $path]]]

    pack $arrow -side right -fill y
    pack $entry -side left  -fill both -expand yes

    set editable [Widget::cget $path -editable]
    Entry::configure $entry -editable $editable
    if {$editable} {
	::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path]
    } else {
	::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a]
	if { ![string equal [Widget::cget $path -state] "disabled"] } {
	    Entry::configure $entry -takefocus 1
	}
    }

    if {$editable} {
	set expand [Widget::getoption $path -expand]
	if {[string equal "tab" $expand]} {
	    # Expand entry value on Tab (from -values)
	    ::bind $entry <Tab> "[list ComboBox::_expand $path]; break"
	} elseif {[string equal "auto" $expand]} {
	    # Expand entry value anytime (from -values)
	    #::bind $entry <Key> "[list ComboBox::_expand $path]; break"
	}
    }

    ## If we have images, we have to use a BWidget ListBox.
    set bw [Widget::getoption $path -usebwlistbox]
    if {[llength [Widget::getoption $path -images]]} {
        Widget::configure $path [list -usebwlistbox 1]
    } else {
        Widget::configure $path [list -usebwlistbox $bw]
    }

    return [Widget::create ComboBox $path]
}


# ComboBox::configure --
#
#	Configure subcommand for ComboBox widgets.  Works like regular
#	widget configure command.
#
# Arguments:
#	path	Name of the ComboBox widget.
#	args	Additional optional arguments:
#			?-option?
#			?-option value ...?
#
# Results:
#	Depends on arguments.  If no arguments are given, returns a complete
#	list of configuration information.  If one argument is given, returns
#	the configuration information for that option.  If more than one
#	argument is given, returns nothing.

proc ComboBox::configure { path args } {
    set res [Widget::configure $path $args]
    set entry $path.e

    set list [list -images -values]
    foreach {ci cv} [eval [linsert $list 0 Widget::hasChangedX $path]] break

    if {$ci} {
        if {![Widget::getoption $path -usebwlistbox]} {
            set msg "cannot use -images in a ComboBox without -usebwlistbox"
            return -code error $msg
        }

        ## If the images have changed, destroy the shell so that it
        ## will re-create itself the next time around.
        destroy $path.shell
    }

    set chgedit [Widget::hasChangedX $path -editable]
    if {$chgedit} {
        if {[Widget::cget $path -editable]} {
            ::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path]
	    Entry::configure $entry -editable true
	} else {
	    ::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a]
	    Entry::configure $entry -editable false

	    # Make sure that non-editable comboboxes can still be tabbed to.

	    if {![string equal [Widget::cget $path -state] "disabled"]} {
		Entry::configure $entry -takefocus 1
	    }
        }
    }

    if {$chgedit || [Widget::hasChangedX $path -expand]} {
	# Unset what we may have created.
	::bind $entry <Tab> {}
	if {[Widget::cget $path -editable]} {
	    set expand [Widget::getoption $path -expand]
	    if {[string equal "tab" $expand]} {
		# Expand entry value on Tab (from -values)
		::bind $entry <Tab> "[list ComboBox::_expand $path]; break"
	    } elseif {[string equal "auto" $expand]} {
		# Expand entry value anytime (from -values)
		#::bind $entry <Key> "[list ComboBox::_expand $path]; break"
	    }
	}
    }

    # If the dropdown listbox is shown, simply force the actual entry
    # colors into it. If it is not shown, the next time the dropdown
    # is shown it'll get the actual colors anyway.
    set listbox [getlistbox $path]
    if {[winfo exists $listbox]} {
        set bg  [Widget::cget $path -entrybg]
        set fg  [Widget::cget $path -foreground]
        set sbg [Widget::cget $path -selectbackground]
        set sfg [Widget::cget $path -selectforeground]

        if {[Widget::getoption $path -usetable]} {
            $listbox configure -bg $bg -fg $fg

            $listbox tag configure sel -bg $sbg -fg $sfg
        } else {
            $listbox configure -bg $bg -fg $fg \
                -selectbackground $sbg -selectforeground $sfg
        }
    }

    if {[Widget::hasChanged $path -text value]} {
        Widget::getVariable $path data
        set values [Widget::getoption $path -values]
        set data(index) [lsearch -exact $values $value]
    }

    if {$cv && [Widget::getoption $path -usetable]} {
        _update_table_values $path
    }

    return $res
}


# ----------------------------------------------------------------------------
#  Command ComboBox::cget
# ----------------------------------------------------------------------------
proc ComboBox::cget { path option } {
    return [Widget::cget $path $option]
}


# ----------------------------------------------------------------------------
#  Command ComboBox::setvalue
# ----------------------------------------------------------------------------
proc ComboBox::setvalue { path index } {
    set idx    [ComboBox::index $path $index 0]
    set value  [Entry::cget $path.e -text]
    set values [Widget::cget $path -values]

    if {$idx >= 0 && $idx < [llength $values]} {
        Widget::getVariable $path data
        set data(index) $idx

        set newval [lindex $values $idx]
        if {[Widget::getoption $path -usetable]} {
            set col [Widget::getoption $path -tablecolumn]
            if {$col > -1} { set newval [lindex $newval $col] }
        }
	Entry::configure $path.e -text $newval
        return 1
    }

    return 0
}


proc ComboBox::icursor { path idx } {
    return [$path.e icursor $idx]
}


proc ComboBox::get { path } {
    return [$path.e get]
}

proc ComboBox::index { path index {strict 1} } {
    Widget::getVariable $path data
    set values [Widget::getoption $path -values]

    set idx  $data(index)
    set last [expr {[llength $values] - 1}]

    switch -- $index {
        "active" {}

        "next" {
            incr idx
        }

        "prev" - "previous" {
            incr idx -1
        }

        "first" {
            set idx 0
        }

        "end" - "last" {
            set idx $last
        }

        default {
            if {[string is integer $index]} {
                set idx $index
            } elseif {[string equal [string index $index 0] "@"]} {
                set idx [string range $index 1 end]
		if {![string is integer -strict $idx]} {
                    return -code error "bad index \"$index\""
                }
            } else {
                return -code error "bad index \"$index\""
            }
        }
    }

    if {$strict} {
        if {$idx < 0} { set idx 0 }
        if {$idx > $last} { set idx $last }
    }

    return $idx
}


# ----------------------------------------------------------------------------
#  Command ComboBox::getvalue
# ----------------------------------------------------------------------------
proc ComboBox::getvalue { path } {
    Widget::getVariable $path data
    return $data(index)
}


proc ComboBox::getlistbox { path } {
    _create_popup $path
    return $path.shell.listb
}


# ----------------------------------------------------------------------------
#  Command ComboBox::post
# ----------------------------------------------------------------------------
proc ComboBox::post { path } {
    _mapliste $path
    return
}


proc ComboBox::unpost { path } {
    _unmapliste $path
    return
}


# ----------------------------------------------------------------------------
#  Command ComboBox::bind
# ----------------------------------------------------------------------------
proc ComboBox::bind { path args } {
    return [eval [list ::bind $path.e] $args]
}


proc ComboBox::insert { path idx args } {
    upvar #0 [Widget::varForOption $path -values] values

    if {[Widget::getoption $path -usebwlistbox]} {
        set l [$path getlistbox]
        set i [eval [list $l insert $idx #auto] $args]
        set text [$l itemcget $i -text]
        set values [linsert $values $idx $text]
    } else {
        set values [eval linsert [list $values] $idx $args]
    }
}

# ----------------------------------------------------------------------------
#  Command ComboBox::_create_popup
# ----------------------------------------------------------------------------
proc ComboBox::_create_popup { path } {
    set shell $path.shell

    if {[winfo exists $shell]} { return }

    set h    [Widget::cget $path -height]
    set lval [Widget::getoption $path -values]

    if { $h <= 0 } {
	set len [llength $lval]
	if { $len < 3 } {
	    set h 3
	} elseif { $len > 10 } {
	    set h 10
	} else {
	    set h $len
	}
    }

    if {[string equal $::tcl_platform(platform) "unix"]} {
	set sbwidth 11
    } else {
	set sbwidth 15
    }

    toplevel            $shell -relief solid -bd 1
    wm withdraw         $shell
    wm overrideredirect $shell 1
    wm transient        $shell [winfo toplevel $path]

    if {$::tcl_platform(platform) eq "windows"} {
        wm attributes $shell -topmost 1
    }

    set sw [ScrolledWindow $shell.sw -managed 0 -size $sbwidth -ipad 0]
    pack $sw -fill both -expand yes
    
    if {[Widget::getoption $path -usetable]} {
        set listb [table $shell.listb \
            -relief flat -borderwidth 0 -highlightthickness 0 \
            -selecttype row -selectmode single -cursor "" \
            -colstretchmode all -resizeborders none \
            -height $h -font [Widget::cget $path -font] \
            -background [Widget::cget $path -entrybg] \
            -foreground [Widget::cget $path -foreground] \
            -variable [Widget::widgetVar $path tableData]]

        BWidget::bindMouseWheel $shell.listb

        _update_table_values $path

        ::bind $listb <ButtonRelease-1> [list ComboBox::_select $path @%x,%y]

        if {[Widget::getoption $path -hottrack]} {
            ::bind $listb <Motion> {
                %W selection clear all
                %W selection set @%x,%y
            }
        }
    } elseif {[Widget::getoption $path -usebwlistbox]} {
        set listb  [ListBox $shell.listb \
                -relief flat -borderwidth 0 -highlightthickness 0 \
                -selectmode single -selectfill 1 -autofocus 0 -height $h \
                -font [Widget::cget $path -font]  \
                -bg [Widget::cget $path -entrybg] \
                -fg [Widget::cget $path -foreground] \
                -selectbackground [Widget::cget $path -selectbackground] \
                -selectforeground [Widget::cget $path -selectforeground]]

        set values [Widget::getoption $path -values]
        set images [Widget::getoption $path -images]
        foreach value $values image $images {
            $listb insert end #auto -text $value -image $image
        }
	$listb bindText  <1> "ComboBox::_select $path"
	$listb bindImage <1> "ComboBox::_select $path"
        if {[Widget::getoption $path -hottrack]} {
            $listb bindText  <Enter> [list $listb selection set]
            $listb bindImage <Enter> [list $listb selection set]
        }
    } else {
        set listb  [listbox $shell.listb \
                -relief flat -borderwidth 0 -highlightthickness 0 \
                -exportselection false \
                -font	[Widget::cget $path -font]  \
                -height $h \
                -bg [Widget::cget $path -entrybg] \
                -fg [Widget::cget $path -foreground] \
                -selectbackground [Widget::cget $path -selectbackground] \
                -selectforeground [Widget::cget $path -selectforeground] \
                -listvariable [Widget::varForOption $path -values]]
        ::bind $listb <ButtonRelease-1> [list ComboBox::_select $path @%x,%y]

        if {[Widget::getoption $path -hottrack]} {
            bindtags $listb [concat [bindtags $listb] ListBoxHotTrack]
        }
    }

    $sw setwidget $listb

    ::bind $listb <Return>   "ComboBox::_select $path \[%W curselection]"
    ::bind $listb <Escape>   [list ComboBox::_unmapliste $path]
    if {[string equal $::tcl_platform(platform) "windows"]} {
        ::bind $listb <FocusOut> [list ComboBox::_focus_out $path]
    }
}


proc ComboBox::_recreate_popup { path } {
    variable background
    variable foreground

    set shell $path.shell
    set h     [Widget::cget $path -height]
    set lval  [Widget::getoption $path -values]

    if { $h <= 0 } {
	set len [llength $lval]
	if { $len < 3 } {
	    set h 3
	} elseif { $len > 10 } {
	    set h 10
	} else {
	    set h $len
	}
    }

    if {$::tcl_platform(platform) == "unix"} {
	set sbwidth 11
    } else {
	set sbwidth 15
    }

    _create_popup $path

    if {![Widget::cget $path -editable]} {
        if {[info exists background]} {
            $path.e configure -bg $background
            $path.e configure -fg $foreground
            unset background
            unset foreground
        }
    }

    set listb $shell.listb
    destroy $shell.sw
    set sw [ScrolledWindow $shell.sw -managed 0 -size $sbwidth -ipad 0]

    set opts [list]
    lappend opts -font [Widget::cget $path -font]
    lappend opts -bg   [Widget::cget $path -entrybg]
    lappend opts -fg   [Widget::cget $path -foreground]

    if {[Widget::getoption $path -usetable]} {
        lappend opts -height $h
    } else {
        lappend opts -height $h
        lappend opts -selectbackground [Widget::cget $path -selectbackground]
        lappend opts -selectforeground [Widget::cget $path -selectforeground]
    }

    eval [list $listb configure] $opts

    pack $sw -fill both -expand yes
    $sw setwidget $listb
    raise $listb
}


# ----------------------------------------------------------------------------
#  Command ComboBox::_mapliste
# ----------------------------------------------------------------------------
proc ComboBox::_mapliste { path } {
    set listb $path.shell.listb
    if {[winfo exists $path.shell] &&
        [string equal [wm state $path.shell] "normal"]} {
	_unmapliste $path
        return
    }

    if { [Widget::cget $path -state] == "disabled" } {
        return
    }

    if {[llength [set cmd [Widget::getoption $path -postcommand]]]} {
        uplevel \#0 $cmd
    }

    if { ![llength [Widget::getoption $path -values]] } {
        return
    }

    _recreate_popup $path

    ArrowButton::configure $path.a -relief sunken
    update

    if {[Widget::getoption $path -usetable]} {
        $listb selection clear all
    } else {
        $listb selection clear 0 end
    }

    set values [Widget::getoption $path -values]
    set curval [Entry::cget $path.e -text]
    set idx 0
    if {[set i [lsearch -exact $values $curval]] != -1 ||
         [set i [lsearch $values "$curval*"]] != -1} {
        set idx $i
    }

    if {[Widget::getoption $path -usetable]} {
        set idx $idx,0
    } elseif {[Widget::getoption $path -usebwlistbox]} {
        set idx [$listb items $idx]
    } else {
        $listb activate $idx
    }

    $listb selection set $idx
    $listb see $idx

    set width [Widget::getoption $path -dropdownwidth]
    if {!$width} { set width [winfo width $path] }
    BWidget::place $path.shell $width 0 below $path

    wm deiconify $path.shell
    raise $path.shell
    BWidget::grab global $path
    BWidget::focus set $listb

    event generate $path <<ComboBoxPost>>
}


# ----------------------------------------------------------------------------
#  Command ComboBox::_unmapliste
# ----------------------------------------------------------------------------
proc ComboBox::_unmapliste { path {refocus 1} } {
    if {[winfo exists $path.shell] && \
	    [string equal [wm state $path.shell] "normal"]} {
        BWidget::grab release $path
        BWidget::focus release $path.shell.listb $refocus
	# Update now because otherwise [focus -force...] makes the app hang!
	if {$refocus} {
	    update
	    focus -force $path.e
	}
        wm withdraw $path.shell
        ArrowButton::configure $path.a -relief raised

        event generate $path <<ComboBoxUnpost>>
    }
}


# ----------------------------------------------------------------------------
#  Command ComboBox::_select
# ----------------------------------------------------------------------------
proc ComboBox::_select { path index } {
    set index [$path.shell.listb index $index]

    _unmapliste $path

    if {[Widget::getoption $path -usetable]} {
        set index [lindex [split $index ,] 0]
    }

    if {$index != -1} {
        if {[ComboBox::setvalue $path @$index]} {
	    set cmd [Widget::getoption $path -modifycommand]
            if {[string length $cmd]} { uplevel #0 $cmd }
        }
    }

    $path.e selection clear
    $path.e selection range 0 end

    event generate $path <<ComboBoxSelected>>
    event generate $path <<ComboboxSelected>>
}


# ----------------------------------------------------------------------------
#  Command ComboBox::_modify_value
# ----------------------------------------------------------------------------
proc ComboBox::_modify_value { path direction } {
    if {[ComboBox::setvalue $path $direction]} {
        $path.e selection clear
        $path.e selection range 0 end
        
        set cmd [Widget::getoption $path -modifycommand]
        if {[string length $cmd]} { uplevel #0 $cmd }
    }
}

# ----------------------------------------------------------------------------
#  Command ComboBox::_expand
# ----------------------------------------------------------------------------
proc ComboBox::_expand {path} {
    set values [Widget::getoption $path -values]
    if {![llength $values]} {
	bell
	return 0
    }

    set found  {}
    set curval [Entry::cget $path.e -text]
    set curlen [$path.e index insert]
    if {$curlen < [string length $curval]} {
	# we are somewhere in the middle of a string.
	# if the full value matches some string in the listbox,
	# reorder values to start matching after that string.
	set idx [lsearch -exact $values $curval]
	if {$idx >= 0} {
	    set values [concat [lrange $values [expr {$idx+1}] end] \
			    [lrange $values 0 $idx]]
	}
    }
    if {$curlen == 0} {
	set found $values
    } else {
	foreach val $values {
	    if {[string equal -length $curlen $curval $val]} {
		lappend found $val
	    }
	}
    }
    if {[llength $found]} {
	Entry::configure $path.e -text [lindex $found 0]
	if {[llength $found] > 1} {
	    set best [_best_match $found [string range $curval 0 $curlen]]
	    set blen [string length $best]
	    $path.e icursor $blen
	    $path.e selection range $blen end
	}
    } else {
	bell
    }
    return [llength $found]
}

# best_match --
#   finds the best unique match in a list of names
#   The extra $e in this argument allows us to limit the innermost loop a
#   little further.
# Arguments:
#   l		list to find best unique match in
#   e		currently best known unique match
# Returns:
#   longest unique match in the list
#
proc ComboBox::_best_match {l {e {}}} {
    set ec [lindex $l 0]
    if {[llength $l]>1} {
	set e  [string length $e]; incr e -1
	set ei [string length $ec]; incr ei -1
	foreach l $l {
	    while {$ei>=$e && [string first $ec $l]} {
		set ec [string range $ec 0 [incr ei -1]]
	    }
	}
    }
    return $ec
}

# possibly faster
#proc match {string1 string2} {
#   set i 1
#   while {[string equal -length $i $string1 $string2]} { incr i }
#   return [string range $string1 0 [expr {$i-2}]]
#}
#proc matchlist {list} {
#   set list [lsort $list]
#   return [match [lindex $list 0] [lindex $list end]]
#}


# ----------------------------------------------------------------------------
#  Command ComboBox::_traverse_in
#  Called when widget receives keyboard focus due to keyboard traversal.
# ----------------------------------------------------------------------------
proc ComboBox::_traverse_in { path } {
    if {[$path.e selection present] != 1} {
	# Autohighlight the selection, but not if one existed
	$path.e selection range 0 end
    }
}


# ----------------------------------------------------------------------------
#  Command ComboBox::_focus_out
# ----------------------------------------------------------------------------
proc ComboBox::_focus_out { path } {
    if {![string length [focus]]} {
	# we lost focus to some other app, make sure we drop the listbox
	return [_unmapliste $path 0]
    }
}


proc ComboBox::_auto_complete { path key } {
    ## Anything that is all lowercase is either a letter, number
    ## or special key we're ok with.  Everything else is a
    ## functional key of some kind.
    if {[string length $key] > 1 && [string tolower $key] != $key} { return }

    set text [string map [list {[} {\[} {]} {\]}] [$path.e get]]
    if {![string length $text]} { return }

    set values [Widget::getoption $path -values]

    if {[Widget::getoption $path -usetable]} {
        set col [Widget::getoption $path -tablecolumn]
        set idx [lsearch -index $col $values $text*]
    } else {
        set idx [lsearch $values $text*]
    }

    if {$idx > -1} {
        set idx [$path.e index insert]
        $path.e configure -text [lindex $values $idx]
        $path.e icursor $idx
        $path.e select range insert end
    }
}


proc ComboBox::_keyboard_command { entry command } {
    set path [winfo parent $entry]

    switch -- $command {
        "up" {
            ComboBox::_unmapliste $path
        }

        "down" {
            ComboBox::_mapliste $path
        }

        default {
            ComboBox::_modify_value $path $command
        }
    }
}


proc ComboBox::_update_table_values { path } {
    Widget::getVariable $path tableData

    set table  [getlistbox $path]
    set values [Widget::getoption $path -values]

    set row  0
    set cols 0
    foreach list $values {
        set len [llength $list]
        if {$len > $cols} { set cols $len }

        for {set col 0} {$col < $len} {incr col} {
            set tableData($row,$col) [lindex $list $col]
        }

        incr row
    }

    $table configure -rows $row -cols $cols -state disabled
}
Added lib/BWidget/configure.in.




























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
AC_INIT(init.tcl)

AC_CONFIG_AUX_DIR(config)
CONFIGDIR=${srcdir}/config
AC_SUBST(CONFIGDIR)

PACKAGE=bwidget

MAJOR_VERSION=1
MINOR_VERSION=7
PATCHLEVEL=

VERSION=${MAJOR_VERSION}.${MINOR_VERSION}${PATCHLEVEL}
NODOT_VERSION=${MAJOR_VERSION}${MINOR_VERSION}

AC_SUBST(PACKAGE)
AC_SUBST(VERSION)
eval AC_DEFINE_UNQUOTED(VERSION, "${VERSION}")

AC_PROG_INSTALL

#--------------------------------------------------------------------
# "cygpath" is used on windows to generate native path names for include
# files.
# These variables should only be used with the compiler and linker since
# they generate native path names.
#
# Unix tclConfig.sh points SRC_DIR at the top-level directory of
# the Tcl sources, while the Windows tclConfig.sh points SRC_DIR at
# the win subdirectory.  Hence the different usages of SRC_DIR below.
#
# This must be done before calling SC_PUBLIC_TCL_HEADERS
#--------------------------------------------------------------------

case "`uname -s`" in
    *win32* | *WIN32* | *CYGWIN_NT*|*CYGWIN_98*|*CYGWIN_95*)
	CYGPATH="cygpath -w"
    ;;
    *)
	CYGPATH=echo
    ;;
esac

AC_SUBST(CYGPATH)

AC_OUTPUT([Makefile])
Added lib/BWidget/dialog.tcl.






































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# ----------------------------------------------------------------------------
#  dialog.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: dialog.tcl,v 1.13 2003/10/20 21:23:52 damonc Exp $
# ----------------------------------------------------------------------------
#  Index of commands:
#     - Dialog::create
#     - Dialog::configure
#     - Dialog::cget
#     - Dialog::getframe
#     - Dialog::add
#     - Dialog::itemconfigure
#     - Dialog::itemcget
#     - Dialog::invoke
#     - Dialog::setfocus
#     - Dialog::enddialog
#     - Dialog::draw
#     - Dialog::withdraw
#     - Dialog::_destroy
# ----------------------------------------------------------------------------

namespace eval Dialog {
    Widget::define Dialog dialog ButtonBox

    Widget::bwinclude Dialog ButtonBox .bbox \
        remove {
            -orient -background
        } initialize {
            -spacing 10 -padx 10
        }

    Widget::declare Dialog {
        {-background    Color    "SystemButtonFace" 0}
        {-title         String   ""      0}
	{-geometry      String   ""      0}
        {-modal         Enum     local   0 {none local global}}
        {-bitmap        String   ""      1}
        {-image         String   ""      1}
        {-separator     Boolean  0       1}
        {-cancel        Int      -1      0 "%d >= -1"}
        {-parent        String   ""      0}
        {-side          Enum     bottom  1 {bottom left top right}}
        {-anchor        Enum     c       1 {n e w s c}}
	{-class         String   Dialog  1}
        {-transient     Boolean  1       1}
        {-place         Enum     center  1 {none center left right above below}}
        {-placerelative Boolean  1       1}

        {-bg            Synonym  -background}
    }

    if {![BWidget::using ttk]} {
        Widget::addmap Dialog "" :cmd   {-background {}}
        Widget::addmap Dialog "" .frame {-background {}}
    }

    bind Dialog <Destroy> [list Dialog::_destroy %W]
}


# ----------------------------------------------------------------------------
#  Command Dialog::create
# ----------------------------------------------------------------------------
proc Dialog::create { path args } {
    Widget::initArgs Dialog $args maps

    # Check to see if the -class flag was specified
    array set _args $maps(Dialog)
    set class "Dialog"
    if {[info exists _args(-class)]} { set class $_args(-class) }

    if {[string equal $::tcl_platform(platform) "unix"]} {
	set re raised
	set bd 1
    } else {
	set re flat
	set bd 0
    }
    toplevel $path -relief $re -borderwidth $bd -class $class \
        -background $::BWidget::colors(SystemButtonFace)
    wm protocol $path WM_DELETE_WINDOW [list Dialog::cancel $path]

    Widget::initFromODB Dialog $path $maps(Dialog)

    bindtags $path [list $path $class all]
    wm overrideredirect $path 1
    wm title $path [Widget::cget $path -title]

    set parent [Widget::getoption $path -parent]
    if {![winfo exists $parent]} {
        set parent [winfo parent $path]
        if {$parent ne "."} { Widget::setoption $path -parent $parent }
    }

    if {[Widget::getoption $path -transient]} {
	wm transient $path [winfo toplevel $parent]
    }
    wm withdraw $path

    set side [Widget::cget $path -side]
    if {[string equal $side "left"] || [string equal $side "right"]} {
        set orient vertical
    } else {
        set orient horizontal
    }

    eval [list ButtonBox::create $path.bbox] $maps(.bbox) -orient $orient
    set frame [frame $path.frame -relief flat -borderwidth 0]

    set opts [list]

    if {![BWidget::using ttk]} {
        set bg [$path cget -background]
        lappend opts -background $bg
        $path configure -background $bg
        $frame configure -background $bg
    }

    if {[set bitmap [Widget::getoption $path -image]] != ""} {
        eval [list label $path.label -image $bitmap] $opts
    } elseif {[set bitmap [Widget::getoption $path -bitmap]] != ""} {
        eval [list label $path.label -bitmap $bitmap] $opts
    }
    if {[Widget::getoption $path -separator]} {
        eval [list Separator::create $path.sep -orient $orient] $opts
    }

    Widget::getVariable $path data
    set data(nbut)     0
    set data(realized) 0

    bind $path <Return> [list Dialog::ok $path]
    bind $path <Escape> [list Dialog::cancel $path]

    return [Widget::create Dialog $path]
}


# ----------------------------------------------------------------------------
#  Command Dialog::configure
# ----------------------------------------------------------------------------
proc Dialog::configure { path args } {
    set res [Widget::configure $path $args]

    if { [Widget::hasChanged $path -title title] } {
        wm title $path $title
    }
    if { [Widget::hasChanged $path -background bg] } {
        if { [winfo exists $path.label] } {
            $path.label configure -background $bg
        }
        if { [winfo exists $path.sep] } {
            Separator::configure $path.sep -background $bg
        }
    }
    return $res
}


# ----------------------------------------------------------------------------
#  Command Dialog::cget
# ----------------------------------------------------------------------------
proc Dialog::cget { path option } {
    return [Widget::cget $path $option]
}


# ----------------------------------------------------------------------------
#  Command Dialog::getframe
# ----------------------------------------------------------------------------
proc Dialog::getframe { path } {
    return $path.frame
}


# ----------------------------------------------------------------------------
#  Command Dialog::add
# ----------------------------------------------------------------------------
proc Dialog::add { path args } {
    Widget::getVariable $path data

    set idx $data(nbut)
    set cmd [list ButtonBox::add $path.bbox \
		 -command [list Dialog::enddialog $path $idx]]
    set res [eval $cmd -value $idx $args]
    incr data(nbut)
    return $res
}


# ----------------------------------------------------------------------------
#  Command Dialog::itemconfigure
# ----------------------------------------------------------------------------
proc Dialog::itemconfigure { path index args } {
    return [eval [list ButtonBox::itemconfigure $path.bbox $index] $args]
}


# ----------------------------------------------------------------------------
#  Command Dialog::itemcget
# ----------------------------------------------------------------------------
proc Dialog::itemcget { path index option } {
    return [ButtonBox::itemcget $path.bbox $index $option]
}


# ----------------------------------------------------------------------------
#  Command Dialog::invoke
# ----------------------------------------------------------------------------
proc Dialog::invoke { path index } {
    ButtonBox::invoke $path.bbox $index
}


# ----------------------------------------------------------------------------
#  Command Dialog::setfocus
# ----------------------------------------------------------------------------
proc Dialog::setfocus { path index } {
    ButtonBox::setfocus $path.bbox $index
}


# ----------------------------------------------------------------------------
#  Command Dialog::enddialog
# ----------------------------------------------------------------------------
proc Dialog::enddialog { path result {destroy 0} } {
    Widget::getVariable $path data

    if {$result ne -1} {
        if {[ButtonBox::index $path.bbox $result] > -1} {
            set result [ButtonBox::itemcget $path.bbox $result -value]
        }
    }

    set data(result) $result

    event generate $path <<DialogEnd>>

    if {$destroy} {
        destroy $path
    }

    return $result
}


# ----------------------------------------------------------------------------
#  Command Dialog::draw
# ----------------------------------------------------------------------------
proc Dialog::draw { path {focus ""} {overrideredirect 0} {geometry ""} } {
    Widget::getVariable $path data

    set parent [Widget::getoption $path -parent]
    if {!$data(realized)} {
        set data(realized) 1
        if {[llength [winfo children $path.bbox]]} {
            set side [Widget::getoption $path -side]
            if {[string equal $side "left"] || [string equal $side "right"]} {
                set pad  -padx
                set fill y
            } else {
                set pad  -pady
                set fill x
            }

            pack $path.bbox -side $side \
                -anchor [Widget::getoption $path -anchor] -padx 1m -pady {5 10}

            if {[winfo exists $path.sep]} {
                pack $path.sep -side $side -fill $fill $pad 2m
            }
        }

        if {[winfo exists $path.label]} {
            pack $path.label -side left -anchor n -padx {10 5} -pady 3m
        }

        pack $path.frame -padx 1m -pady 1m -fill both -expand yes
    }

    if {![string length $geometry]} {
        set geometry [Widget::getoption $path -geometry]
    }

    set width    0
    set height   0
    set place    [Widget::getoption $path -place]
    set usePlace [expr ![string equal $place "none"]]
    if {[string length $geometry]} {
        set split [split $geometry x+-]

        ## If the list is greater than 2 elements, we were given
        ## X and Y coordinates, so we don't want to place the window.
        if {[llength $split] > 2} {
            set usePlace 0
        } else {
            BWidget::lassign $split width height
        }
    }

    wm geometry $path $geometry

    if {$usePlace} {
        set relative [Widget::getoption $path -placerelative]
        if {$relative && [winfo exists $parent]} {
            BWidget::place $path $width $height $place $parent
        } else {
            BWidget::place $path $width $height $place
        }
    }

    update idletasks
    wm overrideredirect $path $overrideredirect
    wm deiconify $path

    # patch by Bastien Chevreux (bach@mwgdna.com)
    # As seen on Windows systems *sigh*
    # When the toplevel is withdrawn, the tkwait command will wait forever.
    #  So, check that we are not withdrawn
    if {![winfo exists $parent] || \
        ([wm state [winfo toplevel $parent]] != "withdrawn")} {
	tkwait visibility $path
    }

    BWidget::focus set $path
    if {[winfo exists $focus]} {
        focus -force $focus
    } else {
        ButtonBox::setfocus $path.bbox default
    }

    if {[set grab [Widget::cget $path -modal]] != "none"} {
        BWidget::grab $grab $path
        set res [Dialog::wait $path]
        withdraw $path
        return $res
    }
}


proc Dialog::wait { path } {
    Widget::getVariable $path data

    if {[info exists data(result)]} { unset data($result) }

    tkwait variable [Widget::widgetVar $path data(result)]
    if {[info exists data(result)]} {
        set res $data(result)
        unset data(result)
    } else {
        set res -1
    }

    return $res
}


# ----------------------------------------------------------------------------
#  Command Dialog::withdraw
# ----------------------------------------------------------------------------
proc Dialog::withdraw { path } {
    BWidget::grab release $path
    BWidget::focus release $path
    if {[winfo exists $path]} {
        wm withdraw $path
    }
}


proc Dialog::ok { path } {
    ButtonBox::invoke $path.bbox default
}


proc Dialog::cancel { path } {
    ButtonBox::invoke $path.bbox [Widget::getoption $path -cancel]
}


# ----------------------------------------------------------------------------
#  Command Dialog::_destroy
# ----------------------------------------------------------------------------
proc Dialog::_destroy { path } {
    BWidget::grab  release $path
    BWidget::focus release $path
    Widget::destroy $path
}
Added lib/BWidget/dragsite.tcl.












































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# ------------------------------------------------------------------------------
#  dragsite.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: dragsite.tcl,v 1.8 2003/10/20 21:23:52 damonc Exp $
# ------------------------------------------------------------------------------
#  Index of commands:
#     - DragSite::include
#     - DragSite::setdrag
#     - DragSite::register
#     - DragSite::_begin_drag
#     - DragSite::_init_drag
#     - DragSite::_end_drag
#     - DragSite::_update_operation
# ----------------------------------------------------------------------------

namespace eval DragSite {
    Widget::define DragSite dragsite -classonly

    Widget::declare DragSite [list \
	    [list	-dragevent	Enum	1	0	[list 1 2 3]] \
	    [list	-draginitcmd	String	""	0] \
	    [list	-dragendcmd	String	""	0] \
	    ]

    variable _topw ".#BWidget#drag"
    variable _tabops
    variable _state
    variable _x0
    variable _y0

    bind BwDrag1 <ButtonPress-1> {DragSite::_begin_drag press  %W %s %X %Y}
    bind BwDrag1 <B1-Motion>     {DragSite::_begin_drag motion %W %s %X %Y}
    bind BwDrag2 <ButtonPress-2> {DragSite::_begin_drag press  %W %s %X %Y}
    bind BwDrag2 <B2-Motion>     {DragSite::_begin_drag motion %W %s %X %Y}
    bind BwDrag3 <ButtonPress-3> {DragSite::_begin_drag press  %W %s %X %Y}
    bind BwDrag3 <B3-Motion>     {DragSite::_begin_drag motion %W %s %X %Y}

    proc use {} {}
}


# ----------------------------------------------------------------------------
#  Command DragSite::include
# ----------------------------------------------------------------------------
proc DragSite::include { class type event } {
    set dragoptions [list \
	    [list	-dragenabled	Boolean	0	0] \
	    [list	-draginitcmd	String	""	0] \
	    [list	-dragendcmd	String	""	0] \
	    [list	-dragtype	String	$type	0] \
	    [list	-dragevent	Enum	$event	0	[list 1 2 3]] \
	    ]
    Widget::declare $class $dragoptions
}


# ----------------------------------------------------------------------------
#  Command DragSite::setdrag
#  Widget interface to register
# ----------------------------------------------------------------------------
proc DragSite::setdrag { path subpath initcmd endcmd {force 0}} {
    set cen       [Widget::hasChanged $path -dragenabled en]
    set cdragevt  [Widget::hasChanged $path -dragevent   dragevt]
    if { $en } {
        if { $force || $cen || $cdragevt } {
            register $subpath \
                -draginitcmd $initcmd \
                -dragendcmd  $endcmd  \
                -dragevent   $dragevt
        }
    } else {
        register $subpath
    }
}


# ----------------------------------------------------------------------------
#  Command DragSite::register
# ----------------------------------------------------------------------------
proc DragSite::register { path args } {
    upvar \#0 DragSite::$path drag
    variable _topw

    if { [info exists drag] } {
        bind $path $drag(evt) {}
        unset drag
    }
    Widget::init DragSite $_topw$path $args
    set event   [Widget::getoption $_topw$path -dragevent]
    set initcmd [Widget::getoption $_topw$path -draginitcmd]
    set endcmd  [Widget::getoption $_topw$path -dragendcmd]
    set tags    [bindtags $path]
    set idx     [lsearch $tags "BwDrag*"]
    Widget::destroy .$_topw$path
    if { $initcmd != "" } {
        if { $idx != -1 } {
            bindtags $path [lreplace $tags $idx $idx BwDrag$event]
        } else {
            bindtags $path [concat $tags BwDrag$event]
        }
        set drag(initcmd) $initcmd
        set drag(endcmd)  $endcmd
        set drag(evt)     $event
    } elseif { $idx != -1 } {
        bindtags $path [lreplace $tags $idx $idx]
    }
}


# ----------------------------------------------------------------------------
#  Command DragSite::_begin_drag
# ----------------------------------------------------------------------------
proc DragSite::_begin_drag { event source state X Y } {
    variable _x0
    variable _y0
    variable _state

    switch -- $event {
        press {
            set _x0    $X
            set _y0    $Y
            set _state "press"
        }
        motion {
            if { ![info exists _state] } {
                # This is just extra protection. There seem to be
                # rare cases where the motion comes before the press.
                return
            }
            if { [string equal $_state "press"] } {
                if { abs($_x0-$X) > 3 || abs($_y0-$Y) > 3 } {
                    set _state "done"
                    _init_drag $source $state $X $Y
                }
            }
        }
    }
}


# ----------------------------------------------------------------------------
#  Command DragSite::_init_drag
# ----------------------------------------------------------------------------
proc DragSite::_init_drag { source state X Y } {
    variable _topw
    upvar \#0 DragSite::$source drag

    destroy  $_topw
    toplevel $_topw
    wm withdraw $_topw
    wm overrideredirect $_topw 1

    set info [uplevel \#0 $drag(initcmd) [list $source $X $Y $_topw]]
    if { $info != "" } {
        set type [lindex $info 0]
        set ops  [lindex $info 1]
        set data [lindex $info 2]

        if { [winfo children $_topw] == "" } {
            if { [string equal $type "BITMAP"] || [string equal $type "IMAGE"] } {
                label $_topw.l -image [Bitmap::get dragicon] -relief flat -bd 0
            } else {
                label $_topw.l -image [Bitmap::get dragfile] -relief flat -bd 0
            }
            pack  $_topw.l
        }
        wm geometry $_topw +[expr {$X+1}]+[expr {$Y+1}]
        wm deiconify $_topw
        if {[catch {tkwait visibility $_topw}]} {
            return
        }
        BWidget::grab  set $_topw
        BWidget::focus set $_topw

        bindtags $_topw [list $_topw DragTop]
        DropSite::_init_drag $_topw $drag(evt) $source $state $X $Y $type $ops $data
    } else {
        destroy $_topw
    }
}


# ----------------------------------------------------------------------------
#  Command DragSite::_end_drag
# ----------------------------------------------------------------------------
proc DragSite::_end_drag { source target op type data result } {
    variable _topw
    upvar \#0 DragSite::$source drag

    BWidget::grab  release $_topw
    BWidget::focus release $_topw
    destroy $_topw
    if { $drag(endcmd) != "" } {
        uplevel \#0 $drag(endcmd) [list $source $target $op $type $data $result]
    }
}


Added lib/BWidget/drawerpanel.tcl.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
# ----------------------------------------------------------------------------
#  drawerpanel.tcl
#	Create Drawer Panel widget.
#  $Id$
# ----------------------------------------------------------------------------
#  Index of commands:
#     - DrawerPanel::cget
#     - DrawerPanel::configure
#     - DrawerPanel::create
#     - DrawerPanel::getframe
#     - DrawerPanel::insert
# ----------------------------------------------------------------------------

namespace eval DrawerPanel {
    Widget::define DrawerPanel drawerpanel IconLibrary

    Widget::declare DrawerPanel::Drawer {
	{-panelbackground        String       ""              0}
	{-panelforeground        String       ""              0}
	{-panelbackground2       String       ""              0}
	{-panelactiveforeground  String       ""              0}
        {-panelheight            Int          ""              0 "%d > 0"}
        {-animatespeed           Int          ""              0 "%d > -1"}
        {-gradientoffset         Int          ""              0 "%d > -1"}

	{-drawerbackground       String       ""              0}
	{-drawerwidth		 Int	      ""              0 "%d > -1"}
	{-drawerheight	         Int	      ""              0 "%d > -1"}

	{-font		         String       ""              0}
	{-text		         String       ""              0}
        {-bevel                  Boolean2     ""              0}
        {-pady                   Padding      ""              0}
        {-padx                   Padding      ""              0}
        {-ipadx                  Padding      ""              0}

        {-open                   Boolean      1               0}
    }

    Widget::tkinclude DrawerPanel frame :cmd \
        include {
            -background -bg -borderwidth -bd -relief
        }

    Widget::tkinclude DrawerPanel canvas .c \
        include {
            -background -bg -width -height
            -xscrollcommand -yscrollcommand -xscrollincrement -yscrollincrement
        } initialize {
            -width 200
        }

    Widget::declare DrawerPanel {
	{-font		         String       "TkTextFont"      0}
	{-panelbackground        String       "#FFFFFF"         0}
	{-panelforeground        String       "#000000"         0}
	{-panelbackground2       String       "#9898b534ffff"   0}
	{-panelactiveforeground  Color        "SystemHighlight" 0}
        {-panelheight            Int          20                0 "%d > 0"}
        {-gradientoffset         Int          75                0}
        {-animatespeed           Int          20                0}

	{-drawerbackground       String       "#9898b534ffff"   0}
	{-drawerwidth		 Int	      150               0 "%d > -1"}
	{-drawerheight	         Int	      100               0 "%d > -1"}

        {-bevel                  Boolean      1                 0}
        {-expand                 Boolean      0                 0}
        {-pady                   Padding      8                 0}
        {-padx                   Padding      10                0}
        {-ipadx                  Padding      10                0}
    }

    bind DrawerPanel <Configure> [list DrawerPanel::_configure %W %w %h]
}


proc DrawerPanel::create { path args } {
    BWidget::LoadBWidgetIconLibrary

    frame $path -class DrawerPanel
    if {[info tclversion] >= 8.4} { $path configure -padx 0 -pady 0 }

    Widget::init DrawerPanel $path $args

    Widget::getVariable $path data

    set data(Y)       0
    set data(image)   0
    set data(redraw)  0
    set data(frames)  [list]
    set data(drawers) [list]

    set data(width)   [Widget::getoption $path -drawerwidth]

    grid rowconfigure    $path 0 -weight 1
    grid columnconfigure $path 0 -weight 1

    canvas $path.c -borderwidth 0 -highlightthickness 0
    grid $path.c -row 0 -column 0 -sticky news

    $path.c bind link <1>     [list DrawerPanel::toggle $path]
    $path.c bind link <Enter> [list DrawerPanel::_highlight_drawer $path enter]
    $path.c bind link <Leave> [list DrawerPanel::_highlight_drawer $path leave]

    return [Widget::create DrawerPanel $path]
}


proc DrawerPanel::cget { path option } {
    return [Widget::cget $path $option]
}


proc DrawerPanel::configure { path args } {
    Widget::getVariable $path data

    set res [Widget::configure $path $args]

    set redraw [Widget::anyChangedX $path -padx -pady -ipadx -font \
        -background -drawerbackground -drawerheight -panelforeground -expand]

    set redrawImages [Widget::anyChangedX $path -panelheight -panelbackground \
        -panelbackground2 -gradientoffset -bevel -drawerwidth]

    if {$redraw || $redrawImages} { _redraw_idle $path $redrawImages }

    return $res
}


proc DrawerPanel::itemcget { path drawer option } {
    return [Widget::cget [getframe $path $drawer] $option]
}


proc DrawerPanel::itemconfigure { path drawer args } {
    Widget::getVariable $path data

    set frame [getframe $path $drawer]

    set res [Widget::configure $frame $args]

    if {[Widget::hasChanged $frame -drawerbackground bg]} {
        $frame configure -background $bg
    }

    if {[Widget::hasChanged $frame -panelforeground fg]} {
        $path.c itemconfigure $drawer-text -fill $fg
    }

    if {[Widget::hasChanged $frame -font font]} {
        set font [Widget::getOption -font "" $frame $path]
        $path.c itemconfigure $drawer-text -font $font
    }

    if {[Widget::hasChanged $frame -text text]} {
        $path.c itemconfigure $drawer-text -text $text
    }

    if {[Widget::hasChanged $frame -open open]} {
        if {$open} {
            DrawerPanel::open  $path $drawer
        } else {
            DrawerPanel::close $path $drawer
        }
    }

    set redraw [Widget::anyChangedX $frame -padx -pady -ipadx -drawerheight]

    set redrawImages [Widget::anyChangedX $frame -panelbackground \
        -panelbackground2 -gradientoffset -panelheight -bevel -drawerwidth]

    if {$redraw || $redrawImages} { _redraw_idle $path $redrawImages }

    return $res
}


proc DrawerPanel::getcanvas { path } {
    return $path.c
}


proc DrawerPanel::open { path drawer } {
    Widget::getVariable $path data

    set frame [getframe $path $drawer]

    Widget::setoption $frame -open 1

    set index  [expr [lsearch -exact $data(drawers) $drawer] + 1]
    set length [llength $data(drawers)]
    set height [Widget::getOption -drawerheight "" $frame $path]
    set amount [Widget::getOption -animatespeed "" $frame $path]

    $path.c itemconfigure $drawer-image \
        -image [BWidget::Icon nav2uparrow16]

    $path.c itemconfigure $frame -window $frame

    DrawerPanel::_animate_drawer $path $frame $index $length 0 $height $amount

    return
}


proc DrawerPanel::close { path drawer } {
    Widget::getVariable $path data

    set frame [getframe $path $drawer]

    Widget::setoption $frame -open 0

    set index  [expr [lsearch -exact $data(drawers) $drawer] + 1]
    set length [llength $data(drawers)]
    set height [Widget::getOption -drawerheight "" $frame $path]
    set amount [Widget::getOption -animatespeed "" $frame $path]
    set amount -$amount

    $path.c itemconfigure $drawer-image \
        -image [BWidget::Icon nav2downarrow16]

    DrawerPanel::_animate_drawer $path $frame $index $length $height 0 $amount

    return
}


proc DrawerPanel::toggle { path {drawer ""} } {
    if {![string length $drawer]} {
        set drawer [_get_drawer_from_item $path current]
        if {![DrawerPanel::exists $path $drawer]} { return }
    }

    set frame [getframe $path $drawer]

    if {[Widget::getoption $frame -open]} {
        DrawerPanel::close $path $drawer
    } else {
        DrawerPanel::open $path $drawer
    }

    return
}


proc DrawerPanel::exists { path drawer } {
    return [expr [DrawerPanel::index $path $drawer] > -1]
}


proc DrawerPanel::getframe { path drawer } {
    if {![DrawerPanel::exists $path $drawer]} {
        return -code error "drawer \"$drawer\" does not exist"
    }
    return $path.f$drawer
}


proc DrawerPanel::index { path drawer } {
    Widget::getVariable $path data
    return [lsearch -exact $data(drawers) $drawer]
}


proc DrawerPanel::drawers { path {first ""} {last ""} } {
    Widget::getVariable $path data
    if {![string length $first]} { return $data(drawers) }
    if {![string length $last]}  { return [lindex $data(drawers) $first] }
    return [lrange $data(drawers) $first $last]
}


proc DrawerPanel::order { path {order ""} } {
    Widget::getVariable $path data

    if {![string length $order]} { return $data(drawers) }

    set data(drawers) $order
    set data(frames)  [list]
    foreach drawer $data(drawers) {
        lappend data(frames) [getframe $path $drawer]
    }

    _redraw_idle $path
}


proc DrawerPanel::insert { path index drawer args } {
    Widget::getVariable $path data

    set drawer [Widget::nextIndex $path $drawer]

    if {[DrawerPanel::exists $path $drawer]} {
        return -code error "drawer \"$drawer\" already exists"
    }

    set frame $path.f$drawer
    Widget::init DrawerPanel::Drawer $frame $args

    set bg     [Widget::getOption -drawerbackground "" $frame $path]
    set width  [Widget::getOption -drawerwidth  "" $frame $path]
    set height [Widget::getOption -drawerheight "" $frame $path]

    frame $frame -width $width -height $height -background $bg
    pack propagate $frame 0
    grid propagate $frame 0

    set data(frames)  [linsert $data(frames)  $index $frame]
    set data(drawers) [linsert $data(drawers) $index $drawer]

    if {[string equal $index "end"]} {
        _draw_drawer $path $drawer
        _resize $path
    } else {
        _redraw_idle $path
    }

    return $frame
}


proc DrawerPanel::delete { path drawer } {
    Widget::getVariable $path data

    set frame [getframe $path $drawer]
    set index [index $path $drawer]

    set data(frames)  [lreplace $data(frames)  $index $index]
    set data(drawers) [lreplace $data(drawers) $index $index]

    destroy $frame

    _redraw_idle $path
}


proc DrawerPanel::xview { path args } {
    return [eval [list $path.c xview] $args]
}


proc DrawerPanel::yview { path args } {
    return [eval [list $path.c yview] $args]
}


proc DrawerPanel::_get_drawer_from_item { path item } {
    return [lindex [$path.c itemcget $item -tags] 1]
}


proc DrawerPanel::_highlight_drawer { path type } {
    set drawer [_get_drawer_from_item $path current]
    set frame  [getframe $path $drawer]

    switch -- $type {
        "leave" {
            set fill [Widget::getOption -panelforeground "" $frame $path]
        }
        "enter" {
            set fill [Widget::getOption -panelactiveforeground "" $frame $path]
        }
    }

    $path.c itemconfigure $drawer-text -fill $fill
}


proc DrawerPanel::_animate_drawer { path frame index length height max amt } {
    ## We use the value of max to determine if we're
    ## opening or closing this drawer.
    ## max == 0 == closing
    ## max >  0 == opening

    if {$height == $max} {
        if {!$max} { $path.c itemconfigure $frame -window "" }
        _resize $path
        return
    }

    incr height $amt

    set animate 1
    if {!$amt} {
        set amt     [expr {$max - $height}]
        set height  $max
        set animate 0
    } elseif {$amt > 0 && $height > $max} {
        set amt    [expr {$max - $height + $amt}]
        set height $max
    } elseif {$amt < 0 && $height < $max} {
        set amt    [expr {$max - $height + $amt}]
        set height $max
    }

    $frame configure -height $height
    if {!$max && !$animate} { $path.c itemconfigure $frame -window "" }

    _move_drawers $path $index $length $amt

    update idletasks

    if {$animate} {
        after 10 [lreplace [info level 0] 5 5 $height]
    } else {
        _resize $path
    }
}


proc DrawerPanel::_move_drawers { path start length amt } {
    for {set i $start} {$i < $length} {incr i} {
        $path.c move idx$i 0 $amt
    }
}


proc DrawerPanel::_get_drawer_colors { path drawer } {
    Widget::getVariable $path data

    set frame  [getframe $path $drawer]
    set width  [Widget::getOption -drawerwidth      "" $frame $path]
    set offset [Widget::getOption -gradientoffset   "" $frame $path]
    set color1 [Widget::getOption -panelbackground  "" $frame $path]
    set color2 [Widget::getOption -panelbackground2 "" $frame $path]
    set color1 [BWidget::color2hex $path $color1]
    set color2 [BWidget::color2hex $path $color2]
    if {[Widget::getoption $path -expand]} { set width $data(width) }

    return [BWidget::getGradientColors $color1 $color2 $width $offset]
}


proc DrawerPanel::_get_drawer_image { path drawer {force 0} } {
    Widget::getVariable $path data

    set frame  [getframe $path $drawer]
    set padx   [DrawerPanel::_get_padding $path $frame -padx 0]
    set padx2  [DrawerPanel::_get_padding $path $frame -padx 1]
    set bevel  [Widget::getOption -bevel            "" $frame $path]
    set width  [Widget::getOption -drawerwidth      "" $frame $path]
    set height [Widget::getOption -panelheight      "" $frame $path]
    set offset [Widget::getOption -gradientoffset   "" $frame $path]
    set color1 [Widget::getOption -panelbackground  "" $frame $path]
    set color2 [Widget::getOption -panelbackground2 "" $frame $path]
    set color1 [BWidget::color2hex $path $color1]
    set color2 [BWidget::color2hex $path $color2]
    set colors [_get_drawer_colors $path $drawer]

    if {[Widget::getoption $path -expand]} { set width $data(width) }

    set width [expr {$width - $padx - $padx2}]

    set key $path:$color1:$color2:$offset:$width:$height:$bevel
    if {!$force && [info exists data(image,$key)]} { return $data(image,$key) }

    set data(image,$key) \
        [image create photo DrawerPanel::$path[incr data(image)]]
    _redraw_image $path $data(image,$key) $colors $width $height $bevel

    return $data(image,$key)
}


proc DrawerPanel::_bevel_image { path image width } {
    set bg [BWidget::color2hex $path [Widget::cget $path -background]]

    $image put $bg -to 0 0
    $image put $bg -to 0 1
    $image put $bg -to 1 0
    $image put $bg -to [expr {$width - 2}] 0
    $image put $bg -to [expr {$width - 1}] 0
    $image put $bg -to [expr {$width - 1}] 1
}


proc DrawerPanel::_redraw_image { path image colors width height {bevel 0} } {
    for {set i 0} {$i < $height} {incr i} {
        lappend imagedata $colors
    }

    $image blank
    $image configure -height $height -width $width
    $image put $imagedata

    if {$bevel} { _bevel_image $path $image $width }
}


proc DrawerPanel::_draw_drawer { path drawer {Y ""} } {
    Widget::getVariable $path data

    if {![string length $Y]} { set Y $data(Y) }

    set c [getcanvas $path]

    set frame   [getframe $path $drawer]
    set image   [_get_drawer_image $path $drawer]
    set index   [lsearch -exact $data(drawers) $drawer]
    set width   [Widget::cgetOption -drawerwidth  "" $frame $path]
    set height  [Widget::cgetOption -drawerheight "" $frame $path]
    set pheight [Widget::getOption  -panelheight  "" $frame $path]
    set padx    [DrawerPanel::_get_padding $path $frame -padx 0]
    set padx2   [DrawerPanel::_get_padding $path $frame -padx 1]
    set ipadx   [DrawerPanel::_get_padding $path $frame -ipadx 0]
    set ipadx2  [DrawerPanel::_get_padding $path $frame -ipadx 1]

    if {[Widget::getoption $path -expand]} { set width $data(width) }

    set data($drawer,Y) $Y

    incr Y [DrawerPanel::_get_padding $path $frame -pady 0]
    $path.c create image $padx $Y -anchor nw -image $image \
        -tags [list idx$index $drawer $drawer-panel link]

    $path.c create text \
        [expr {$padx + $ipadx}] [expr {$Y + ($pheight / 2)}] \
        -text [Widget::getoption $frame -text] \
        -font [Widget::getOption -font "" $frame $path] \
        -fill [Widget::getOption -panelforeground "" $frame $path] \
        -anchor w -tags [list idx$index $drawer $drawer-text link]

    set image nav2downarrow16
    if {[Widget::getoption $frame -open]} { set image nav2uparrow16 }

    $path.c create image \
        [expr {$width - $padx - $padx2 - $ipadx2}] \
        [expr {$Y + ($pheight / 2)}] \
        -image [BWidget::Icon $image] -anchor w \
        -tags [list idx$index $drawer $drawer-image link]

    incr Y $pheight

    $path.c create window $padx $Y -anchor nw \
        -tags [list idx$index $drawer $drawer-frame $frame]
    $frame configure -height $height -width [expr {$width - $padx - $padx2}]

    if {[Widget::getoption $frame -open]} {
        $path.c itemconfigure $drawer-frame -window $frame
        incr Y [Widget::getOption -drawerheight "" $frame $path]
    }

    incr Y [DrawerPanel::_get_padding $path $frame -pady 1]

    set data(Y) $Y
}


proc DrawerPanel::_get_padding { path frame option index } {
    set value [Widget::getOption $option "" $frame $path]
    return [Widget::_get_padding $value $index]
}


proc DrawerPanel::_resize { path } {
    set bbox [$path.c bbox all]
    if {![llength $bbox]} { return }
    set bbox [lreplace $bbox 0 1 0 0]
    $path.c configure -scrollregion $bbox
}


proc DrawerPanel::_redraw_idle { path {redrawImages 0} } {
    Widget::getVariable $path data

    if {!$data(redraw)} {
        after idle [list DrawerPanel::_redraw $path $redrawImages]
        set data(redraw) 1
    }
}


proc DrawerPanel::_redraw { path {redrawImages 0} } {
    Widget::getVariable $path data

    $path.c delete all

    if {$redrawImages} {
        ## Destroy all of the panel images.
        foreach image [array names data image,*] {
            image delete $data($image)
            unset data($image)
        }
    }

    set Y 0
    foreach drawer $data(drawers) {
        set Y [_draw_drawer $path $drawer $Y]
    }

    _resize $path

    set data(redraw) 0

    return
}


proc DrawerPanel::_configure { path width height } {
    Widget::getVariable $path data

    if {$width == $data(width)} { return }

    set data(width) $width

    if {[Widget::getoption $path -expand]} {
        ## Redraw all the drawers.
        _redraw $path 1
    }
}
Added lib/BWidget/dropsite.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
# ------------------------------------------------------------------------------
#  dropsite.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: dropsite.tcl,v 1.7 2003/10/20 21:23:52 damonc Exp $
# ------------------------------------------------------------------------------
#  Index of commands:
#     - DropSite::include
#     - DropSite::setdrop
#     - DropSite::register
#     - DropSite::setcursor
#     - DropSite::setoperation
#     - DropSite::_update_operation
#     - DropSite::_compute_operation
#     - DropSite::_draw_operation
#     - DropSite::_init_drag
#     - DropSite::_motion
#     - DropSite::_release
# ----------------------------------------------------------------------------


namespace eval DropSite {
    Widget::define DropSite dropsite -classonly

    Widget::declare DropSite [list \
	    [list -dropovercmd String "" 0] \
	    [list -dropcmd     String "" 0] \
	    [list -droptypes   String "" 0] \
	    ]

    proc use {} {}

    variable _top  ".#BWidget#drag"
    variable _opw  "$_top.\#op"
    variable _target  ""
    variable _status  0
    variable _tabops
    variable _defops
    variable _source
    variable _type
    variable _data
    variable _evt
    # key       win    unix
    # shift       1   |   1    ->  1
    # control     4   |   4    ->  4
    # alt         8   |  16    -> 24
    # meta            |  64    -> 88

    array set _tabops {
        mod,none    0
        mod,shift   1
        mod,control 4
        mod,alt     24
        ops,copy    1
        ops,move    1
        ops,link    1
    }

    if { $tcl_platform(platform) == "unix" } {
        set _tabops(mod,alt) 8
    } else {
        set _tabops(mod,alt) 16
    }
    array set _defops \
        [list \
             copy,mod  shift   \
             move,mod  control \
             link,mod  alt     \
             copy,img  @[file join $::BWIDGET::LIBRARY "images" "opcopy.xbm"] \
             move,img  @[file join $::BWIDGET::LIBRARY "images" "opmove.xbm"] \
             link,img  @[file join $::BWIDGET::LIBRARY "images" "oplink.xbm"]]

    bind DragTop <KeyPress-Shift_L>     {DropSite::_update_operation [expr %s | 1]}
    bind DragTop <KeyPress-Shift_R>     {DropSite::_update_operation [expr %s | 1]}
    bind DragTop <KeyPress-Control_L>   {DropSite::_update_operation [expr %s | 4]}
    bind DragTop <KeyPress-Control_R>   {DropSite::_update_operation [expr %s | 4]}
    if { $tcl_platform(platform) == "unix" } {
        bind DragTop <KeyPress-Alt_L>       {DropSite::_update_operation [expr %s | 8]}
        bind DragTop <KeyPress-Alt_R>       {DropSite::_update_operation [expr %s | 8]}
    } else {
        bind DragTop <KeyPress-Alt_L>       {DropSite::_update_operation [expr %s | 16]}
        bind DragTop <KeyPress-Alt_R>       {DropSite::_update_operation [expr %s | 16]}
    }

    bind DragTop <KeyRelease-Shift_L>   {DropSite::_update_operation [expr %s & ~1]}
    bind DragTop <KeyRelease-Shift_R>   {DropSite::_update_operation [expr %s & ~1]}
    bind DragTop <KeyRelease-Control_L> {DropSite::_update_operation [expr %s & ~4]}
    bind DragTop <KeyRelease-Control_R> {DropSite::_update_operation [expr %s & ~4]}
    if { $tcl_platform(platform) == "unix" } {
        bind DragTop <KeyRelease-Alt_L>     {DropSite::_update_operation [expr %s & ~8]}
        bind DragTop <KeyRelease-Alt_R>     {DropSite::_update_operation [expr %s & ~8]}
    } else {
        bind DragTop <KeyRelease-Alt_L>     {DropSite::_update_operation [expr %s & ~16]}
        bind DragTop <KeyRelease-Alt_R>     {DropSite::_update_operation [expr %s & ~16]}
    }
}


# ----------------------------------------------------------------------------
#  Command DropSite::include
# ----------------------------------------------------------------------------
proc DropSite::include { class types } {
    set dropoptions [list \
	    [list	-dropenabled	Boolean	0	0] \
	    [list	-dropovercmd	String	""	0] \
	    [list	-dropcmd	String	""	0] \
	    [list	-droptypes	String	$types	0] \
	    ]
    Widget::declare $class $dropoptions
}


# ----------------------------------------------------------------------------
#  Command DropSite::setdrop
#  Widget interface to register
# ----------------------------------------------------------------------------
proc DropSite::setdrop { path subpath dropover drop {force 0}} {
    set cen    [Widget::hasChanged $path -dropenabled en]
    set ctypes [Widget::hasChanged $path -droptypes   types]
    if { $en } {
        if { $force || $cen || $ctypes } {
            register $subpath \
                -droptypes   $types \
                -dropcmd     $drop  \
                -dropovercmd $dropover
        }
    } else {
        register $subpath
    }
}


# ----------------------------------------------------------------------------
#  Command DropSite::register
# ----------------------------------------------------------------------------
proc DropSite::register { path args } {
    variable _tabops
    variable _defops
    upvar \#0 DropSite::$path drop

    Widget::init DropSite .drop$path $args
    if { [info exists drop] } {
        unset drop
    }
    set dropcmd [Widget::getoption .drop$path -dropcmd]
    set types   [Widget::getoption .drop$path -droptypes]
    set overcmd [Widget::getoption .drop$path -dropovercmd]
    Widget::destroy .drop$path
    if { $dropcmd != "" && $types != "" } {
        set drop(dropcmd) $dropcmd
        set drop(overcmd) $overcmd
        foreach {type ops} $types {
            set drop($type,ops) {}
            foreach {descop lmod} $ops {
                if { ![llength $descop] || [llength $descop] > 3 } {
                    return -code error "invalid operation description \"$descop\""
                }
                foreach {subop baseop imgop} $descop {
                    set subop [string trim $subop]
                    if { ![string length $subop] } {
                        return -code error "sub operation is empty"
                    }
                    if { ![string length $baseop] } {
                        set baseop $subop
                    }
                    if { [info exists drop($type,ops,$subop)] } {
                        return -code error "operation \"$subop\" already defined"
                    }
                    if { ![info exists _tabops(ops,$baseop)] } {
                        return -code error "invalid base operation \"$baseop\""
                    }
                    if { ![string equal $subop $baseop] &&
                         [info exists _tabops(ops,$subop)] } {
                        return -code error "sub operation \"$subop\" is a base operation"
                    }
                    if { ![string length $imgop] } {
                        set imgop $_defops($baseop,img)
                    }
                }
                if { [string equal $lmod "program"] } {
                    set drop($type,ops,$subop) $baseop
                    set drop($type,img,$subop) $imgop
                } else {
                    if { ![string length $lmod] } {
                        set lmod $_defops($baseop,mod)
                    }
                    set mask 0
                    foreach mod $lmod {
                        if { ![info exists _tabops(mod,$mod)] } {
                            return -code error "invalid modifier \"$mod\""
                        }
                        set mask [expr {$mask | $_tabops(mod,$mod)}]
                    }
                    if { ($mask == 0) != ([string equal $subop "default"]) } {
                        return -code error "sub operation default can only be used with modifier \"none\""
                    }
                    set drop($type,mod,$mask)  $subop
                    set drop($type,ops,$subop) $baseop
                    set drop($type,img,$subop) $imgop
                    lappend masklist $mask
                }
            }
            if { ![info exists drop($type,mod,0)] } {
                set drop($type,mod,0)       default
                set drop($type,ops,default) copy
                set drop($type,img,default) $_defops(copy,img)
                lappend masklist 0
            }
            set drop($type,ops,force) copy
            set drop($type,img,force) $_defops(copy,img)
            foreach mask [lsort -integer -decreasing $masklist] {
                lappend drop($type,ops) $mask $drop($type,mod,$mask)
            }
        }
    }
}


# ----------------------------------------------------------------------------
#  Command DropSite::setcursor
# ----------------------------------------------------------------------------
proc DropSite::setcursor { cursor } {
    variable _top
    catch {$_top configure -cursor $cursor}
}


# ----------------------------------------------------------------------------
#  Command DropSite::setoperation
# ----------------------------------------------------------------------------
proc DropSite::setoperation { op } {
    variable _curop
    variable _dragops
    variable _target
    variable _type
    upvar \#0 DropSite::$_target drop

    if { [info exist drop($_type,ops,$op)] &&
         $_dragops($drop($_type,ops,$op)) } {
        set _curop $op
    } else {
        # force to a copy operation
        set _curop force
    }
}


# ----------------------------------------------------------------------------
#  Command DropSite::_init_drag
# ----------------------------------------------------------------------------
proc DropSite::_init_drag { top evt source state X Y type ops data } {
    variable _top
    variable _source
    variable _type
    variable _data
    variable _target
    variable _status
    variable _state
    variable _dragops
    variable _opw
    variable _evt

    if {[info exists _dragops]} {
        unset _dragops
    }
    array set _dragops {copy 1 move 0 link 0}
    foreach op $ops {
        set _dragops($op) 1
    }
    set _target ""
    set _status  0
    set _top     $top
    set _source  $source
    set _type    $type
    set _data    $data

    label $_opw -relief flat -bd 0 -highlightthickness 0 \
        -foreground #000000 -background #FFFFFF

    bind $top <ButtonRelease-$evt> {DropSite::_release %X %Y}
    bind $top <B$evt-Motion>       {DropSite::_motion  %X %Y}
    bind $top <Motion>             {DropSite::_release %X %Y}
    set _state $state
    set _evt   $evt
    _motion $X $Y
}


# ----------------------------------------------------------------------------
#  Command DropSite::_update_operation
# ----------------------------------------------------------------------------
proc DropSite::_update_operation { state } {
    variable _top
    variable _status
    variable _state

    if { $_status & 3 } {
        set _state $state
        _motion [winfo pointerx $_top] [winfo pointery $_top]
    }
}


# ----------------------------------------------------------------------------
#  Command DropSite::_compute_operation
# ----------------------------------------------------------------------------
proc DropSite::_compute_operation { target state type } {
    variable  _curop
    variable  _dragops
    upvar \#0 DropSite::$target drop

    foreach {mask op} $drop($type,ops) {
        if { ($state & $mask) == $mask } {
            if { $_dragops($drop($type,ops,$op)) } {
                set _curop $op
                return
            }
        }
    }
    set _curop force
}


# ----------------------------------------------------------------------------
#  Command DropSite::_draw_operation
# ----------------------------------------------------------------------------
proc DropSite::_draw_operation { target type } {
    variable _opw
    variable _curop
    variable _dragops
    variable _tabops
    variable _status

    upvar \#0 DropSite::$target drop

    if { !($_status & 1) } {
        catch {place forget $_opw}
        return
    }

    if { 0 } {
    if { ![info exist drop($type,ops,$_curop)] ||
         !$_dragops($drop($type,ops,$_curop)) } {
        # force to a copy operation
        set _curop copy
        catch {
            $_opw configure -bitmap $_tabops(img,copy)
            place $_opw -relx 1 -rely 1 -anchor se
        }
    }
    } elseif { [string equal $_curop "default"] } {
        catch {place forget $_opw}
    } else {
        catch {
            $_opw configure -bitmap $drop($type,img,$_curop)
            place $_opw -relx 1 -rely 1 -anchor se
        }
    }
}


# ----------------------------------------------------------------------------
#  Command DropSite::_motion
# ----------------------------------------------------------------------------
proc DropSite::_motion { X Y } {
    variable _top
    variable _target
    variable _status
    variable _state
    variable _curop
    variable _type
    variable _data
    variable _source
    variable _evt

    set script [bind $_top <B$_evt-Motion>]
    bind $_top <B$_evt-Motion> {}
    bind $_top <Motion>        {}
    wm geometry $_top "+[expr {$X+1}]+[expr {$Y+1}]"
    update
    if { ![winfo exists $_top] } {
        return
    }
    set path [winfo containing $X $Y]
    if { ![string equal $path $_target] } {
        # path != current target
        if { $_status & 2 } {
            # current target is valid and has recall status
            # generate leave event
            upvar   \#0 DropSite::$_target drop
            uplevel \#0 $drop(overcmd) [list $_target $_source leave $X $Y $_curop $_type $_data]
        }
        set _target $path
        upvar \#0 DropSite::$_target drop
        if { [info exists drop($_type,ops)] } {
            # path is a valid target
            _compute_operation $_target $_state $_type
            if { $drop(overcmd) != "" } {
                set arg     [list $_target $_source enter $X $Y $_curop $_type $_data]
                set _status [uplevel \#0 $drop(overcmd) $arg]
            } else {
                set _status 1
                catch {$_top configure -cursor based_arrow_down}
            }
            _draw_operation $_target $_type
            update
            catch {
                bind $_top <B$_evt-Motion> {DropSite::_motion  %X %Y}
                bind $_top <Motion>        {DropSite::_release %X %Y}
            }
            return
        } else {
            set _status 0
            catch {$_top configure -cursor dot}
            _draw_operation "" ""
        }
    } elseif { $_status & 2 } {
        upvar \#0 DropSite::$_target drop
        _compute_operation $_target $_state $_type
        set arg     [list $_target $_source motion $X $Y $_curop $_type $_data]
        set _status [uplevel \#0 $drop(overcmd) $arg]
        _draw_operation $_target $_type
    }
    update
    catch {
        bind $_top <B$_evt-Motion> {DropSite::_motion  %X %Y}
        bind $_top <Motion>        {DropSite::_release %X %Y}
    }
}



# ----------------------------------------------------------------------------
#  Command DropSite::_release
# ----------------------------------------------------------------------------
proc DropSite::_release { X Y } {
    variable _target
    variable _status
    variable _curop
    variable _source
    variable _type
    variable _data

    if { $_status & 1 } {
        upvar \#0 DropSite::$_target drop

        set res [uplevel \#0 $drop(dropcmd) [list $_target $_source $X $Y $_curop $_type $_data]]
        DragSite::_end_drag $_source $_target $drop($_type,ops,$_curop) $_type $_data $res
        event generate $_target <<Drop>>
    } else {
        if { $_status & 2 } {
            # notify leave event
            upvar \#0 DropSite::$_target drop
            uplevel \#0 $drop(overcmd) [list $_target $_source leave $X $Y $_curop $_type $_data]
        }
        DragSite::_end_drag $_source "" "" $_type $_data 0
    }
}
Added lib/BWidget/dynhelp.tcl.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
# ----------------------------------------------------------------------------
#  dynhelp.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: dynhelp.tcl,v 1.13 2003/10/20 21:23:52 damonc Exp $
# ----------------------------------------------------------------------------
#  Index of commands:
#     - DynamicHelp::configure
#     - DynamicHelp::include
#     - DynamicHelp::sethelp
#     - DynamicHelp::register
#     - DynamicHelp::_motion_balloon
#     - DynamicHelp::_motion_info
#     - DynamicHelp::_leave_info
#     - DynamicHelp::_menu_info
#     - DynamicHelp::_show_help
#     - DynamicHelp::_init
# ----------------------------------------------------------------------------

namespace eval DynamicHelp {
    Widget::define DynamicHelp dynhelp -classonly

    Widget::declare DynamicHelp {
        {-foreground     Color      "#000000"       0}
        {-topbackground  Color      "#000000"       0}
        {-background     Color      "#FFFFC0"       0}
        {-borderwidth    Int        1               0}
        {-justify        TkResource left            0 label}
        {-font           String     "TkTooltipFont" 0}
        {-delay          Int        600             0 "%d >= 100 & %d <= 2000"}
	{-state          Enum       "normal"        0 {normal disabled}}
        {-padx           Int        1               0}
        {-pady           Int        1               0}

        {-bd             Synonym    -borderwidth}
        {-bg             Synonym    -background}
        {-fg             Synonym    -foreground}
        {-topbg          Synonym    -topbackground}
    }

    Widget::declare DynamicHelp::Node {
        {-row            Int             ""         0}
        {-col            Int             ""         0}
        {-cell           String          ""         0}

        {-tag            String          ""         0}
        {-type           String          "balloon"  0}
        {-text           String          ""         0}
        {-item           String          ""         0}
        {-index          Int             "-1"       0}
        {-command        String          ""         0}
        {-variable       String          ""         0}
        {-destroyballoon Enum            "leave"    0 {leave motion}}
    }

    variable _saved
    variable _widgets
    variable _registered

    variable _top     ".#Bwidget#helpBalloon"
    variable _id      ""
    variable _delay   600
    variable _current_balloon  ""
    variable _current_variable ""

    Widget::init DynamicHelp $_top [list]

    bind BwHelpBalloon <Enter>   {DynamicHelp::_motion_balloon enter  %W %X %Y}
    bind BwHelpBalloon <Motion>  {DynamicHelp::_motion_balloon motion %W %X %Y}
    bind BwHelpBalloon <Leave>   {DynamicHelp::_motion_balloon leave  %W %X %Y}
    bind BwHelpBalloon <Button>  {DynamicHelp::_motion_balloon button %W %X %Y}

    bind BwHelpVariable <Enter>  {DynamicHelp::_motion_info %W}
    bind BwHelpVariable <Motion> {DynamicHelp::_motion_info %W}
    bind BwHelpVariable <Leave>  {DynamicHelp::_leave_info  %W}

    bind BwHelpMenu <Unmap>        {DynamicHelp::_menu_info unmap  %W}
    bind BwHelpMenu <<MenuSelect>> {DynamicHelp::_menu_info select %W}

    bind BwHelpTableBalloon <Leave>  { DynamicHelp::_table_leave balloon %W }
    bind BwHelpTableBalloon <Motion> {
        DynamicHelp::_table_motion balloon %W %X %Y %x %y
    }

    bind BwHelpTableVariable <Leave>  { DynamicHelp::_table_leave variable %W }
    bind BwHelpTableVariable <Motion> {
        DynamicHelp::_table_motion variable %W %X %Y %x %y
    }

    bind BwHelpDestroy <Destroy> [list DynamicHelp::_unset_help %W]
}


# ----------------------------------------------------------------------------
#  Command DynamicHelp::configure
# ----------------------------------------------------------------------------
proc DynamicHelp::configure { args } {
    variable _top
    variable _delay

    set res [Widget::configure $_top $args]
    if { [Widget::hasChanged $_top -delay val] } {
        set _delay $val
    }

    return $res
}


# ----------------------------------------------------------------------------
#  Command DynamicHelp::include
# ----------------------------------------------------------------------------
proc DynamicHelp::include { class type } {
    set helpoptions [list \
        [list -helptext    String    ""    0] \
        [list -helpvar     String    ""    0] \
        [list -helpcommand String    ""    0] \
        [list -helptype    Enum      $type 0 [list balloon variable]] \
    ]
    Widget::declare $class $helpoptions
}


# ----------------------------------------------------------------------------
#  Command DynamicHelp::sethelp
# ----------------------------------------------------------------------------
proc DynamicHelp::sethelp { path subpath {force 0} } {
    set vars [list -helptype -helptext -helpvar -helpcommand]
    if {$force || [eval [list Widget::anyChangedX $path] $vars]} {
	set type [Widget::cget $path -helptype]
        set txt  [Widget::cget $path -helptext]
        set cmd  [Widget::cget $path -helpcommand]

        switch $type {
            "balloon" {
                add $subpath -text $txt -command $cmd
            }

            "variable" {
                set var [Widget::cget $path -helpvar]
                add $subpath -text $txt -type $type -command $cmd -variable $var
            }

            default {
                return [register $subpath $type]
            }
        }
    }
}

# ----------------------------------------------------------------------------
#  Command DynamicHelp::register ( DEPRECATED -- USE DynamicHelp::add )
#
#  DynamicHelp::register path balloon  ?itemOrTag? text
#  DynamicHelp::register path variable ?itemOrTag? text varName
#  DynamicHelp::register path menu varName
#  DynamicHelp::register path menuentry index text
# ----------------------------------------------------------------------------
proc DynamicHelp::register { path type args } {
    variable _registered

    set len [llength $args]
    if {$type == "balloon"  && $len > 1} { set type canvasBalloon  }
    if {$type == "variable" && $len > 2} { set type canvasVariable }

    if { ![winfo exists $path] } {
        _unset_help $path
        return 0
    }

    switch $type {
        "balloon" {
            set data(-text) [lindex $args 0]
        }

        "canvasBalloon" {
            set data(-item) [lindex $args 0]
            set data(-text) [lindex $args 1]
        }

        "variable" {
            set data(-type)     variable
            set data(-variable) [lindex $args 0]
            set data(-text)     [lindex $args 1]
        }

        "canvasVariable" {
            set data(-type)     variable
            set data(-item)     [lindex $args 0]
            set data(-variable) [lindex $args 1]
            set data(-text)     [lindex $args 2]
        }

        "menu" {
            set data(-type)     menu
            set data(-variable) [lindex $args 0]
        }

        "menuentry" {
            set data(-type)  menu
            set data(-index) [lindex $args 0]
            set data(-text)  [lindex $args 1]
        }

        default {
            _unset_help $path
	    return 0
        }
    }

    foreach option [list -text -variable -index] {
        if {[info exists data($option)] && [string equal $data($option) ""]} {
            _unset_help $path
            return 0
        }
    }

    eval [list DynamicHelp::add $path] [array get data]

    return 1
}


proc DynamicHelp::add { path args } {
    variable _registered

    set node #DynamicHelp#$path
    Widget::init DynamicHelp::Node $node $args

    if {[winfo exists $path] && [string equal [winfo class $path] "Menu"]} {
        Widget::configure $node [list -type menu]
    }

    set name     $path
    set tag      [Widget::getoption $node -tag]
    set item     [Widget::getoption $node -item]
    set type     [Widget::getoption $node -type]
    set text     [Widget::getoption $node -text]
    set variable [Widget::getoption $node -variable]

    set row      [Widget::getoption $node -row]
    set col      [Widget::getoption $node -col]
    set cell     [Widget::getoption $node -cell]

    switch -- $type {
        "balloon" {
            if {[string length $item]} {
                _add_canvas_balloon $path $text $item
                set name $path,$item
            } elseif {[string length $tag]} {
                _add_text_balloon $path $text $tag
                set name $path,$tag
            } elseif {[string length $cell]} {
                _add_table_balloon $path $text $cell
                set name $path,$cell
            } elseif {[string length $row]} {
                _add_table_balloon $path $text row,$row
                set name $path,row,$row
            } elseif {[string length $col]} {
                _add_table_balloon $path $text col,$col
                set name $path,col,$col
            } else {
                _add_balloon $path $text
            }

            if {[string length $variable]} {
		set _registered($tag,balloonVar) $variable
	    }
        }

        "variable" {
            set var $variable
            if {[string length $item]} {
                _add_canvas_variable $path $text $var $item
                set name $path,$item
            } elseif {[string length $tag]} {
                _add_text_variable $path $text $var $tag
                set name $path,$tag
            } elseif {[string length $cell]} {
                _add_table_variable $path $text $var $cell
                set name $path,$cell
            } elseif {[string length $row]} {
                _add_table_variable $path $text $var row,$row
                set name $path,row,$row
            } elseif {[string length $col]} {
                _add_table_variable $path $text $var col,$col
                set name $path,col,$col
            } else {
                _add_variable $path $text $var
            }
        }

        "menu" {
            set index [Widget::getoption $node -index]

            if {$index != -1} {
                set cpath [BWidget::clonename $path]
                if { [winfo exists $cpath] } { set path $cpath }
                if {![info exists _registered($path)]} { return 0 }
                _add_menuentry $path $text $index
                set name $path,$index
            } else {
                _add_menu $path $variable
            }
        }

        default {
            return 0
        }
    }

    set command [Widget::getoption $node -command]
    if {[string length $command]} { set _registered($name,command) $command }

    return 1
}


proc DynamicHelp::delete { path } {
    _unset_help $path
}


proc DynamicHelp::itemcget { path option } {
    set item #DynamicHelp#$path
    if {![Widget::exists $item]} {
        return -code error "no dynamic help found for $path"
    }
    return [Widget::getoption $item $option]
}


proc DynamicHelp::itemconfigure { path args } {
    set item #DynamicHelp#$path
    if {![Widget::exists $item]} {
        return -code error "no dynamic help found for $path"
    }
    return [Widget::configure $item $args]
}


proc DynamicHelp::_add_bind_tag { path args } {
    set evt [bindtags $path]
    set found 0
    foreach tag $args {
        if {[lsearch -exact $evt $tag] < 0} {
            set found 1
            lappend evt $tag
        }
    }
    if {$found} { bindtags $path $evt }
    return $found
}


proc DynamicHelp::_add_balloon { path text } {
    variable _registered
    set _registered($path,balloon) $text
    _add_bind_tag $path BwHelpBalloon BwHelpDestroy
}


proc DynamicHelp::_add_canvas_balloon { path text tagOrItem } {
    set DynamicHelp::_registered($path,$tagOrItem,balloon) $text

    if {[DynamicHelp::_add_bind_tag $path BwHelpBalloon BwHelpDestroy]} {
        ## This canvas doesn't have the bindings yet.

        $path bind BwHelpBalloon <Enter> \
            [list DynamicHelp::_motion_balloon enter  %W %X %Y canvas]
        $path bind BwHelpBalloon <Motion> \
            [list DynamicHelp::_motion_balloon motion %W %X %Y canvas]
        $path bind BwHelpBalloon <Leave> \
            [list DynamicHelp::_motion_balloon leave  %W %X %Y canvas]
        $path bind BwHelpBalloon <Button> \
            [list DynamicHelp::_motion_balloon button %W %X %Y canvas]
    }

    $path addtag BwHelpBalloon withtag $tagOrItem
}


proc DynamicHelp::_add_text_balloon { path text tag } {
    set DynamicHelp::_registered($path,$tag,balloon) $text

    _add_bind_tag $path BwHelpDestroy

    $path tag bind $tag <Enter> \
        [list DynamicHelp::_motion_balloon enter  %W %X %Y text $tag]
    $path tag bind $tag <Motion> \
        [list DynamicHelp::_motion_balloon motion %W %X %Y text $tag]
    $path tag bind $tag <Leave> \
        [list DynamicHelp::_motion_balloon leave  %W %X %Y text $tag]
    $path tag bind $tag <Button> \
        [list DynamicHelp::_motion_balloon button %W %X %Y text $tag]
}


proc DynamicHelp::_add_table_balloon { path text cell } {
    set DynamicHelp::_registered($path,$cell,balloon) $text
    _add_bind_tag $path BwHelpTableBalloon BwHelpDestroy
}


proc DynamicHelp::_add_variable { path text varName } {
    set DynamicHelp::_registered($path,variable) [list $varName $text]
    _add_bind_tag $path BwHelpVariable BwHelpDestroy
}


proc DynamicHelp::_add_canvas_variable { path text varName tagOrItem } {
    set DynamicHelp::_registered($path,$tagOrItem,variable) \
        [list $varName $text]

    if {[DynamicHelp::_add_bind_tag $path BwHelpVariable BwHelpDestroy]} {
        ## This canvas doesn't have the bindings yet.

        $path bind BwHelpVariable <Enter> \
            [list DynamicHelp::_motion_info %W canvas]
        $path bind BwHelpVariable <Motion> \
            [list DynamicHelp::_motion_info %W canvas]
        $path bind BwHelpVariable <Leave> \
            [list DynamicHelp::_leave_info  %W canvas]
    }

    $path addtag BwHelpVariable withtag $tagOrItem
}


proc DynamicHelp::_add_text_variable { path text varName tag } {
    set DynamicHelp::_registered($path,$tag,variable) [list $varName $text]

    _add_bind_tag $path BwHelpDestroy

    $path tag bind $tag <Enter>  [list DynamicHelp::_motion_info %W text $tag]
    $path tag bind $tag <Motion> [list DynamicHelp::_motion_info %W text $tag]
    $path tag bind $tag <Leave>  [list DynamicHelp::_leave_info  %W text $tag]
}


proc DynamicHelp::_add_table_variable { path text varName cell } {
    set DynamicHelp::_registered($path,$cell,variable) [list $varName $text]
    _add_bind_tag $path BwHelpTableVariable BwHelpDestroy
}


proc DynamicHelp::_add_menu { path varName } {
    set cpath [BWidget::clonename $path]
    if {[winfo exists $cpath]} { set path $cpath }

    set DynamicHelp::_registered($path) [list $varName]
    _add_bind_tag $path BwHelpMenu BwHelpDestroy
}


proc DynamicHelp::_add_menuentry { path text index } {
    variable _registered

    set idx  [lsearch $_registered($path) [list $index *]]
    set list [list $index $text]
    if { $idx == -1 } {
	lappend _registered($path) $list
    } else {
	set _registered($path) \
	    [lreplace $_registered($path) $idx $idx $list]
    }
}


proc DynamicHelp::_table_motion { type table X Y x y } {
    variable _registered

    set row  [$table index @$x,$y row]
    set col  [$table index @$x,$y col]
    set cell $row,$col
    set path $table

    if {[info exists _registered($table,$cell,$type)]} {
        set path $table,$cell
    } elseif {[info exists _registered($table,row,$row,$type)]} {
        set path $table,row,$row
    } elseif {[info exists _registered($table,col,$col,$type)]} {
        set path $table,col,$col
    }

    if {[string equal $type "balloon"]} {
        variable _id
        variable _top
        variable _delay
        variable _current_balloon

        set event [Widget::getoption #DynamicHelp#$table -destroyballoon]
        if {[string equal $event "motion"]} { _destroy_balloon $_top }

        if {![string equal $_current_balloon $path]} {
            _destroy_balloon $_top
            set _current_balloon $path
        }

        if {[string length $_id]} {
            after cancel $_id
            set _id ""
        }

        if {![winfo exists $_top]} {
            set cmd [list DynamicHelp::_show_help $path $table $X $Y $row $col]
            set _id [after $_delay $cmd]
        }
    } else {
        variable _saved
        variable _current_variable

        set curr $_current_variable

        if {![string equal $_current_variable $path]} {
            _table_leave variable $table

            if {[info exists _registered($path,variable)]} {
                set varName [lindex $_registered($path,variable) 0]
                if {![info exists _saved]} {
                    set _saved [BWidget::getglobal $varName]
                }
                set string [lindex $_registered($path,variable) 1]
                if {[info exists _registered($path,command)]} {
                    set string [eval $_registered($path,command)]
                }
                BWidget::setglobal $varName $string
                set _current_variable $path
            }
        }
    }
}


proc DynamicHelp::_table_leave { type table } {
    switch -- $type {
        "balloon" {
            variable _id
            variable _top
            variable _current_balloon ""
            after cancel $_id
            _destroy_balloon $_top
        }

        "variable" {
            variable _saved
            variable _registered
            variable _current_variable
            set curr $_current_variable

            set _current_variable ""

            if {[info exists _registered($curr,variable)]} {
                set varName [lindex $_registered($curr,variable) 0]
                BWidget::setglobal $varName $_saved
            }
        }
    }
}


# ----------------------------------------------------------------------------
#  Command DynamicHelp::_motion_balloon
# ----------------------------------------------------------------------------
proc DynamicHelp::_motion_balloon { type path x y {class ""} {tag ""} } {
    variable _id
    variable _top
    variable _delay
    variable _current_balloon

    set event [Widget::getoption #DynamicHelp#$path -destroyballoon]

    set w $path
    if {[string equal $class "canvas"]} {
        set path [_get_canvas_path $path balloon]
    } elseif {[string equal $class "text"]} {
        set path $path,$tag
    }

    if {![string equal $_current_balloon $path]
        && [string equal $type "enter"]} {
        set _current_balloon $path
        set type "motion"
        _destroy_balloon $_top
    }

    if {[string equal $_current_balloon $path]} {
        if {[string length $_id]} {
            after cancel $_id
            set _id ""
        }

        if {[string equal $type "motion"]} {
            if {![winfo exists $_top]} {
                set cmd [list DynamicHelp::_show_help $path $w $x $y]
                set _id [after $_delay $cmd]
            } elseif {[string equal $event "motion"]} {
                ## The user has opted to destroy the balloon
                ## any time there is mouse motion.  We still
                ## keep the current_balloon set though so that
                ## if the mouse stops again within the same
                ## widget, we'll display the balloon again.
                _destroy_balloon $_top
            }
        } else {
            _destroy_balloon $_top
            set _current_balloon ""
        }
    }
}


# ----------------------------------------------------------------------------
#  Command DynamicHelp::_motion_info
# ----------------------------------------------------------------------------
proc DynamicHelp::_motion_info { path {class ""} {tag ""} } {
    variable _saved
    variable _registered
    variable _current_variable

    if {[string equal $class "canvas"]} {
        set path [_get_canvas_path $path balloon]
    } elseif {[string equal $class "text"]} {
        set path $path,$tag
    }

    if { $_current_variable != $path
        && [info exists _registered($path,variable)] } {

        set varName [lindex $_registered($path,variable) 0]
        if {![info exists _saved]} { set _saved [BWidget::getglobal $varName] }
        set string [lindex $_registered($path,variable) 1]
        if {[info exists _registered($path,command)]} {
            set string [eval $_registered($path,command)]
        }
        BWidget::setglobal $varName $string
        set _current_variable $path
    }
}


# ----------------------------------------------------------------------------
#  Command DynamicHelp::_leave_info
# ----------------------------------------------------------------------------
proc DynamicHelp::_leave_info { path {class ""} {tag ""} } {
    variable _saved
    variable _registered
    variable _current_variable

    if {[string equal $class "canvas"]} {
        set path [_get_canvas_path $path balloon]
    } elseif {[string equal $class "text"]} {
        set path $path,$tag
    }

    if { [info exists _registered($path,variable)] } {
        set varName [lindex $_registered($path,variable) 0]
        BWidget::setglobal $varName $_saved
    }
    unset _saved
    set _current_variable ""
}


# ----------------------------------------------------------------------------
#  Command DynamicHelp::_menu_info
#    Version of R1v1 restored, due to lack of [winfo ismapped] and <Unmap>
#    under windows for menu.
# ----------------------------------------------------------------------------
proc DynamicHelp::_menu_info { event path } {
    variable _registered

    if { [info exists _registered($path)] } {
        set index   [$path index active]
        set varName [lindex $_registered($path) 0]
        if { ![string equal $index "none"] &&
             [set idx [lsearch $_registered($path) [list $index *]]] != -1 } {
	    set string [lindex [lindex $_registered($path) $idx] 1]
	    if {[info exists _registered($path,$index,command)]} {
		set string [eval $_registered($path,$index,command)]
	    }
            BWidget::setglobal $varName $string
        } else {
            BWidget::setglobal $varName ""
        }
    }
}


# ----------------------------------------------------------------------------
#  Command DynamicHelp::_show_help
# ----------------------------------------------------------------------------
proc DynamicHelp::_show_help { path w x y {row -1} {col -1} } {
    variable _top
    variable _registered
    variable _id
    variable _delay

    if {[string equal [Widget::getoption $_top -state] "disabled"]} { return }

    if {[info exists _registered($path,balloon)]} {
        _destroy_balloon $_top 1

        set string $_registered($path,balloon)

	if {[info exists _registered($path,balloonVar)]} {
	    upvar #0 $_registered($path,balloonVar) var
	    if {[info exists var]} { set string $var }
	}

        if {[info exists _registered($path,command)]} {
            set map [list %W $w %X $x %Y $y %c $col %r $row %C $row,$col]
            set string [eval [string map $map $_registered($path,command)]]
        }

        if {![string length $string]} { return }

        toplevel $_top -relief flat \
            -bg [Widget::getoption $_top -topbackground] \
            -bd [Widget::getoption $_top -borderwidth] \
            -screen [winfo screen $w]

        wm withdraw $_top
        if {[BWidget::using aqua]} {
            ::tk::unsupported::MacWindowStyle style $_top help none
        } else {
            wm overrideredirect $_top 1
        }

	catch { wm attributes $_top -topmost 1 }

        label $_top.label -text $string \
            -relief flat -bd 0 -highlightthickness 0 \
	    -padx       [Widget::getoption $_top -padx] \
	    -pady       [Widget::getoption $_top -pady] \
            -foreground [Widget::getoption $_top -foreground] \
            -background [Widget::getoption $_top -background] \
            -font       [Widget::getoption $_top -font] \
            -justify    [Widget::getoption $_top -justify] \
            -wraplength 400


        pack $_top.label -side left
        update idletasks

	if {![winfo exists $_top]} { return }

        set  scrwidth  [winfo vrootwidth  .]
        set  scrheight [winfo vrootheight .]
        set  width     [winfo reqwidth  $_top]
        set  height    [winfo reqheight $_top]
        incr y 12
        incr x 8

        if { $x+$width > $scrwidth } {
            set x [expr {$scrwidth - $width}]
        }
        if { $y+$height > $scrheight } {
            set y [expr {$y - 12 - $height}]
        }

        wm geometry  $_top "+$x+$y"
        update idletasks

	if {![winfo exists $_top]} { return }
        wm deiconify $_top
        raise $_top
    }
}

# ----------------------------------------------------------------------------
#  Command DynamicHelp::_unset_help
# ----------------------------------------------------------------------------
proc DynamicHelp::_unset_help { path } {
    variable _widgets
    variable _registered

    if {[info exists _registered($path)]} { unset _registered($path) }
    if {[winfo exists $path]} {
	set cpath [BWidget::clonename $path]
	if {[info exists _registered($cpath)]} { unset _registered($cpath) }

        set tags [list BwHelpBalloon BwHelpVariable BwHelpMenu BwHelpDestroy]
        bindtags $path [eval [list BWidget::lremove [bindtags $path]] $tags]
    }

    array unset _widgets    $path,*
    array unset _registered $path,*

    Widget::destroy #DynamicHelp#$path
}

# ----------------------------------------------------------------------------
#  Command DynamicHelp::_get_canvas_path
# ----------------------------------------------------------------------------
proc DynamicHelp::_get_canvas_path { path type {item ""} } {
    variable _registered

    if {$item == ""} { set item [$path find withtag current] }

    ## Check the tags related to this item for the one that
    ## represents our text.  If we have text specific to this
    ## item or for 'all' items, they override any other tags.
    eval [list lappend tags $item all] [$path itemcget $item -tags]
    foreach tag $tags {
	set check $path,$tag
	if {![info exists _registered($check,$type)]} { continue }
	return $check
    }
}


proc DynamicHelp::_destroy_balloon { top {force 0} } {
    if {[winfo exists $top]} {
	if {!$force && [BWidget::using aqua]} {
	    BWidget::FadeWindowOut $top 1
	} else {
	    destroy $top
        }
    }
}
Added lib/BWidget/entry.tcl.




















































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
# ------------------------------------------------------------------------------
#  entry.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: entry.tcl,v 1.21 2004/04/21 22:26:30 hobbs Exp $
# ------------------------------------------------------------------------------
#  Index of commands:
#     - Entry::create
#     - Entry::configure
#     - Entry::cget
#     - Entry::_init_drag_cmd
#     - Entry::_end_drag_cmd
#     - Entry::_drop_cmd
#     - Entry::_over_cmd
#     - Entry::_auto_scroll
#     - Entry::_scroll
# ------------------------------------------------------------------------------

namespace eval Entry {
    Widget::define Entry entry DragSite DropSite DynamicHelp

    # Note:  -textvariable is pulled off of the tk entry and put onto the
    # BW Entry so that we avoid the TkResource test for it, which screws up
    # the existance/non-existance bits of the -textvariable.
    Widget::tkinclude Entry entry :cmd \
    	remove { -state -background -foreground -textvariable
    		 -disabledforeground -disabledbackground }

    set declare [list \
	    [list -background         Color       "SystemWindow"	   0] \
	    [list -foreground         Color       "SystemWindowText"	   0] \
	    [list -state              Enum  normal 0  [list normal disabled]] \
	    [list -text               String      ""	   0] \
	    [list -textvariable       String      ""     0] \
	    [list -editable           Boolean     1      0] \
	    [list -command            String      ""     0] \
	    [list -relief             TkResource  ""     0  entry] \
	    [list -borderwidth        TkResource  ""     0  entry] \
            [list -disabledbackground Color       "SystemButtonFace" 0] \
            [list -disabledforeground Color       "SystemDisabledText" 0] \
	    [list -fg                 Synonym     -foreground] \
	    [list -bg                 Synonym     -background] \
	    [list -bd                 Synonym     -borderwidth] \
	]

    Widget::declare Entry $declare
    Widget::addmap Entry "" :cmd { -textvariable {} }

    DynamicHelp::include Entry balloon
    DragSite::include    Entry "" 3
    DropSite::include    Entry {
        TEXT    {move {}}
        FGCOLOR {move {}}
        BGCOLOR {move {}}
        COLOR   {move {}}
    }

    BWidget::CopyBindings Entry BwEntry

    # Copy is kind of a special event.  It should be enabled when the
    # widget is editable but not disabled, and not when the widget is disabled.
    # To make this a bit easier to manage, we will handle it separately.

    bind BwEntry         <<Copy>> {}
    bind BwEditableEntry <<Copy>> [bind Entry <<Copy>>]

    bind BwEntry         <Return>  [list Entry::invoke %W]
    bind BwEntry         <Destroy> [list Widget::destroy %W]
    bind BwDisabledEntry <Destroy> [list Widget::destroy %W]
}


# ------------------------------------------------------------------------------
#  Command Entry::create
# ------------------------------------------------------------------------------
proc Entry::create { path args } {
    Widget::initArgs Entry $args maps

    eval [list entry $path] $maps(:cmd)
    Widget::initFromODB Entry $path $maps(Entry)

    Widget::getVariable $path data

    set data(afterid) ""
    set state    [Widget::getoption $path -state]
    set editable [Widget::getoption $path -editable]
    set text     [Widget::getoption $path -text]
    if {$editable && [string equal $state "normal"]} {
        bindtags $path [list $path BwEntry [winfo toplevel $path] all]
        $path configure -takefocus 1 -insertontime 600
    } else {
        bindtags $path [list $path BwDisabledEntry [winfo toplevel $path] all]
        $path configure -takefocus 0 -insertontime 0
    }

    if {!$editable} {
        $path configure -cursor left_ptr
    }

    if {[string equal $state "disabled"]} {
        $path configure \
            -foreground [Widget::getoption $path -disabledforeground] \
            -background [Widget::getoption $path -disabledbackground]
    } else {
	$path configure \
                -foreground [Widget::getoption $path -foreground] \
                -background [Widget::getoption $path -background]
	bindtags $path [linsert [bindtags $path] 2 BwEditableEntry]
    }

    if {[string length $text]} {
	set varName [$path cget -textvariable]
	if { ![string equal $varName ""] } {
	    uplevel \#0 [list set $varName [Widget::cget $path -text]]
	} else {
	    set validateState [$path cget -validate]
	    $path configure -validate none
	    $path delete 0 end
	    $path configure -validate $validateState
	    $path insert 0 [Widget::getoption $path -text]
	}
    }

    DragSite::setdrag $path $path Entry::_init_drag_cmd Entry::_end_drag_cmd 1
    DropSite::setdrop $path $path Entry::_over_cmd Entry::_drop_cmd 1
    DynamicHelp::sethelp $path $path 1

    Widget::create Entry $path
    proc ::$path { cmd args } \
    	"return \[Entry::_path_command [list $path] \$cmd \$args\]"
    return $path
}


# ------------------------------------------------------------------------------
#  Command Entry::configure
# ------------------------------------------------------------------------------
proc Entry::configure { path args } {
    # Cheat by setting the -text value to the current contents of the entry
    # This might be better hidden behind a function in ::Widget.
    set Widget::Entry::${path}:opt(-text) [$path:cmd get]

    set res [Widget::configure $path $args]

    # Extract the modified bits that we are interested in.
    set vars [list chstate cheditable chfg chdfg chbg chdbg chtext]
    set opts [list -state -editable -foreground -disabledforeground \
                -background -disabledbackground -text]
    foreach $vars [eval [linsert $opts 0 Widget::hasChangedX $path]] { break }

    if { $chstate || $cheditable } {
	set state [Widget::getoption $path -state]
	set editable [Widget::getoption $path -editable]
        set btags [bindtags $path]
        if { $editable && [string equal $state "normal"] } {
            set idx [lsearch -exact $btags BwDisabledEntry]
            if { $idx != -1 } {
                bindtags $path [lreplace $btags $idx $idx BwEntry]
            }
            $path:cmd configure -takefocus 1 -insertontime 600
        } else {
            set idx [lsearch -exact $btags BwEntry]
            if { $idx != -1 } {
                bindtags $path [lreplace $btags $idx $idx BwDisabledEntry]
            }
            $path:cmd configure -takefocus 0 -insertontime 0
            if { [string equal [focus] $path] } {
                focus .
            }
        }
    }

    if { $chstate || $chfg || $chdfg || $chbg || $chdbg } {
	set state [Widget::getoption $path -state]
        if { [string equal $state "disabled"] } {
            $path:cmd configure \
                -fg [Widget::cget $path -disabledforeground] \
                -bg [Widget::cget $path -disabledbackground]
        } else {
            $path:cmd configure \
                -fg [Widget::cget $path -foreground] \
                -bg [Widget::cget $path -background]
        }
    }
    if { $chstate } {
	if { [string equal $state "disabled"] } {
	    set idx [lsearch -exact [bindtags $path] BwEditableEntry]
	    if { $idx != -1 } {
		bindtags $path [lreplace [bindtags $path] $idx $idx]
	    }
	} else {
	    set idx [expr {[lsearch [bindtags $path] Bw*Entry] + 1}]
	    bindtags $path [linsert [bindtags $path] $idx BwEditableEntry]
	}
    }

    if { $cheditable } {
        if { $editable } {
            $path:cmd configure -cursor xterm
        } else {
            $path:cmd configure -cursor left_ptr
        }
    }

    if { $chtext } {
	# Oh my lordee-ba-goordee
	# Do some magic to prevent multiple validation command firings.
	# If there is a textvariable, set that to the right value; if not,
	# disable validation, delete the old text, enable, then set the text.
	set varName [$path:cmd cget -textvariable]
	if { ![string equal $varName ""] } {
	    uplevel \#0 [list set $varName \
		    [Widget::getoption $path -text]]
	} else {
	    set validateState [$path:cmd cget -validate]
	    $path:cmd configure -validate none
	    $path:cmd delete 0 end
	    $path:cmd configure -validate $validateState
	    $path:cmd insert 0 [Widget::getoption $path -text]
	}
    }

    DragSite::setdrag $path $path Entry::_init_drag_cmd Entry::_end_drag_cmd
    DropSite::setdrop $path $path Entry::_over_cmd Entry::_drop_cmd
    DynamicHelp::sethelp $path $path

    return $res
}


# ------------------------------------------------------------------------------
#  Command Entry::cget
# ------------------------------------------------------------------------------
proc Entry::cget { path option } {
    if { [string equal "-text" $option] } {
	return [$path:cmd get]
    }
    Widget::cget $path $option
}


# ------------------------------------------------------------------------------
#  Command Entry::invoke
# ------------------------------------------------------------------------------
proc Entry::invoke { path } {
    if {![string equal [set cmd [Widget::getoption $path -command]] ""]} {
        uplevel \#0 $cmd
    }
}


# ------------------------------------------------------------------------------
#  Command Entry::_path_command
# ------------------------------------------------------------------------------
proc Entry::_path_command { path cmd larg } {
    if {[string equal $cmd "configure"] || [string equal $cmd "cget"]} {
        return [eval [linsert $larg 0 Entry::$cmd $path]]
    } else {
        return [eval [linsert $larg 0 $path:cmd $cmd]]
    }
}


# ------------------------------------------------------------------------------
#  Command Entry::_init_drag_cmd
# ------------------------------------------------------------------------------
proc Entry::_init_drag_cmd { path X Y top } {
    Widget::getVariable $path data

    if {[llength [set cmd [Widget::getoption $path -draginitcmd]]]} {
        return [uplevel \#0 $cmd [list $path $X $Y $top]]
    }
    set type [Widget::getoption $path -dragtype]
    if { $type == "" } {
        set type "TEXT"
    }
    if { [set drag [$path get]] != "" } {
        if { [$path:cmd selection present] } {
            set idx  [$path:cmd index @[expr {$X-[winfo rootx $path]}]]
            set sel0 [$path:cmd index sel.first]
            set sel1 [expr {[$path:cmd index sel.last]-1}]
            if { $idx >=  $sel0 && $idx <= $sel1 } {
                set drag [string range $drag $sel0 $sel1]
                set data(dragstart) $sel0
                set data(dragend)   [expr {$sel1+1}]
                if { ![Widget::getoption $path -editable] ||
                     [Widget::getoption $path -state] == "disabled" } {
                    return [list $type {copy} $drag]
                } else {
                    return [list $type {copy move} $drag]
                }
            }
        } else {
            set data(dragstart) 0
            set data(dragend)   end
            if { ![Widget::getoption $path -editable] ||
                 [Widget::getoption $path -state] == "disabled" } {
                return [list $type {copy} $drag]
            } else {
                return [list $type {copy move} $drag]
            }
        }
    }
}


# ------------------------------------------------------------------------------
#  Command Entry::_end_drag_cmd
# ------------------------------------------------------------------------------
proc Entry::_end_drag_cmd { path target op type dnddata result } {
    Widget::getVariable $path data

    if {[llength [set cmd [Widget::getoption $path -dragendcmd]]]} {
        return [uplevel \#0 $cmd [list $path $target $op $type $dnddata $result]]
    }
    if { $result && $op == "move" && $path != $target } {
        $path:cmd delete $data(dragstart) $data(dragend)
    }
}


# ------------------------------------------------------------------------------
#  Command Entry::_drop_cmd
# ------------------------------------------------------------------------------
proc Entry::_drop_cmd { path source X Y op type dnddata } {
    Widget::getVariable $path data

    if { $data(afterid) != "" } {
        after cancel $data(afterid)
        set data(afterid) ""
    }
    if {[llength [set cmd [Widget::getoption $path -dropcmd]]]} {
        set idx [$path:cmd index @[expr {$X-[winfo rootx $path]}]]
        return [uplevel \#0 $cmd [list $path $source $idx $op $type $dnddata]]
    }
    if { $type == "COLOR" || $type == "FGCOLOR" } {
        configure $path -foreground $dnddata
    } elseif { $type == "BGCOLOR" } {
        configure $path -background $dnddata
    } else {
        $path:cmd icursor @[expr {$X-[winfo rootx $path]}]
        if { $op == "move" && $path == $source } {
            $path:cmd delete $data(dragstart) $data(dragend)
        }
        set sel0 [$path index insert]
        $path:cmd insert insert $dnddata
        set sel1 [$path index insert]
        $path:cmd selection range $sel0 $sel1
    }
    return 1
}


# ------------------------------------------------------------------------------
#  Command Entry::_over_cmd
# ------------------------------------------------------------------------------
proc Entry::_over_cmd { path source event X Y op type dnddata } {
    Widget::getVariable $path data

    set x [expr {$X-[winfo rootx $path]}]
    if { [string equal $event "leave"] } {
        if { [string length $data(afterid)] } {
            after cancel $data(afterid)
            set data(afterid) ""
        }
    } elseif { [_auto_scroll $path $x] } {
        return 2
    }

    if {[llength [set cmd [Widget::getoption $path -dropovercmd]]]} {
        set x   [expr {$X-[winfo rootx $path]}]
        set idx [$path:cmd index @$x]
        set res [uplevel \#0 $cmd [list $path $source $event $idx $op $type $dnddata]]
        return $res
    }

    if { [string equal $type "COLOR"]   ||
         [string equal $type "FGCOLOR"] ||
         [string equal $type "BGCOLOR"] } {
        DropSite::setcursor based_arrow_down
        return 1
    }
    if { [Widget::getoption $path -editable]
	&& [string equal [Widget::getoption $path -state] "normal"] } {
        if { ![string equal $event "leave"] } {
            $path:cmd selection clear
            $path:cmd icursor @$x
            DropSite::setcursor based_arrow_down
            return 3
        }
    }
    DropSite::setcursor dot
    return 0
}


# ------------------------------------------------------------------------------
#  Command Entry::_auto_scroll
# ------------------------------------------------------------------------------
proc Entry::_auto_scroll { path x } {
    Widget::getVariable $path data

    set xmax [winfo width $path]
    if { $x <= 10 && [$path:cmd index @0] > 0 } {
        if { $data(afterid) == "" } {
            set data(afterid) [after 100 [list Entry::_scroll $path -1 $x $xmax]]
            DropSite::setcursor sb_left_arrow
        }
        return 1
    } else {
        if { $x >= $xmax-10 && [$path:cmd index @$xmax] < [$path:cmd index end] } {
            if { $data(afterid) == "" } {
                set data(afterid) [after 100 [list Entry::_scroll $path 1 $x $xmax]]
                DropSite::setcursor sb_right_arrow
            }
            return 1
        } else {
            if { $data(afterid) != "" } {
                after cancel $data(afterid)
                set data(afterid) ""
            }
        }
    }
    return 0
}


# ------------------------------------------------------------------------------
#  Command Entry::_scroll
# ------------------------------------------------------------------------------
proc Entry::_scroll { path dir x xmax } {
    Widget::getVariable $path data

    $path:cmd xview scroll $dir units
    $path:cmd icursor @$x
    if { ($dir == -1 && [$path:cmd index @0] > 0) ||
         ($dir == 1  && [$path:cmd index @$xmax] < [$path:cmd index end]) } {
        set data(afterid) [after 100 [list Entry::_scroll $path $dir $x $xmax]]
    } else {
        set data(afterid) ""
        DropSite::setcursor dot
    }
}
Added lib/BWidget/font.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
# ----------------------------------------------------------------------------
#  font.tcl
#  This file is part of Unifix BWidget Toolkit
# ----------------------------------------------------------------------------
#  Index of commands:
#     - SelectFont::create
#     - SelectFont::configure
#     - SelectFont::cget
#     - SelectFont::_draw
#     - SelectFont::_destroy
#     - SelectFont::_update_style
#     - SelectFont::_update
#     - SelectFont::_getfont
#     - SelectFont::_init
# ----------------------------------------------------------------------------

namespace eval SelectFont {
    Widget::define SelectFont font Dialog LabelFrame ScrolledWindow

    Widget::declare SelectFont {
        {-title		String		"Select a Font" 0}
        {-parent	String		"" 0}
        {-background	Color           "SystemButtonFace" 0}

        {-type		Enum		dialog        0 {dialog toolbar}}
        {-font		String          "TkTextFont"  0}
	{-families	String		"all"         1}
	{-querysystem	Boolean		1             0}
	{-styles	String		"bold italic underline overstrike" 1}
        {-command	String		""            0}
        {-sampletext	String		"Sample Text" 0}
        {-bg		Synonym		-background}
        {-sizes         String          "6 8 9 10 11 12 14 16 18 20 22 24" 1}

        {-size          String          ""            1}
        {-family        String          ""            1}
    }

    if {[string equal $::tcl_platform(platform) "windows"]} {
        set sizes [list 8 9 10 11 12 14 16 18 20 22 24 26 28 36 48 72]
        Widget::declare SelectFont [list [list -sizes String $sizes 1]]
    }

    variable _families
    variable _styleOff
    array set _styleOff [list bold normal italic roman]
    
    # Set up preset lists of fonts, so the user can avoid the painfully slow
    # loadfont process if desired.
    if { [string equal $::tcl_platform(platform) "windows"] } {
	set presetVariable [list	\
		7x14			\
		Arial			\
		{Arial Narrow}		\
		{Lucida Sans}		\
		{MS Sans Serif}		\
		{MS Serif}		\
		{Times New Roman}	\
		]
	set presetFixed    [list	\
		6x13			\
		{Courier New}		\
		FixedSys		\
		Terminal		\
		]
	set presetAll      [list	\
		6x13			\
		7x14			\
		Arial			\
		{Arial Narrow}		\
		{Courier New}		\
		FixedSys		\
		{Lucida Sans}		\
		{MS Sans Serif}		\
		{MS Serif}		\
		Terminal		\
		{Times New Roman}	\
		]
    } else {
	set presetVariable [list	\
		helvetica		\
		lucida			\
		lucidabright		\
		{times new roman}	\
		]
	set presetFixed    [list	\
		courier			\
		fixed			\
		{lucida typewriter}	\
		screen			\
		serif			\
		terminal		\
		]
	set presetAll      [list	\
		courier			\
		fixed			\
		helvetica		\
		lucida			\
		lucidabright		\
		{lucida typewriter}	\
		screen			\
		serif			\
		terminal		\
		{times new roman}	\
		]
    }
    array set _families [list \
	    presetvariable	$presetVariable	\
	    presetfixed		$presetFixed	\
	    presetall		$presetAll	\
	    ]
		
    variable _widget
}


# ----------------------------------------------------------------------------
#  Command SelectFont::create
# ----------------------------------------------------------------------------
proc SelectFont::create { path args } {
    variable _sizes
    variable _styles
    variable _families

    set widg $path#SelectFont

    # Initialize the internal rep of the widget options
    Widget::init SelectFont $widg $args

    Widget::getVariable $widg data

    set _sizes [Widget::cget $widg -sizes]

    if {[Widget::getoption $widg -querysystem]} {
        loadfont [Widget::getoption $widg -families]
    }

    set _styles [Widget::getoption $widg -styles]

    return [eval [list SelectFont::[Widget::getoption $widg -type] $path] $args]
}


proc SelectFont::dialog { path args } {
    variable _sizes
    variable _styles
    variable _families

    set widg $path#SelectFont

    ## Initialize the internal rep of the widget options.
    Widget::init SelectFont $widg $args

    set bg   [Widget::getoption $widg -background]
    set font [Widget::getoption $widg -font]

    array set tmp [font actual $font]
    Widget::setoption $widg -size   $tmp(-size)
    Widget::setoption $widg -family $tmp(-family)

    Widget::getVariable $widg data

    Dialog::create $path -modal local -default 0 -cancel 1 \
        -background $bg -anchor e \
        -title  [Widget::getoption $widg -title] \
        -parent [Widget::getoption $widg -parent]

    ## Turn off the Return key closing the dialog.
    bind $path <Return> ""

    set frame [Dialog::getframe $path]
    set topf  [frame $frame.topf -relief flat -bd 0 -background $bg]

    set labf1 [LabelFrame::create $topf.labf1 -text "Font:" -name font \
               -side top -anchor w -relief flat -background $bg]

    set f [LabelFrame::getframe $labf1]

    Entry $f.fontEntry -textvariable [Widget::varForOption $widg -family] \
        -command [list SelectFont::_update $path]
    pack  $f.fontEntry -fill x

    set sw [ScrolledWindow::create $f.sw -bg $bg]
    pack $sw -fill both -expand yes

    set lbf [listbox $sw.lb -height 5 -width 25 \
        -exportselection 0 -selectmode browse \
        -listvariable [Widget::widgetVar $widg data(familyList)]]
    ScrolledWindow::setwidget $sw $lbf

    LabelFrame::configure $labf1 -focus $f.fontEntry

    if {[Widget::getoption $widg -querysystem]} {
        set fam [Widget::getoption $widg -families]
    } else {
        set fam "preset"
        append fam [Widget::getoption $widg -families]
    }
    eval [list $lbf insert end] $_families($fam)

    set script [list SelectFont::_update_family $path %W]

    bind $lbf <1>               [list focus %W]
    bind $lbf <ButtonRelease-1> $script
    bind $lbf <space>           $script
    bind $lbf <Up>              $script
    bind $lbf <Down>            $script
    bind $lbf <KeyRelease-Up>   $script
    bind $lbf <KeyRelease-Down> $script

    set labf2 [LabelFrame::create $topf.labf2 -text "Size:" -name size \
                   -side top -anchor w -relief flat -background $bg]

    set f [LabelFrame::getframe $labf2]

    Entry $f.sizeEntry -textvariable [Widget::varForOption $widg -size] \
        -command [list SelectFont::_update $path]
    pack  $f.sizeEntry -fill x

    set sw [ScrolledWindow::create $f.sw -scrollbar vertical -background $bg]
    pack $sw -fill both -expand yes

    set lbs [listbox $sw.lb -height 5 -width 6 \
        -exportselection 0 -selectmode browse \
        -listvariable [Widget::widgetVar $widg data(sizeList)]]
    ScrolledWindow::setwidget $sw $lbs

    LabelFrame::configure $labf2 -focus $f.sizeEntry

    eval [list $lbs insert end] $_sizes

    set script [list SelectFont::_update_size $path %W]

    bind $lbs <1>               [list focus %W]
    bind $lbs <ButtonRelease-1> $script
    bind $lbs <space>           $script
    bind $lbs <Up>              $script
    bind $lbs <Down>            $script
    bind $lbs <KeyRelease-Up>   $script
    bind $lbs <KeyRelease-Down> $script

    set labf3 [LabelFrame::create $topf.labf3 -text "Font Style:" -name style \
                   -side top -anchor w -relief sunken -bd 1 -background $bg]
    set subf  [LabelFrame::getframe $labf3]

    foreach st $_styles {
        set name [lindex [BWidget::getname $st] 0]
        if {![string length $name]} { set name [string toupper $name 0] }

        if {[BWidget::using ttk]} {
            ttk::checkbutton $subf.$st -text $name \
                -command  [list SelectFont::_update $path] \
                -variable [Widget::widgetVar $widg data($st)]
        } else {
            $checkbutton $subf.$st -text $name -background $bg \
                -command  [list SelectFont::_update $path] \
                -variable [Widget::widgetVar $widg data($st)]
        }
        bind $subf.$st <Return> break
        pack $subf.$st -anchor w -padx [list 0 5]
    }
    LabelFrame::configure $labf3 -focus $subf.[lindex $_styles 0]

    pack $labf1 -side left -anchor n -fill both -expand yes
    pack $labf2 -side left -anchor n -fill both -expand yes -padx 8
    pack $labf3 -side left -anchor n -fill both -expand yes

    text $frame.sample -bg #FFFFFF -width 0 -height 3 \
        -font "Courier 10" -wrap none
    $frame.sample tag configure text -justify center -font $font
    $frame.sample insert end [Widget::cget $widg -sampletext] text
    $frame.sample configure -state disabled

    pack $topf -pady 4 -fill both -expand 1
    pack $frame.sample -pady 4 -fill x

    Dialog::add $path -name ok -width 12
    Dialog::add $path -name cancel -width 12

    set data(lbf)  $lbf
    set data(lbs)  $lbs
    set data(text) $frame.sample

    _getfont $path

    Widget::create SelectFont $path 0

    return [_draw $path]
}


proc SelectFont::toolbar { path args } {
    variable _sizes
    variable _styles
    variable _families

    set widg $path#SelectFont

    ## Initialize the internal rep of the widget options.
    Widget::init SelectFont $widg $args

    array set tmp [font actual [Widget::getoption $widg -font]]
    Widget::setoption $widg -size   $tmp(-size)
    Widget::setoption $widg -family $tmp(-family)

    set bg [Widget::getoption $widg -background]

    if {[Widget::getoption $widg -querysystem]} {
        set fams [Widget::getoption $widg -families]
    } else {
        set fams "preset"
        append fams [Widget::getoption $widg -families]
    }

    if {[BWidget::using ttk]} {
        ttk::frame $path
        set lbf [ttk::combobox $path.font \
                -takefocus 0 -exportselection 0 \
                -values $_families($fams) -state readonly \
                -textvariable [Widget::varForOption $widg -family]]
        set lbs [ttk::combobox $path.size \
                -takefocus 0 -exportselection 0 \
                -width 4 -values $_sizes -state readonly \
                -textvariable [Widget::varForOption $widg -size]]
        bind $lbf <<ComboboxSelected>> [list SelectFont::_update $path]
        bind $lbs <<ComboboxSelected>> [list SelectFont::_update $path]
    } else {
        frame $path -background $bg
        set lbf [ComboBox::create $path.font \
                     -highlightthickness 0 -takefocus 0 -background $bg \
                     -values   $_families($fams) \
                     -textvariable [Widget::varForOption $widg -family] \
                     -editable 0 \
                     -modifycmd [list SelectFont::_update $path]]
        set lbs [ComboBox::create $path.size \
                     -highlightthickness 0 -takefocus 0 -background $bg \
                     -width    4 \
                     -values   $_sizes \
                     -textvariable [Widget::varForOption $widg -size] \
                     -editable 0 \
                     -modifycmd [list SelectFont::_update $path]]
    }

    bind $path <Destroy> [list SelectFont::_destroy $path]
    pack $lbf -side left -anchor w
    pack $lbs -side left -anchor w -padx 4

    foreach st $_styles {
        if {[BWidget::using ttk]} {
            ttk::checkbutton $path.$st -takefocus 0 \
                -style BWSlim.Toolbutton \
                -image [Bitmap::get $st] \
                -variable [Widget::widgetVar $widg data($st)] \
                -command [list SelectFont::_update $path]
        } else {
            button $path.$st \
                -highlightthickness 0 -takefocus 0 -padx 0 -pady 0 -bd 2 \
                -background $bg -image  [Bitmap::get $st] \
                -command [list SelectFont::_update_style $path $st]
        }
        pack $path.$st -side left -anchor w
    }
    set data(lbf) $lbf
    set data(lbs) $lbs
    _getfont $path

    return [Widget::create SelectFont $path]
}


# ----------------------------------------------------------------------------
#  Command SelectFont::configure
# ----------------------------------------------------------------------------
proc SelectFont::configure { path args } {
    set widg $path#SelectFont

    set _styles [Widget::getoption $widg -styles]

    set res [Widget::configure $widg $args]

    if { [Widget::hasChanged $widg -font font] } {
        _getfont $path
    }

    if { [Widget::hasChanged $widg -background bg] } {
        switch -- [Widget::getoption $widg -type] {
            "dialog" {
                Dialog::configure $path -background $bg
                set topf [Dialog::getframe $path].topf
                $topf configure -background $bg
                foreach labf {labf1 labf2} {
                    LabelFrame::configure $topf.$labf -background $bg
                    set subf [LabelFrame::getframe $topf.$labf]
                    ScrolledWindow::configure $subf.sw -background $bg
                    $subf.sw.lb configure -background $bg
                }
                LabelFrame::configure $topf.labf3 -background $bg
                set subf [LabelFrame::getframe $topf.labf3]
                foreach w [winfo children $subf] {
                    $w configure -background $bg
                }
            }

            "toolbar" {
                $path configure -background $bg
                ComboBox::configure $path.font -background $bg
                ComboBox::configure $path.size -background $bg
                foreach st $_styles {
                    $path.$st configure -background $bg
                }
            }
        }
    }
    return $res
}


# ----------------------------------------------------------------------------
#  Command SelectFont::cget
# ----------------------------------------------------------------------------
proc SelectFont::cget { path option } {
    return [Widget::cget "$path#SelectFont" $option]
}


# ----------------------------------------------------------------------------
#  Command SelectFont::loadfont
# ----------------------------------------------------------------------------
proc SelectFont::loadfont {{which all}} {
    variable _families

    # initialize families
    if {![info exists _families(all)]} {
	set _families(all) [lsort -dictionary [font families]]
    }

    if {[regexp {fixed|variable} $which] && ![info exists _families($which)]} {
	# initialize families
	set _families(fixed) {}
	set _families(variable) {}
	foreach family $_families(all) {
	    if { [font metrics [list $family] -fixed] } {
		lappend _families(fixed) $family
	    } else {
		lappend _families(variable) $family
	    }
	}
    }
    return
}


proc SelectFont::_update_family { path listbox } {
    set sel [$listbox curselection]
    Widget::setoption $path#SelectFont -family [$listbox get $sel]

    _update $path
}


proc SelectFont::_update_size { path listbox } {
    set sel [$listbox curselection]
    Widget::setoption $path#SelectFont -size [$listbox get $sel]

    _update $path
}


# ----------------------------------------------------------------------------
#  Command SelectFont::_update_style
# ----------------------------------------------------------------------------
proc SelectFont::_update_style { path style } {
    Widget::getVariable $path#SelectFont data

    if { $data($style) == 1 } {
        $path.$style configure -relief raised
        set data($style) 0
    } else {
        $path.$style configure -relief sunken
        set data($style) 1
    }

    _update $path
}


# ----------------------------------------------------------------------------
#  Command SelectFont::_update
# ----------------------------------------------------------------------------
proc SelectFont::_update { path } {
    variable _families
    variable _sizes
    variable _styleOff

    set widg $path#SelectFont

    Widget::getVariable $widg data

    set type    [Widget::getoption $widg -type]
    set size    [Widget::getoption $widg -size]
    set family  [Widget::getoption $widg -family]
    set _styles [Widget::getoption $widg -styles]

    set font    [list $family $size]

    if {[Widget::getoption $widg -querysystem]} {
	set fams [Widget::getoption $widg -families]
    } else {
	set fams "preset"
	append fams [Widget::getoption $widg -families]
    }

    if {[string equal $type "dialog"]} {
        set curs [$path:cmd cget -cursor]
        $path:cmd configure -cursor watch
    }

    foreach st $_styles {
        if {$data($st)} { lappend font $st }
    }
    Widget::setoption $widg -font $font

    if {[string equal $type "dialog"]} {
        $data(text) tag configure text -font $font
        $path:cmd configure -cursor $curs
    }

    set cmd [Widget::getoption $widg -command]
    if {![string equal $cmd ""]} { uplevel \#0 $cmd }
}


# ----------------------------------------------------------------------------
#  Command SelectFont::_draw
# ----------------------------------------------------------------------------
proc SelectFont::_draw { path } {
    set widg $path#SelectFont

    Widget::getVariable $widg data

    set idx [lsearch -exact $data(familyList) [Widget::getoption $widg -family]]
    $data(lbf) selection clear 0 end
    $data(lbf) selection set $idx
    $data(lbf) activate $idx
    $data(lbf) see $idx

    set idx [lsearch -exact $data(sizeList) [Widget::getoption $widg -size]]
    $data(lbs) selection clear 0 end
    $data(lbs) selection set $idx
    $data(lbs) activate $idx
    $data(lbs) see $idx

    _update $path

    if {![Dialog::draw $path]} {
        set result [Widget::getoption $widg -font]
    } else {
        set result ""
    }

    Widget::destroy $widg
    destroy $path

    return $result
}


# ----------------------------------------------------------------------------
#  Command SelectFont::_getfont
# ----------------------------------------------------------------------------
proc SelectFont::_getfont { path } {
    variable _sizes
    variable _families

    set widg $path#SelectFont

    Widget::getVariable $widg data

    array set font [font actual [Widget::getoption $widg -font]]
    set data(bold)       [expr {![string equal $font(-weight) "normal"]}]
    set data(italic)     [expr {![string equal $font(-slant)  "roman"]}]
    set data(underline)  $font(-underline)
    set data(overstrike) $font(-overstrike)
    set _styles [Widget::getoption $widg -styles]
    if {[Widget::getoption $widg -querysystem]} {
	set fams [Widget::getoption $widg -families]
    } else {
	set fams "preset"
	append fams [Widget::getoption $widg -families]
    }

    Widget::setoption $widg -size   $font(-size)
    Widget::setoption $widg -family $font(-family)

    if {[string equal [Widget::getoption $widg -type] "toolbar"]
        && ![BWidget::using ttk]} {
        foreach st $_styles {
            $path.$st configure -relief [expr {$data($st) ? "sunken":"raised"}]
        }
    }
}
Added lib/BWidget/icons.tcl.




































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
# ------------------------------------------------------------------------------
#  icons.tcl
#  $Id$
# ------------------------------------------------------------------------------
#  Index of commands:
#     - IconLibrary::delete
#     - IconLibrary::image
#     - IconLibrary::load
# ------------------------------------------------------------------------------

if {0} {
    ## Example of how to load a KDE theme as an icon library.
    ## Replace $kdedir with the directory where the KDE theme is.

    ## Create the icon library.
    IconLibrary icons

    icons load -find 1 -directory $kdedir -extension png -findgroups \
            [list {actions act} {apps app} {devices dev}
                {filesystems file} {mimetypes mime}]
}


package require Tcl 8.4

namespace eval IconLibrary {
    Widget::define IconLibrary icons

    Widget::declare IconLibrary {
        {-file          String    "tkIcons"                 0}
        {-icons         String    ""                        0}
        {-sizes         String    ""                        0}
        {-groups        String    ""                        0}
        {-create        Boolean   0                         0}
        {-directory     String    ""                        0}

        {-find          Boolean   0                         0}
        {-extension     String    "gif"                     0}
        {-findsizes     String    "16 22"                   0}
        {-findgroups    String    "act app dev file mime"   0}
    }

    namespace eval Icon {
        Widget::declare IconLibrary::Icon {
            {-size      String    ""                        1}
            {-type      String    ""                        1}
            {-file      String    ""                        1}
            {-data      String    ""                        1}
            {-image     String    ""                        1}
            {-imageargs String    ""                        1}
            {-filegroup String    ""                        1}
            {-workgroup String    ""                        1}
        }
    }

    namespace eval NamesArgs {
        Widget::declare IconLibrary::NamesArgs {
            {-icons         String    ""                        0}
            {-sizes         String    ""                        0}
            {-groups        String    ""                        0}
        }
    }

    ## Setup a quick look-up array of common icon sizes.
    variable  sizeMap
    array set sizeMap {
        16x16   16
        22x22   22
        32x32   32
        48x48   48
        64x64   64
        128x128 128
    }

    variable  groupMapArray
    array set groupMapArray {
        apps            app
        actions         act
        devices         dev
        mimetypes       mime
        filesystems     file
    }

    variable groupMap 

    foreach name [array names groupMapArray] {
        lappend groupMap [list $name $groupMapArray($name)]
    }
}


proc IconLibrary::create { library args } {
    Widget::init IconLibrary $library $args

    Widget::getVariable $library data

    set data(icons) [list]

    if {[llength $args]} { eval [list IconLibrary::load $library] $args }

    return [Widget::create IconLibrary $library 0]
}


proc IconLibrary::load { library args } {
    Widget::getVariable $library data

    Widget::init IconLibrary $library $args

    set file      [Widget::getoption $library -file]
    set create    [Widget::getoption $library -create]
    set iconlist  [Widget::getoption $library -icons]
    set sizelist  [Widget::getoption $library -sizes]
    set grouplist [Widget::getoption $library -groups]
    set directory [Widget::getoption $library -directory]

    set filename $file
    if {![string length $directory]} {
        set directory [file dirname $file]
    } elseif {[string length $file]} {
        set filename [file join $directory $file]
    }

    if {[Widget::getoption $library -find]} {
        if {![string length $directory]} {
            return -code error "cannot find images without -directory"
        }

        set ext        [Widget::getoption $library -extension]
        set findsizes  [Widget::getoption $library -findsizes]
        set findgroups [Widget::getoption $library -findgroups]

        foreach size $findsizes {
            set size  [IconLibrary::_get_size $size]

            set sizedir [file join $directory $size]
            if {![file exists $sizedir]} { continue }

            foreach group $findgroups {
                set filegroup [lindex $group 0]
                set workgroup [lindex $group 1]
                if {[llength $group] == 1} { set workgroup $filegroup }

                set groupdir [file join $sizedir $filegroup]
                if {![file exists $groupdir]} { continue }

                foreach imagefile [glob -nocomplain -dir $groupdir *.$ext] {
                    set image [file root [file tail $imagefile]]
                    set image $workgroup$image$size
                    lappend data(icons) $image

                    set icon $library#$image
                    set exists [expr {[Widget::exists $icon]
                        && [string length [Widget::getoption $icon -image]]}]

                    Widget::init IconLibrary::Icon $icon \
                        [list -size $size -type file -file $imagefile \
                        -filegroup $filegroup -workgroup $workgroup \
                        -data "" -image ""]

                    ## If we already had this icon, and the image had
                    ## already been created, we want to re-create it.
                    if {$exists && !$create} {
                        IconLibrary::image $library $image
                    }
                }
            }
        }

        if {![file exists $filename]} {
            if {$create} { _create_icons $library $data(icons) }
            set data(icons) [lsort -unique $data(icons)]
            return $data(icons)
        }
    }

    if {![file isfile $filename] || ![file readable $filename]} {
        return -code error "couldn't open \"$filename\": no such file"
    }

    set iLen [llength $iconlist]
    set sLen [llength $sizelist]
    set gLen [llength $grouplist]

    set fp [open $filename]

    while {[gets $fp line] != -1} {
        if {[string equal [string index $line 0] "#"]} { continue }

        set list [split $line :]
        if {[llength $list] < 5} { continue }

        BWidget::lassign $list image workgroup filegroup size type imagedata
        set size [IconLibrary::_get_size_int $size]

        if {($gLen && [lsearch -exact $grouplist $workgroup] < 0)
            || ($sLen && [lsearch -exact $sizelist $size] < 0)
            || ($iLen && [lsearch -exact $iconlist $image] < 0)} { continue }

        set file ""
        if {[string equal $type "file"]} {
            if {![string length $imagedata]} { continue }

            if {[string is integer $size]} { set size ${size}x${size} }
            set file [file join $directory $size $filegroup $imagedata]
            set images($image,file) $file
        }

        lappend data(icons) $image

        set icon $library#$image
        set exists [expr {[Widget::exists $icon]
            && [string length [Widget::getoption $icon -image]]}]

        Widget::init IconLibrary::Icon $icon \
            [list -size $size -type $type -file $file -data $imagedata \
            -filegroup $filegroup -workgroup $workgroup -image ""]

        ## If we already had this icon, and the image had
        ## already been created, we want to re-create it.
        if {$exists && !$create} {
            IconLibrary::image $library $image
        }
    }

    close $fp

    if {$create} { _create_icons $library $icons }

    set data(icons) [lsort -unique $data(icons)]
}


proc IconLibrary::cget { library option } {
    return [Widget::cget $library $option]
}


proc IconLibrary::configure { library args } {
    return [Widget::configure $library $args]
}


proc IconLibrary::itemcget { library image option } {
    if {![IconLibrary::exists $library $image]} {
        return -code error "no such icon '$image'"
    }

    set path    $library#$image
    set image   [Widget::getoption $path -image]
    set created [string length $image]
    if {$created && ($option eq "-file" || $option eq "-data")} {
        return [$image cget $option]
    }
    return [Widget::cget $path $option]
}


proc IconLibrary::itemconfigure { library image args } {
    if {![IconLibrary::exists $library $image]} {
        return -code error "no such icon '$image'"
    }

    set path    $library#$image
    set image   [Widget::getoption $path -image]
    set created [string length $image]

    if {![llength $args]} {
        set return [list]
        foreach list [Widget::configure $path $args] {
            set option [lindex $list 0]
            if {$created && ($option eq "-file" || $option eq "-data")} {
                lappend return [$image configure $option]
            } else {
                lappend return $list
            }
        }
        return $return
    } elseif {[llength $args] == 1} {
        set option [lindex $args 0]
        if {$created && ($option eq "-file" || $option eq "-data")} {
            return [$image configure $option]
        } else {
            return [Widget::configure $path $option]
        }
    }

    set imageOpts  [list]
    set widgetOpts [list]
    foreach [list option value] $args {
        if {$created && ($option eq "-file" || $option eq "-data")} {
            lappend imageOpts $option $value
        } else {
            lappend widgetOpts $option $value
        }
    }

    if {[llength $imageOpts]} {
        eval [list $image configure] $imageOpts
    }

    if {[llength $widgetOpts]} {
        Widget::configure $path $widgetOpts
    }
}


proc IconLibrary::exists { library image } {
    return [Widget::exists $library#$image]
}


proc IconLibrary::icons { library {pattern ""} } {
    Widget::getVariable $library data
    if {![string length $pattern]} { return $data(icons) }
    return [lsearch -glob -all -inline $data(icons) $pattern]
}


proc IconLibrary::add { library image args } {
    Widget::getVariable $library data

    if {[IconLibrary::exists $library $image]} {
        return -code error "icon \"$image\" already exists"
    }

    array set _args $args

    set create 0
    if {[info exists _args(-create)]} {
        if {$_args(-create)} { set create 1 }
        unset _args(-create)
    }

    Widget::init IconLibrary::Icon $library#$image [array get _args]
    lappend data(icons) $image

    if {$create} { IconLibrary::image $library $image }

    return $image
}


proc IconLibrary::image { library image } {
    Widget::getVariable $library images

    if {![IconLibrary::exists $library $image]} {
        return -code error "no such icon '$image'"
    }

    set path $library#$image

    ## If an icon is type 'icon', it's a link to another
    ## icon in the library.
    if {[string equal [Widget::getoption $path -type] "icon"]} {
        set icon  $image
        set image [Widget::getoption $path -data]
        set path  $library#$image
        if {![IconLibrary::exists $library $image]} {
            return -code error "no such icon '$image' while loading '$icon'"
        }
    }

    if {![string length [Widget::getoption $path -image]]} {
        set img ::Icons::${library}::$image

        set data [Widget::getoption $path -data]
        set file [Widget::getoption $path -file]
        set args [Widget::getoption $path -imageargs]

        if {[string length $data]} {
            lappend args -data $data
        } elseif {[string length $file]} {
            lappend args -file $file
        }

        eval [list ::image create photo $img] $args

        Widget::setoption $path -image $img -file "" -data ""
    }

    return [Widget::getoption $path -image]
}


proc IconLibrary::delete { library args } {
    Widget::getVariable $library data

    set images [list]
    foreach icon $args {
        set image [Widget::getoption $library#$icon -image]
        if {[string length $image]} { lappend images $image }
        Widget::destroy $library#$icon 0
    }

    if {[llength $images]} { eval ::image delete $images }

    set data(icons) [eval [list BWidget::lremove $data(icons)] $args]

    return
}


proc IconLibrary::clear { library } {
    Widget::getVariable $library data
    eval [list IconLibrary::delete $library] $data(icons)
}


proc IconLibrary::destroy { library } {
    IconLibrary::clear $library
    Widget::destroy $library
}


proc IconLibrary::_get_size { size } {
    if {[string is integer -strict $size]} { return ${size}x${size} }
    return $size
}


proc IconLibrary::_get_size_int { size } {
    variable sizeMap
    if {[info exists sizeMap($size)]} { return $sizeMap($size) }
    if {[scan $size "%dx%d" w h] == 2 && $w == $h} { return $w }
    return $size
}


proc IconLibrary::_create_icons { library icons } {
    foreach icon $icons {
        IconLibrary::image $library $icon
    }
}
Added lib/BWidget/images/BWidget.gif.tkico.








































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
## Plus and minus images for trees.
tree-plus:tree:tree:9:data:R0lGODlhCQAJAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A/wD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBmAABmMwBmZgBmmQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMzmTMzzDMz/zNmADNmMzNmZjNmmTNmzDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPMADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZmzGZm/2aZAGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lmAJlmM5lmZplmmZlmzJlm/5mZAJmZM5mZZpmZmZmZzJmZ/5nMAJnMM5nMZpnMmZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswAmcwAzMwA/8wzAMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZZsyZmcyZzMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9mmf9mzP9m//+ZAP+ZM/+ZZv+Zmf+ZzP+Z///MAP/MM//MZv/Mmf/MzP/M////AP//M///Zv//mf//zP///ywAAAAACQAJAAAINgARGBpI0JDABwgTPhiYEEBChggdPqDGEIBFixQNIfQHwB+1jB+pAQg5kBoCBNNSChRYcCCCgAA7
tree-minus:tree:tree:9:data:R0lGODlhCQAJAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A/wD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBmAABmMwBmZgBmmQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMzmTMzzDMz/zNmADNmMzNmZjNmmTNmzDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPMADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZmzGZm/2aZAGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lmAJlmM5lmZplmmZlmzJlm/5mZAJmZM5mZZpmZmZmZzJmZ/5nMAJnMM5nMZpnMmZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswAmcwAzMwA/8wzAMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZZsyZmcyZzMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9mmf9mzP9m//+ZAP+ZM/+ZZv+Zmf+ZzP+Z///MAP/MM//MZv/Mmf/MzP/M////AP//M///Zv//mf//zP///yH5BAEAABAALAAAAAAJAAkAAAhHAGGlMmQoVaFChmAZ+sew4T9VqRwyzEfw3zaL+fxVQ+gPhUeP/lSp8rct4zZt1DhSo4YP5bSC1KZNczZzWiGFqgwBGphKVUAAOw==

## Checkbox and radiobutton images for option trees.
check-off:tree:optiontree:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CJYyPacDtfZ5kEaiKb6DLar55FwgqpGiKZXJqYTaq01PNkIvnRwEAOw==
check-on:tree:optiontree:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CK4yPacDtfZ5kEaiKlaXLJsoFYLV5Ynl6IehkZ2e+XfSZoWZPD6nf1w9UFAAAOw==
radio-off:tree:optiontree:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CI4yPqcsGD1qANCqIcHrXHr6AjreRYpmRKcqm5vlVcDlLtl0AADs=
radio-on:tree:optiontree:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CJoyPqcsGD1qANCqIcHrXHu54YBiC42RR5Ce2m8d2sPZWsHxL+l4AADs=

actback16:act:actions:16:data:R0lGODlhEAAQAPcAAAAAAAJqiABtiwJyjQV2kwd6lQx4lg16lQyAmhR0jRN7kxN/mxp/lSZ/lw+CnBWEnR2Lnw6PphiGohWKoxuOph6WrSCarieBmSmCmS2KoDiEmjqFmyKWqyObriqcrSaesjeMoT2QpDaVpj6UpS6ruzeuwDa9yzy1xUOGm0GKoFCOokWSp0ibrk+XrEmbq1KVqFmTpV2crWWesGijr2Wstmyst2+2vmy5wHqjtHC/xUjC0E/N2UnV3VXW31rq7mLm64amtJKst5Otupmwu560wJe/xpu1wq68xbPAyJ3EyqTFyqnKz67M0bLN0sXL0MjN0czP08HV2NTX2tfa3Nvc3t/g4djl5+Dh4uHi4+zs7fDw8fPz9Pf6+v7+/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABLzmAAAAJEFyBQgmBL0ZJEFURQTeJEFbQAAAJEEPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKAAAAAAAAAAAAAAAAAAAAAAAAJEzzgCtJhLxtBQAABL1iJDuGJFAwP///5FAuwHWjgAARRLzqBAAgBL1iJDuGJEFcP///wAAAJEEPRL03IELdQAAAP///wAAAwAAgAAAGAAAABL0xAAAQgAAABL0qAAAAAAAAAAAAAAADAAAApABAf38AAAA1AAAAAAAARoA3BQgoAAAABQgoAAAAYDi3xL1AIAaTwAHoJDiNIEQ2wAHoBL1CBL1EAAACAAABP///////wAAAwAHoBL1TML0nwAAAwAHoEPjSgAAAQAAAAAADAAAAAAAAQAAAAAAAwAAAwAAABL1mMLlVokfmBL1mML2EwAAA8L2BEPjSgAAAQAAAAAAAwAAAwAAARL1aKH6YBL1+MNclMElGP///8L2BMQwSaHvMACAAAAAQAABpIkrOEPjSMOlLqH6YBL1zMO5ZwAAExL2CMPwCcX84MPwAIkrOEPjSAAAAMX84CH+JENyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWMgUHJvY2Vzc29yAAAh+QQJAQAAACwAAAAAEAAQAAcIwwABCBxIsKBBITJatIgxxOBAFh4+fLBAgcIKhyJI6NBBooOHCg4wFBxBYscPHjZqdOBQoUCIgUE4nOjhI0eXJBEqTJBwIIjAGBVKmLixpcsSES4yPCAAQ+AKCx9oFO3SpagSAgQ2CBxRgYKSLlyoUm0ygIAGgS8mdIDQhKqVJExmEBigQiAQBBUftC1SloABAUAGgnAAYcKBKFcXHAjQgCARBgYeIFDA4ICBAAmIFDSCAevcAIw1O8SRosEFFDgcqjYYEAA7
actcolorize16:act:actions:16:data:R0lGODlhEgASAPcAAAAAAB9zLydULiF6NAtCXwBYXQB4fUxLQ09PT1NSSllURVNTU1tbWWRfTmNfVmFgYWZhUGdiUWdlXm5qWnBtZHJvZXZ1b3Z2dn59eHp6egBOhQBalSJlhiKApzCbRDabRkCfTWKEdWqgs3StoHa7gXO3qnm4p0i05lS66FDBwIDPgUrCwWDE8YwAC5lCSYZ/aIl/Z4KAfJN7bM0OJ8QhNNhDT/BFUOZoaed3eYWEfY2QeZaNdJuQdoqvfIyMjJSTj6CbgZaVlZmZmYq7hp+1mqajjKOuh6KtmLCrnae6n7GtmqWlpaysrKS2r7Svoba2tr+9t76+vqzBu4PZ1YfZ2rbLx6zm+8alkci4lc26lc28ncK5p+y3q9TDntDDocfFvtDMs9fMsNrJodrOq93Ur9PUvOPUrufYseXXveLcuOfcu+nbterZu8bGxM3NzeDaxNPT09vZ093d3dX31+fcxuLfyf/W1eXmyOTizevlzufm0url1PDq0+/x3fbt0vTu2/Lx3u7u7vP45Pr14//87vf39///9vz8+wAAAAAAAAAAAAAAAAAAAJEzzgCtJhLxtBQAABL1iJDuGJFAwP///5FAuwHWjgAARRLzqBAAgBL1iJDuGJEFcP///wAAAJEEPRL03IELdQAAAP///wAAAwAAgAAAGAAAABL0xAAAQgAAABL0qAAAAAAAAAAAAAAADAAAApABAf38AAAA1AAAAAAAARoA3BQgoAAAABQgoAAAAYDi3xL1AIAaTwAHoJDiNIEQ2wAHoBL1CBL1EAAACAAABP///////wAAAwAHoBL1TML0nwAAAwAHoEPjSgAAAQAAAAAADAAAAAAAAQAAAAAAAwAAAwAAABL1mMLlVokfmBL1mML2EwAAA8L2BEPjSgAAAQAAAAAAAwAAAwAAARL1aKH6YBL1+MNclMElGP///8L2BMQwSaHvMACAAAAAQAABpIkrOEPjSMOlLqH6YBL1zMO5ZwAAExL2CMPwCcX84MPwAIkrOEPjSAAAAMX84CH+JENyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWMgUHJvY2Vzc29yAAAh+QQJAQAAACwAAAAAEgASAAcI6AABCBxIsKDBIDkMKhQYx5AhDAVjTKBQ8AchJE4OMRiIwY8aNREG+jCk5EKGNl8GbpHSxMyZjQAsELIg0IFGADGqWEHRwcwCgRUGUQRwgdAgCX9EsDixQQwEoH/4PLgA5c8ePHTYcNBAoEsDgRT45AEkqI+eOm/QsDGRJIsZBQIv5KnD5UYNrHTQlKCygogZBAOL3MFhh0aZIR56jJiSIgSPDAMl3JlhowUYEnNAHDFQQMeBgkWuuJAR5oOKAFq6YIFxwSCQNGTGGBkgQAuZF60VJtgxZo0ZLzsO5F4IYIFxBJCJK1/OPCAAOw==
actup16:act:actions:16:data:R0lGODlhEAAQAPcAAAAAAANpiABtigJzjgp1jwJ0kQd7lgt4lA17lQ+AmxR0jRZ8lBN/mxl+lCV/mCmAlw6GnhSEnhmInheGoRWOph2OpheRph6Uqx2ZrieBmSyInjiEmjqFmyKVrCObriSesiuetD6PpTSVqD+RpS6ruziuwDW9yjy1xUOGm0GKoESMoVCOokSSp0OYrEibrk+XrFKVqFGdqlmTpV2crVmir2WesGajr2muuGu3vnqjtH2zvEbD0U/N2UnV3lXW31rr73PBxmLm64amtIKzvJKst5Otupyzv466wpu1wqG3wq68xbPAyKzIzbfS18XL0MzP08bb3svc3tTX2tfa3Nrc3t/g4djm6ODh4uHi4+zs7fDw8fPz8/39/VxcXF1dXV5eXl9fX2BgYGFhYWJiYmNjY2RkZGVlZWZmZmdnZ2hoaGlpaWpqamtra2xsbG1tbW5ubm9vb3BwcHFxcXJycnNzc3R0dHV1dXZ2dnd3d3h4eHl5eXp6ent7e3x8fH19fX5+fn9/f4CAgIGBgYKCgoODg4SEhIWFhYaGhoeHh4iIiImJiYqKiouLi4yMjI2NjY6Ojo+Pj5CQkJGRkZKSkpOTk5SUlJWVlZaWlpeXl5iYmJmZmZqampubm5ycnJ2dnZ6enp+fn6CgoKGhoaKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq6ysrK2tra6urq+vr7CwsLGxsbKysrOzs7S0tLW1tba2tre3t7i4uLm5ubq6uru7u7y8vL29vb6+vr+/v8DAwMHBwcLCwsPDw8TExMXFxcbGxsfHx8jIyMnJycrKysvLy8zMzM3Nzc7Ozs/Pz9DQ0NHR0dLS0tPT09TU1NXV1dbW1tfX19jY2NnZ2dra2tvb29zc3N3d3d7e3t/f3+Dg4OHh4eLi4uPj4+Tk5OXl5ebm5ufn5+jo6Onp6erq6uvr6+zs7O3t7e7u7u/v7/Dw8PHx8fLy8vPz8/T09PX19fb29vf39/j4+Pn5+fr6+vv7+/z8/P39/f7+/iH+JENyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWMgUHJvY2Vzc29yAAAh+QQJAQAAACwAAAAAEAAQAAcIxQABCBxIsKDBIjVevJhhxOBAFx4+fPBQQUIIhyJK7NhBwgOIDhA0FGxBgkeQHjh0WOhQwYCKgUQ6nPDxA8gWLkMgXIiAgIjAGRhKmMBxkwtOAxMKyBDIIuKNoka5HEFggIPAERcsHIESxaiVJkwWFNggEAaFDhYgxDA6ZIABBAJWCBQSoUIHCjSMHjHA4IAAIQM1JKgQIUQUKzYKIAjggKCRBggiJDhAoMCBAAqSFESiYcCAAgMEMG7oMEeKDA9Q5HDI2mBAADs=
folder16:folder:filesystems:16:data:R0lGODlhEAAQAPcAAAAAACRqhzd7lj18lkF/mEKAmUSDnEmEnFyEkGCLl0WGoU6Mo1SOpFKXr1yWq2SIjmqPmn6OkmuVpGqerWeesWaktm6ktnKmt3iptnuuvX6zwoaXnIianY+doJKfoYGiqIGiqo2vs5WjpZenqZWrrpmmqKCqrJOss6Cvspm2uqOtrqusrKawsqa3uqi8vq60tK29wLGoprG6vbu1s4S1woy9ypS/xpy9xZTCzJ/L0JbF0Z3L1aTHy6fJzbDCxaTN06XT2qvV3LfJzr3DxLzQ07HT17bY3LHZ277Z4KbX4bXf5b/a4bzj573l6ca+vMLHyMPIycvIx8/T1c/Y2tfQz9bZ2dze38rx9cn0+dT6++Ld3OXk5eXr7u7v7/Dx8fX19f39/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABLzmAAAAJEFyBQgmBL0ZJEFURQTeJEFbQAAAJEEPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKAAAAAAAAAAAAAAAAAAAAAAAAJEzzgDKbRLxtBQAABL1iJDuGJFAwP///5FAuwHWjgAARRLzqBAAgBL1iJDuGJEFcP///wAAAJEEPRL03IELdQAAAP///wAAAwAAgAAAGAAAABL0xAAAQgAAABL0qAAAAAAAAAAAAAAADAAAApABAf38AAAA3gAAAAAAARoA5hQgoAAAABQgoAAAAYDi3xL1AIAaTwAHnJDiNIEQ2wAHnBL1CBL1EAAACAAABP///////wAAAwAHnBL1TML0nwAAAwAHnEPjSgAAAQAAAAAADAAAAAAAAQAAAAAAAwAAA5EFbRL1mMLlVokfmBL1mML2EwAAA8L2BEPjSgAAAQAAACH+JENyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWMgUHJvY2Vzc29yAAAh+QQJAQAAACwAAAAAEAAQAAcIxQABCBxIsKDBgwaBGOGRgsQIACSgwCBRYmAILEyaMFlShMsXK1a2cBn4IUkQJU2u5PAhxcaRHkRECIRQo4aOHUCS7LARJEsWIB1mXriQQUMNHD+ABAnC5EdQAAgUMHBAwcIFDTSO7vQgMEEDAwUMHJhKgShWmQBOILGhocICAwQOHHDgAANaF2CsSBFyA4MDAwIGGJiAdoSPKVu0UIki44QEAwEYoB1YQkSLJ1GczFixAcRkgxw6mHgRA8VnhB0iPEDIGkBAADs=
foldernew16:folder:actions:16:data:R0lGODlhEAAQAPcAAAAAACRqhzd7lT18lj2BnkSDnFyEkE6MolONo1KXr1yTplyVqVaasWSIjm+KjmGLl2mOmWmRnX6OkmScr2uVpGqerWaktm2jtHOmt3qtvF2mx26wy3GyzX60wq6GV7CLW6GTfbyVYbGdesmFMN2HJtySMt+aNe2QHOOYH++aJeuvOPG0NsOLS86JQsOKUtqQReGdZO2nQ+yqYOOpdfPLf/rHeoqOgoaXnIeanY6cn5ecl5Ken5qdmIGiqIGiqo2vs5SjpZemqpKqr5ulpKCqrJSttKCvsquhiKOto6OtrqusrKawsqWxsqa6tqi8vq60tKm3urGoprO2pbG6vbu1s4G0w4e6x4u3wY2/zZO8xZy9xZbF0JzL1p/R3aXGy6fJzbDCxaXV26vV3bfJzr3DxLbY3L7Z4KbX4bXf5b3j5r3l6b/p78a+vPTOiMbExMzIxdDU1c/Y2tfQz9bZ2cry9sn0+d32/+Pe3ePh3+Tl5e7v7/Dx8ff39/39/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKAAAAAAAAAAAAAAAAAAAAAAAAJEzzgCtJhLxtBQAABL1iJDuGJFAwP///5FAuwHWjgAARRLzqBAAgBL1iJDuGJEFcP///wAAAJEEPRL03IELdQAAAP///wAAAwAAgAAAGAAAABL0xAAAQgAAABL0qAAAAAAAAAAAAAAADAAAApABAf38AAAA1AAAAAAAARoA3BQgoAAAABQgoAAAAYDi3xL1AIAaTwAHoJDiNIEQ2wAHoBL1CBL1EAAACAAABP///////wAAAwAHoBL1TML0nwAAAwAHoEPjSgAAAQAAAAAADAAAAAAAAQAAAAAAAwAAAwAAABL1mMLlVokfmBL1mML2EwAAA8L2BEPjSgAAAQAAAAAAAwAAAwAAARL1aKH6YBL1+MNclMElGP///8L2BMQwSaHvMACAAAAAQAABpIkrOEPjSMOlLqH6YBL1zMO5ZwAAExL2CMPwCcX84MPwAIkrOEPjSAAAAMX84CH+JENyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWMgUHJvY2Vzc29yAAAh+QQJAQAAACwAAAAAEAAQAAcIywABCBxIsKDBgwbDlPFSRIgOACBaDPEwZOCPOmnUoFkj5YWMGCdm2BnY44wYNGrodGFRo42KEjB4CIyABcsWLl9cmGhDY4UJKTsEQsCAIUOVK1lEpIiBgkSToAAMHECwYMKFDR4+jAiB5AgQgQ8SFBhbAIEDDSJscLACtYiZLB0sHChAoMABBQwwfAXgpM8dOGO0YFhQQMCAAhX2AgETJ88dOW6mFKFQIACCvQOBBIHi5g0bKkpu+MBsEEcOIk+iGCGNMIeEBghjAwgIADs=
folderopen16:folder:filesystems:16:data:R0lGODlhEAAQAPcAAAAAACJpgTZ3jjx8jkF9jUR/kz6BnEWEmE6FlFKHlFaNoFmOnl2Rm1SPoVaUpmCbr2uKj2qIlWaYo2KdsGydo26grXqdpnSkrHeptnKrvH+vuLKEN7yUZL+Xcde3cOexcu26fYSTlYucnpWdg4qeoZSgopConoWkrI6oq4Krs4eys4i1vIq0tZajpZenqpmkqZ+rrZStsZaxuZS+v563va61n7+jkbu0iKOusKSvs6SxtKe5u6q1tq+4ubiuq7Ozs7a+v4O3x4u5xJW+xaa9wZnCwLfEnJ7Iy5bK1KLDx6TLyaLO0aTQ2abR2qzS0rfFyLbGy77ExbnHyrTL0r/Q0rTSy7Pa27vg4sWilMe1rMG6uMfAvs6+utmzo+S+rs3OzsbO0cLbxc7V1sna3NHLytPW19ja29vc3cft78/v68r7/+Dr7dL+/+Lc2+Pl5ejm7Ozn5vDw8Ozv9vT09Pz8/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABLzmAAAAJEFyBQgmBL0ZJEFURQTeJEFbQAAAJEEPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKAAAAAAAAAAAAAAAAAAAAAAAAJEzzgDKbRLxtBQAABL1iJDuGJFAwP///5FAuwHWjgAARRLzqBAAgBL1iJDuGJEFcP///wAAAJEEPRL03IELdQAAAP///wAAAwAAgAAAGAAAABL0xAAAQgAAABL0qAAAAAAAAAAAAAAADAAAApABAf38AAAA3gAAAAAAARoA5hQgoAAAABQgoAAAAYDi3xL1AIAaTwAHnJDiNIEQ2wAHnBL1CBL1EAAACAAABP///////wAAAwAHnBL1TML0nwAAAwAHnEPjSgAAAQAAAAAADAAAAAAAAQAAAAAAAwAAA5EFbRL1mMLlVokfmBL1mML2EwAAA8L2BEPjSgAAAQAAACH+JENyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWMgUHJvY2Vzc29yAAAh+QQJAQAAACwAAAAAEAAQAAcIyAABCBxIsKDBgwap0PkChQYMADqe7HDhYiCKJD6wdPFChgycN3LkrBEYQ80VK1aq1ADxoQOHDjbMtBCIpImVK2iW3PBQI4yRDVwqAsgQRMiQI0yOFHGShs2ILEIbPKiAQcOKo0qUWDGhZSYABQYKIFgg4cIFDSpmsADj1UKQCQ4OECCQgAGFChSeeNVBR8yUIRjiGhiQAAERrwDGuIHT5osUGRcQCAiQArHAFjl+gCGz5ceLCCcsFxRBAsYPHzpKICwYAsLq1QEBADs=
mimeunknown16:mime:mimetypes:16:data:R0lGODlhEAAQAPcAAAAAAHBwcHd3d4yMjJWVlZ2dnaGhocDAwMXFxczMzODg4O7u7vX19f39/WpsIwAR//yeT/MTEx+ZqB9+F5sAcP//DH+4Z/nv/jzv5y5o9KxH0QQRyU9nkUQutQAAAE5FSWBCrk5FSWBCrkQutQAAAE5FSWBCri614QAA7kVJAEKuREKuggAAgkVJAEKuRE3vggAAE0VJAEKuREVJgkKuRE3vggAAE0VJAEKuRO9oggATkUkAAK5ETq6CYACCYEkAAK5ETlaCYA0e1GgpDDkLHA9O3s8BRgaoGshFi48njOkxYRWeMiIlXg6qdQ4MJqZvQx05cIDPsC1lqOLQRdPoViN2BPt48VQqPfLhHCN6g+eBqFO85OBXcyUHaqsWQXEcuB30g300OBUxQMGAFJsywoafnP8HrLlyjv6Bg5fIjaSchhy44PSDkjQ4eDFAjYAUbDLCaJ+clQesxXKONYGDBsiN1ZyG5KuNgK9kgblh06dGBWCgNdeg6nf2FsLn1Ma3SwUVSyhn/STrkiyrr//aynrtj/OOzLgT5an3jBZIm5oxkCTnpAFRemXFs/Nep5RquZ9IJ/+HWl4D+OEOAwCLwEkAAK5ETiCCYChuoZCCRAAAAEAAAAAAAAAAAAAAOEHocBL6XESCkAAAAQAAQAAAQAAAIKFucESCkAAAAAAAQAAAAAAAAA4AAHDoQVz6EpCCRAEAAEAAAEAAACAAAMg8oZCCRAAAAEAAAAAAAAAAAAAAN0HocBL6XESCkAAAAQAAQAAAQAAAIKFuuESCkAAAAAAAQAAAAAAAACwAAHDoQVz6EpCCRAEAAEAAAEAAACAAAMg8oZCCRAAAAEAAAAAAAAAAAAAAHUHocBL6XESCkAAAAQAAQAAAQAAAIKFuuESCkAAAAAAAQAAAQAAAIKFswESCkAAAAAAAQAAAQAAAIKFuKP///wAAAAAAAAAAAAAAAG9ybQEBAAAAAAAAAAAAAAAACqGEfAAAAFIAAAAAAFIAAJgISwgQO4kBeIkBeDEgZiH+JENyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWMgUHJvY2Vzc29yAAAh+QQJAQAAACwAAAAAEAAQAAcIXAABCBxIsCDBAggTJjQwoOCChxAXMJhYwGHEiRgrEoSIsaPGgRI7eiwoEmODBh8Fljx5MiWAjixZupwYM6bLmjVv4mRJoODOBgwSGPyZIIDBA0iTHiggwKBTpwEBADs=
nav2uparrow16:act:actions:16:data:R0lGODlhEAAQAPcAAAAAAAJ5jRB/khJ6ixyImhyLnBuNoxuUqCKLmCGYryidsy2esTyRpT2cqy6psjSkrjKmuzyptDK0vjSxwTy1w0KJmkSYrkiZrk2gr1KXqFWZrVOmuV+mt3+sv0K9zHauxX+uwkHEy0jJ1ErL1ae2vqu2v6u5wIOvw4W3zYS605a4zZ280Jy/1KG8zam5wbO+xZDC3L7HzrLF07/K1cXM0snP1sjR1s3R1tDU2dPX28PS4d/h4ufo6ezs7fDw8fLy8/39/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABLzmAAAAJEFyBQgmBL0ZJEFURQTeJEFbQAAAJEEPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKAAAAAAAAAAAAAAAAAAAAAAAAJEzzgCtJhLxtBQAABL1iJDuGJFAwP///5FAuwHWjgAARRLzqBAAgBL1iJDuGJEFcP///wAAAJEEPRL03IELdQAAAP///wAAAwAAgAAAGAAAABL0xAAAQgAAABL0qAAAAAAAAAAAAAAADAAAApABAf38AAAA1AAAAAAAARoA3BQgoAAAABQgoAAAAYDi3xL1AIAaTwAHoJDiNIEQ2wAHoBL1CBL1EAAACAAABP///////wAAAwAHoBL1TML0nwAAAwAHoEPjSgAAAQAAAAAADAAAAAAAAQAAAAAAAwAAAwAAABL1mMLlVokfmBL1mML2EwAAA8L2BEPjSgAAAQAAAAAAAwAAAwAAARL1aKH6YBL1+MNclMElGP///8L2BMQwSaHvMACAAAAAQAABpIkrOEPjSMOlLqH6YBL1zMO5ZwAAExL2CMPwCcX84MPwAIkrOEPjSAAAAMX84CH+JENyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWMgUHJvY2Vzc29yAAAh+QQJAQAAACwAAAAAEAAQAAcIaQABCBxIsKDBgwgTKgTRQuHADg4iNFR4ogCFEQ9WJDwhQIGCCSIesDiIYkABAwQKLKCAAIbBEgNVjHQoEAMHmgAsSAixweEFAxA8eOiJkEGAAwcSTJDQQIbBFBU0SNWQgUOGDzpwaj0YEAA7
nav2downarrow16:act:actions:16:data:R0lGODlhEAAQAPcAAAAAAAJ3igx3iSaAkRKBlBeIoBaJmxqLnB2PpByUqimOnDeToCGariuftUCWqyynrzCmuC6tuC+yuTyisDSpvTazvji1xjq2xzy9w1ugtkmnuE6pulSkt2WkuGKkumapvHStv0G8y3OzzUXFz5atuJivuZ6xuYGuwYeyxoG0yYmzx5a4y5a6zqW3xYnB3KLG3LDF1rTDzrXD0cLM1crQ18rQ2czS2NTY29fa3t3e4MfT4d7f4eDi5OPl5uvr7PX29v39/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABLzmAAAAJEFyBQgmBL0ZJEFURQTeJEFbQAAAJEEPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKAAAAAAAAAAAAAAAAAAAAAAAAJEzzgCtJhLxtBQAABL1iJDuGJFAwP///5FAuwHWjgAARRLzqBAAgBL1iJDuGJEFcP///wAAAJEEPRL03IELdQAAAP///wAAAwAAgAAAGAAAABL0xAAAQgAAABL0qAAAAAAAAAAAAAAADAAAApABAf38AAAA0AAAAAAAARoA2BQgoAAAABQgoAAAAYDi3xL1AIAaTwAHoJDiNIEQ2wAHoBL1CBL1EAAACAAABP///////wAAAwAHoBL1TML0nwAAAwAHoEPjSgAAAQAAAAAADAAAAAAAAQAAAAAAAwAAAwAAABL1mMLlVokfmBL1mML2EwAAA8L2BEPjSgAAAQAAAAAAAwAAAwAAARL1aKH6YBL1+MNclMElGP///8L2BMQwSaHsGACAAAAAQAABpIkrOEPjSMOlLqH6YBL1zMO5ZwAAExL2CMPwCcX84MPwAIkrOEPjSAAAAMX84CH+JENyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWMgUHJvY2Vzc29yAAAh+QQJAQAAACwAAAAAEAAQAAcIaQABCBxIsKDBgwgTGhSxYIODhw8HuDjIQcIFBgkSBMiQsIOFERQOeFAI4AOGCBxJAgDxQWGLEiVMrGBhgoRNgy8UVIBwwACCAgJSHIQxYcSFBg0IqEhIdESIAydIytDwIKpKACiualUZEAA7
viewmulticolumn16:view:actions:16:data:R0lGODlhEAAQAPcAAAAAADiWsUKMp0uYsFipulunvFu/zGavw3G4ynm/0GHE0G/J1XTG0nzC03nR2pavs5qytp+2uqG4vKK5vKu/w7TAwoHH1oLM14LO2YTT3JDV3pLV3pza4rDBxKLK0qjR16zY367Z4LXDxbnGx7vHyb3KzKfc463e5bTh6L7k6rPt9sPMzsvq79Dv9NLv89rv8tj1+d7x9Nz3++Tm5+bo6efp6evs7Of09+33+fX29/T6+/7+/nQAb28AdF8AbXQAc3IAYXAALmcAbgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABLzmAAAAJEFyBQgmBL0ZJEFURQTeJEFbQAAAJEEPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKAAAAAAAAAAAAAAAAAAAAAAAAJEzzgCtJhLxtBQAABL1iJDuGJFAwP///5FAuwHWjgAARRLzqBAAgBL1iJDuGJEFcP///wAAAJEEPRL03IELdQAAAP///wAAAwAAgAAAGAAAABL0xAAAQgAAABL0qAAAAAAAAAAAAAAADAAAApABAf38AAAA4AAAAAAAARoA6BQgoAAAABQgoAAAAYDi3xL1AIAaTwAHoJDiNIEQ2wAHoBL1CBL1EAAACAAABP///////wAAAwAHoBL1TML0nwAAAwAHoEPjSgAAAQAAAAAADAAAAAAAAQAAAAAAAwAAAwAAABL1mMLlVokfmBL1mML2EwAAA8L2BEPjSgAAAQAAAAAAAwAAAwAAARL1aKH6YBL1+MNclMElGP///8L2BMQwSaMpaACAAAAAQAABpIkrOEPjSMOlLqH6YBL1zMO5ZwAAExL2CMPwCcX84MPwAIkrOEPjSAAAAMX84CH+JENyZWF0ZWQgYnkgZkNvZGVyIEdyYXBoaWMgUHJvY2Vzc29yAAAh+QQJAQAAACwAAAAAEAAQAAcIjQABCBxIsKDBgwUJJGhgoWECBAcKFBggIIBADzty7MiYQ+NGjSwu7ojBIsbGHS9c4NjYQuCHHScWMNiIY4OBEyxdwsxwYaMODgtQ5ATwUscNHSdxHB36kgUHoTt0pDDxYigImA5mRtWgwITVHSk2cPBpAkOKoSFOql3rQuAGGTDixpVBt64KhHjz6tUbEAA7
Added lib/BWidget/images/BWidget.png.tkico.








































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
## Plus and minus images for trees.
tree-plus:tree:tree:9:data:R0lGODlhCQAJAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A/wD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBmAABmMwBmZgBmmQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMzmTMzzDMz/zNmADNmMzNmZjNmmTNmzDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPMADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZmzGZm/2aZAGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lmAJlmM5lmZplmmZlmzJlm/5mZAJmZM5mZZpmZmZmZzJmZ/5nMAJnMM5nMZpnMmZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswAmcwAzMwA/8wzAMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZZsyZmcyZzMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9mmf9mzP9m//+ZAP+ZM/+ZZv+Zmf+ZzP+Z///MAP/MM//MZv/Mmf/MzP/M////AP//M///Zv//mf//zP///ywAAAAACQAJAAAINgARGBpI0JDABwgTPhiYEEBChggdPqDGEIBFixQNIfQHwB+1jB+pAQg5kBoCBNNSChRYcCCCgAA7
tree-minus:tree:tree:9:data:R0lGODlhCQAJAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A/wD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBmAABmMwBmZgBmmQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMzmTMzzDMz/zNmADNmMzNmZjNmmTNmzDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPMADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZmzGZm/2aZAGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lmAJlmM5lmZplmmZlmzJlm/5mZAJmZM5mZZpmZmZmZzJmZ/5nMAJnMM5nMZpnMmZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswAmcwAzMwA/8wzAMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZZsyZmcyZzMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9mmf9mzP9m//+ZAP+ZM/+ZZv+Zmf+ZzP+Z///MAP/MM//MZv/Mmf/MzP/M////AP//M///Zv//mf//zP///yH5BAEAABAALAAAAAAJAAkAAAhHAGGlMmQoVaFChmAZ+sew4T9VqRwyzEfw3zaL+fxVQ+gPhUeP/lSp8rct4zZt1DhSo4YP5bSC1KZNczZzWiGFqgwBGphKVUAAOw==

## Checkbox and radiobutton images for option trees.
check-off:prefs:photo:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CJYyPacDtfZ5kEaiKb6DLar55FwgqpGiKZXJqYTaq01PNkIvnRwEAOw==
check-on:prefs:photo:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CK4yPacDtfZ5kEaiKlaXLJsoFYLV5Ynl6IehkZ2e+XfSZoWZPD6nf1w9UFAAAOw==
radio-off:prefs:photo:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CI4yPqcsGD1qANCqIcHrXHr6AjreRYpmRKcqm5vlVcDlLtl0AADs=
radio-on:prefs:photo:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CJoyPqcsGD1qANCqIcHrXHu54YBiC42RR5Ce2m8d2sPZWsHxL+l4AADs=

actback16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADRUlEQVR42mWTTWxUZRSG3/Pde+femTvTmY4znQ6QVmEKqAVSHBQKZCTGiEhiTGDjSnZaY9wSdGGiCW5M1PhDdGGMCSsWRE0TTaCJpFb8CVWkjZPWaXFs047t/Ny5//f7PhdYovUkZ3feZ/Oeh/DfYQBEPKajOFBKJdK9/QDgtJvLy7fnum7g373ZCNDm8Ojjz5T7H6mMeZnew66q5qSQYDxs5Nqta4uTV96/PvHl9L8hGwAyEyl54vmz55o7d71WV6BxpkkAFHKOwHIlANpJMsjXF8+NX3jzLduxCIBUALB4TJdPjb3yam3HjjdauQy2Dm4TmWya3DCQgRdI01AQSoXX2l3mxePHDw/vt2emrn4LgCkA5Ojx04eaDx/41OnL033bB1C8t1+xSaLsdKikEs26nFRIRTMM1JsdJAr5yoCQ4/Xff1ti8ZiO3MjBsVVmqMl4ghsJnbkKk7sbK/T2k8dofzFH67ZHAYf0XY/1mEl+a83SsyOHXgAAVhwoZVvp9JGIMfAgZAtLDXnP9E16vbwXAJCMaXhA49hjgAoyklJGzIsE2maqsr30YFLtLWzZ4jM1zxih1erQo9Kl808chWmaAIDT5X04cX8Jpmni4tSP9Nzl76CCoc1lX8xMFhkAFklBQkjYrS4qxRxM04QfRXf73YD1GAYEDxHdaZABYGq3+ddKIeItt+MkzIwpz07+ih7DoJMjwwCA6vIKJmt/oNfQ8dXMvGSKJgUPKUH6esPurqr1hbmVIdv6wWHG05rCBBRdPTP+vfwEoJMjw5io1vDiF1Ngyp2/UMG4FwqWDdzrv9yebzLbsWDfuvHxcMpAu9Mlxn3JdJ2evfSNvDZbRSqmgimaTCfiZKhMeFaHhrIp2Dd/+sgNPCgAqLE4Xz1YPlJcluLAejuMNJUQEdGl6Squ1pYgQPB9Lpx2R+aSujqq8HcnPnvvg4hzUgAgDAOszc1+/djosW2uxh5asjzwkJMvQF0/IN9yEAU+DfVllKMxduHKh+df7lhtuVkmMhMpWTl15lRs996X/ozEvlYUpUAMWRlZeVW5EcxMvzP5+cXLGx78D/DPilyuXxnctWeop7B1kPuetFtrCwuzP8+tra+KzTr/DWYOgM1eOJPLAAAAGHRFWHRUaXRsZQBNYWRlIHdpdGggU29kaXBvZGmf9C8nAAAADnRFWHRBdXRob3IAVW5rbm93bowhDPIAAAAVdEVYdERlc2NyaXB0aW9uAGEgcGljdHVyZUGqmqAAAAAASUVORK5CYII=
actcolorize16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAORSURBVHjaYvz//z8DJQAggBg3B0IYTEBzfv9k4GXmZAgRVFL3+C5sYCohK8HLyc3J8Onls78f7py7uf7g9V0rL/5d9uoXw32YAQABxAAyYJMfEPsyeJxqNDv15vyq/3suf/h/6uW///se//v/9s+////+/Pz/98WD/9+vbvu/t9H5kYcsQzJMP0AAAEEAvv8AsU4AALNSA2Tjr2n+/v7p//7++P9Nsf7/OL3+/yqp/v/Fz9P//qh2//7GnP/+roj//vLc/9ymaP4+GQBuAAAAAAIAQQC+/wNaJwA7Hz4+qdTf8OGul5DWFfXMCwcuKQr4CgoAFgjuAFsT3QAKy5MAAPPOAPvawQABJDYAEi83ASsA2kK3x+K/AgBBAL7/A3BTJJwGGiInZnu1YbvS7X/339MgfVsoM0kQ7QBVC9cACgLzAAAYHAD7FCcA/xwfAAMECQABCyMAGxQJBObMuw8CiEXU0MhKwtyGYXLB9faf79/lyOppGP3/94WB7eNlYKj+YmD4+xcUxAysTECa9R8Dw6d5DAzSJ4HiNxhs1HmtAAKIhfnzC2YOMVYG17xwLYaPH7UYGECKgIH86ycDwx+gAX9+AxX/ARoGxL+AfOEnDAzAqPr//z6DCC8zD0AAMf9/+ZxPm+W1BT8n0Bo2oGWf3zEwfAXi7x8YGL69B+K3QP4bBoYvb8D0j08CDD8esjKwP3jLcP/Bp58AAQBBAL7/A8nk/b3ExeTJ1crY/Rr/8igXGAwEAP36AAD49gAA+vcAAPnyAP/y7wAB+PMA0Pn7AN07fgD0H0kA+9qxANzQ8u0CiBkUFc++M9wFGrTh4Ok3V9WY3zoqK/LxgL3w4wvDv/8CDN9E/BjY/v9hWPzvDkOn0UeGzfyXGD5cvsbwaf+fYwABxIScLK9/YthQsOxt6tWT94Ee/s7w78s3husvchheSXUy3Pq7mMH8HTuD5tf7DMpf7jDI3//BsPY+ww6AAGJBT9vXgRbM2fFiWZ8cYxwTyx+GF7f5weH38bYwgycvG8OKdY8Yfv5gZqjbxXDu0ieGtQABxIwtgzz+wHCB9+d3d3XhP6KyApcYRGS+Myj9b2UQ4rrC8OXtP4Ype//e6r/AkP/zH8MlgABixJXLuJkZlLwUGbKNpRmcRbgZxLjZGBhffGL4vvcew+49jxjm/vjHcBao7C9AADESkWNFgJgHlHMZwImE4RUDKICgACDAAIaNf6pWNsqkAAAAAElFTkSuQmCC
actup16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADQklEQVR42mWTzWtcZRTGn/Pe7zsz6cw0k0mnaUJMYit+NWpIm6ZWi5HSiiAo+B+oQelGQVpBhVaj4EKhEHQhblyIi9JFFlZU0CpS0w9aU9tEk05S0+kkmZk798699733vq+bJmh84OzO78dZnIfw3zAAwtINbOvuz9hbcp0A0GrUlpfLc67Pw42ddYA2wyNjzz3WOXxgPMjm9vmq2i6FBEuiatF1f7zx7ZlT0+fOXvq3ZF1AKTsjD7/85rHavTvfWVKgRUyTAEgkCXjTlyIK6R5N46Vb5WNTkxMfea0mAZAKAGbphjwyfvyt+b6+E2GxgEL3dpHdmqUw4jIKuEzZNhKmJDe9FosymUMj9+32Zn757mcATAEgRw69sNffM/qFU8jRjt4ulHqKSgvAbt+hYVunnyprZCqKooKwWHeRy+cOlICppb+u/80s3UD74J7xsiQ1bdmJaRvMVxV5/2qFJkaH6N0jB+nVviJV645UDJ2lLTO54PhGfnDvKwCgdPfuypv7Dp6sWlY2ZeioRRz9i2U6MTyIVCoFAHh8oBeJU6Opa2VpGQY5nk8daStDC3Ofs1yxVAqZWlAJWKs7NOTUaGJ0aANez/HDT+LDJx4g3/NI1VU0EtlhbcltUwGwWApKeAIv9tG/I4erlRVotIJHensAALOVKuZXauhqS8MigVYoAEthAJjq1lYqxTipt0Jut5m6/GBmEf75WXqqM4Ov7wq+mr6Kt7+/DM00pQ4mReiTbdtrVc+9w5YW5iptXvO8aAUIAy7Smk6GaUpT0zbOTxk6NNOUGU2nJE4EAOS5/+ty+c8a81pNuFd++6ykEZyGS2HApWgFVK668sL8TcxWqvjj9oqMeUxhxIXfcGkg3wbvyvSnPg9A61/47BvvTf4g6aV6ICIrk2JRFLM4CAERI4QCg5HwG65szxjqWEr/5PT7rx/1eUgKAEQRx+3fL37z9P6xLm6bj5ZX6+CcUwJGsRAkeYTYD2igM6/s12ny7KmTR51mQ24uE23Nd8jhZ158Xt/10Gu3YvFwPREZJgWyEM2CqlzkM5c+Pnfmy9PrPfif4O6I9vZOpWfngwNtxe09SRhIr766sHDt8tzq2h2xuc7/AKCThTNYzwiKAAAAGHRFWHRUaXRsZQBNYWRlIHdpdGggU29kaXBvZGmf9C8nAAAADnRFWHRBdXRob3IAVW5rbm93bowhDPIAAAAVdEVYdERlc2NyaXB0aW9uAGEgcGljdHVyZUGqmqAAAAAASUVORK5CYII=
folder16:folder:filesystems:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAC8UlEQVR42n2TS2gbVxiFz71z53FnpJHGcqNpEwtsJ3KTitQ2hkJWadI0zcYJdNVFNm0gm1KyKaXrUgpZtQS6DKQNXfZJwSQBL0ogXXRRU4GdWsRPIU8sjx4zo5GiuTcL2WrqQs/qv/8PH5fDOcBABP8VAcCgGezQfbDfl3IwvPbWOx8WilMzHUIRB2EHST8GIJD0BQCNWOlXQKhE0u8CEC/SUJp/9+NPP//iZpYR4TcadM/zGlvrG6trldWlyspy+dL85ffenjk9u+E3ny6vrVcXFxcXHv70w2foxR0CAO9/+fW969c+uND2610QqgKgNIxlu9chc24eOVPHZm0HAKSpqgm4xeavXv3kj4VfbzIA8Lx6r7JZgyqeMc4NYmhMWPlR+eTx3/JRuSzHRxz68GmDjh09IgOvnrjcYK7rFrBvErY9n21XdwAApq5B1xjlvAWeHoEPVVb32sR1XUyOF4BxKEuP19BqB2IA6MUAQKu1OgCAGyoUVYVtcXCVImvphOdyAIDl1Q2Sskwpe92hfwwA/FZI/lr3YOsUhqEjxXU0WyEUQpBKm9AVAt0wwFWKZhijEwVQFEUOAXbW1tOOjcZuHaIVgjIGjQAm12E0BkBT14a/0xUCxiiGgLOnJrpXzs2gvLUFL0xIrRnInZ090oi6EK0QhjrIzYhjAwDGRlPDVDEAODaaVd4sFjDGhGiHkahFKbr9coZW6i2yuRvI2l6LBHEPQbwLplBk+DB/gyT2M7nZdNaZNjlX83aavmQw6ioCkxZLxkxF5lMadAo0noFUqp7IWJYivLXfV5f+XPgn45oxki9OnZmbm7s4PTt77uTx41MFJ6MYELLfiUgQRYkfxWLF84W0Hf23hZ+/evDd3RsHAAJAvlAYqo3mX50olc6ffn36YulE8UzhSM6xNSZJFPSbpq3e/f7HWw++uf3R4ZbR/Tn5Vy81I+OMT74xUTxxoVScOi+d3Mlfvr0z76+U7+N/RPdNpof2jFjpoweP50IVE3k02KZIAAAAGHRFWHRUaXRsZQBNYWRlIHdpdGggU29kaXBvZGmf9C8nAAAADnRFWHRBdXRob3IAVW5rbm93bowhDPIAAAAVdEVYdERlc2NyaXB0aW9uAGEgcGljdHVyZUGqmqAAAAAASUVORK5CYII=
foldernew16:folder:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADFElEQVR42n2TS2wbVRiFz713Xh57POM4TTyETGurOIE4kFCpBYSgTRrBqkUCygKxZMcKqQs27CpQJbbseFRILbBCSgsRlVIVFQmQInBwhdoSF9VxprYnHr+SceyZOyxITFokzu5/6PulX+cw/COC/4oAEABQAOFDM7bXY3udqZMvv2NlJ2Y9QtHtbHsI/O7uEs8aJJ0eic1seKwMJgKBH+6/gtypV8++98GH5w0K3nAbtFbaaGzUKn/e/fnqarHRL7yRi7910lifvZF43VbznzcvOpnF5a8uvQ+gKwDA0bn5hcMHLbTqTn9U00Q9ZRpPquqRTlo9MnnnAkmYekgC8Der58yt588cOHH6o7Nnmi1nZenKeQoA1epmb610H27LE7o9nyiSwKMRmdfGngnsLu3Hx00uTyyQwHqE79jfB8KltzGuUQu7T0LJaQsbdg0AEJEYZFmm0XIZ2evnMGbUwp6sE/AuJDEEUyWWTx1Hi17hAwDlPi3vAhRZgKIoUBlHbfZd1O99S15Y+RRBbBxeq0q4Q8NOZgiB75MBwG1tkbVdgKZIiCgyIrIIoo3Cqq3hOjsKs3YTbWMO5YnjUO1VCKoWDgC6octCVEPD2UTH6wHoQCIhYpE6rtFjqI89i9e8RdxqKlgXn4BpZhH28hgAXpzK7LwyN4vCvXU4O5zYbjusVDZJfbuHCjcQLRbwiTKJuCxg214HiytgTPgX8GhSZyeyFg4LPne2u/z+cJSWTZ2uOU1Sctqh7XaI67bhEgKBtpCSDzxgSfh68mnNSMzIEVUc1mJ0RBFpinFYCg0OalKYikmQKeD2QYp2lRtRlXnV0i93V3/9jgHAX7+tLH198cuPv1levvHj7WK9udWN9UUpqcuiYKgyMSVCM1HGp3QWWDHKR4Y0oXTnj5+Kv68uCQNL97x6pZC/XCnkL1/7DFQaHp3M5HLz00/NvDT9WPY5aySZiEsSnR6K+k1VwQ9MpA+nkACgkCJAzwseyJ4U0RPpzLFM+tBCbio3HyaSjy9+ceGUe+vmVfyP6L4475dANX1sr/gbbgww8WkO7t4AAAAYdEVYdFRpdGxlAE1hZGUgd2l0aCBTb2RpcG9kaZ/0LycAAAAOdEVYdEF1dGhvcgBVbmtub3dujCEM8gAAABV0RVh0RGVzY3JpcHRpb24AYSBwaWN0dXJlQaqaoAAAAABJRU5ErkJggg==
folderopen16:folder:filesystems:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAADHUlEQVR42n1TS28bVRg99854xnPHk3HiOHYSO00dGoeSFgoUokqFAC0LpLSqxIJuEGKH+AFskFiAWPAL2LBgkyxYIAQSQaiCokqtQp3WNSFDE9vBSZzi5zh+jD0PXzZuVJ6fdBbf+aTzSUfnAP89BIA4APkXHgAgDAhh/tXX3h2bOXGmJ0roVcsWgC6A/gASFHUCrsMB9AbckRoA6N/dXs9ePD0fWs9keKHtNDYLe9vZjbv37m4aG1cvLV2dTyafPqhWyvnfC8Xvf7qxeuuL5Q8BWOTk4itvxM88c/H1paUrk7WiPtQuITwSpIwxXhuKEwCYmJyEBxmCX+EAvLbXFS+/+dZ76W+//kQ8fnZh8YOPP3rb3Ct4vViU1gFet+p9e/cX/qKT4rbV5pk1UK/fogINcK5OefFzl8X4eHQqDUDcTKXSN29n2iFFlnRGBdknQQudoFuejDvFEiblNq8fe5KEk0m0HvwK+4dPhdbUKdic9AFArO7vZu/vFBHRh6gi9KGIAFP9kPwadkcvIGe3SCg4Am10HMGZc+RHY59HrEMQQgkAiJ1KKW9s51vtaFRVRXBVkaActqBIJgJ+P1TG0O1Z2NjOQddNOGoMti8A17E5AIhOtbzfbFn1XLEaEd0OZxKIpgagMR90TQEAMBaAX3BgNjuwAxH4RsdBPQcYBKITFrrF588uzOX2/+DtbodUG008qNcBAMNMhspkaKoMX82C43bRCIWPUiUCQIR3jPcvPPty6rct98ByhUKzSQvlBsmXTVIzD3nFJKRfrmBMlWC7fdSP9/4qsJZaz/y8U8DEsC5Ohwh9qsNIKajwcjzkZEt1stVo0uxuh+yZNjmomXhu7hA+So+ijFJ2687nyysr39y4mU7nd1pdFxpxuvpIaFR8TJNIUhXp48OMJ4ZkN0C4N6IxMXffuJXL3Ft9WArPqZYN4/o1w7h+7bNlwKceS5yMJWZeOD3/xEtzs7MLibHweCyokmkWRcUnHz1/tGX0kd37WzMVNhE7NT2bPJ9IJM6HpxOLq199+c5Bam3lf9oMOvBI+MdFUbWH/v0JsjRJYWeyB/MAAAAYdEVYdFRpdGxlAE1hZGUgd2l0aCBTb2RpcG9kaZ/0LycAAAAOdEVYdEF1dGhvcgBVbmtub3dujCEM8gAAABV0RVh0RGVzY3JpcHRpb24AYSBwaWN0dXJlQaqaoAAAAABJRU5ErkJggg==
mimeunknown16:mime:mimetypes:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAMhJREFUeAFjYKAQMCLpt5o5c+YRRkZGBhAGARgbXWzq1KlTTp8+nQdSw4JkAKu/vz+GJiYmJgyxjRs3MgENAGtFNoABphibJmTXIFmKagAzMzOGbejeQPYOThfg0oTNFVi9QMgAnF4g5PeBdwGy02FsosIAm0aiDMCl8fPnz3AprC7ApfH79+8MN27cYLh06dIjbGrs/xEAJ0+e/BcTE/MAqJkfmxd+HzhwAJvBDP///2e4f//+7/nz5+88evRoLlDRR6wKyREEAJFnT+G1LkTuAAAAAElFTkSuQmCC
nav2downarrow16:nav:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAACb0lEQVR42qVT70tTURh+z73nbuz+mM62yVIRo1Ihw5IItcIUE6ISyhUYBBX9A2F96Ft9CVEIqg9iQUhQHyJGhZTGSLTpmL/KJjgIbdq0TZ26ud/33NOXe0syMOmBFw6853ne57znfRH8BlLjX0DV+H8gAABRkJg9FUdKZTlDOcQQAGC0PGVZQIRo7hTKsnw0vLT81Ts8AwCAAQDWY1Gl6UrLqVlRaPHMTUoWq02OhiOaCCgKRQBAlpeDBntVQ2DqeWezKsCw2iXPe4ervKQ8Riy5NQsmTsI7rDgYT3BhonARhBhfYFZ/aGdhcKn7xcXXT+8PqI7oL4F0Js2MfHjjqS097Jf0xppViedzC8wEyaDEwiG21la4wLn7z6tkFgAUUA8b+4FHP777XFZQ7MsyWetWBBCTmRRTktEtskN9Fxxd9wYAQAcARCNtFKCqKvIO903t1Uu9OTn5x8RkKoacPSdfPXvoUYsQ+KMqAgB66fpdO5tlOuoPBVKYZXF8PbJ2oKq+EnMcHh/sHdTp+WyZkLRBkIxmiga72m48AQCENaVxt3P07M22a+7p0Xphd5GSiabRy/kAkhUKuuKy46mUTBOrIaZ5X8WXkY7W9k1PCM1NrwS8Y46mOrvlezJSYSzKI7zRRBnAgLAuE19b4poKiwc8D+6c+eTp82/6BQBgwqH51GT/297T1Y3Gb7HVKt5mRnqDQQn5Z3QnsnOHxjtb7RNjrh/qoNG/NRElEnHZ53b2NJTXMmFKqheTK7iS8EMTj9vPTYy5FlSystV4I1GQ4PLtjltXH3W79h+stmkut7UooiDhvPxd4sa92S7QVuSfmy79fTgawK8AAAAYdEVYdFRpdGxlAE1hZGUgd2l0aCBTb2RpcG9kaZ/0LycAAAAOdEVYdEF1dGhvcgBVbmtub3dujCEM8gAAABV0RVh0RGVzY3JpcHRpb24AYSBwaWN0dXJlQaqaoAAAAABJRU5ErkJggg==
nav2uparrow16:nav:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAACVklEQVR42qWT3UsUYRjFz7wzo4774dduuLImVJqWrIu6lolKa9gHKwlSEgaBBkEJFdFFQeJVf0IXUTcFdhFpeFFEkqBCuLY3mkJqkUrtruhuM6O7O7Pz0U0DU7le1Ll54YXz4+Gc5wF2F4X/EGV6M4LoDP8EgF5e6XXkchYiCHE5E4TOYNY8tU0uX/+9V4eP+OsiH0OvBSGuGuDdAASA5q1vLanuvTEyW0j7eCvr9ftOl8eWF8ZiG5HUnxB6J7On7+aL8a3No84St2Jzu/RFcd3T3hioTn5bHY98XxHNEANAAdA9tU2umsu3no9GVo9ZHS5ZltJMWlFRUOpWPvHhKn/zWS821ifXvi7GjUxow9zQeqaq8frg6PDSbH2u3aapisbIQgzb8TilbkuEKyrSP3ye3x/o7G3Pp8jc4lxwBQDFGPNb9lXu46cnXtbwsScIhxlKVX54j3ecYxlWnnk7PALAXkYzaujLWpbTWez6ZdN3qoYA0Dp6+k+JLc1DVjorYQvO9D17eP+NMW2mFggAFoBy/urAxc26hiGx1GElbqddtzm62mpa+Pnpd0FFSTNmkBlAAVAuXBvojh6qfrQsSVwOwylcNqfJNktWimX87b4T0kJwfEqSUn/VSAHQO6/cvbR6oOLx+2iYs+bn6YlUkt7iE4Rk0xAtNBtNS22B1k7bUmhqIrktqoaRANC6+m6f3BvofjAWmuQK8grTptXVFS0Nuz1PEwSeVBSXKQeZnKd3epoHzQeDoj0lhVw2xwAw7705MB2ALusaAcCKm9GNZDLxW6D/pJ+z/OtphdemuQAAABh0RVh0VGl0bGUATWFkZSB3aXRoIFNvZGlwb2Rpn/QvJwAAAA50RVh0QXV0aG9yAFVua25vd26MIQzyAAAAFXRFWHREZXNjcmlwdGlvbgBhIHBpY3R1cmVBqpqgAAAAAElFTkSuQmCC
viewmulticolumn16:view:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAACNUlEQVR42qVTTWsTURQ9933MTGaa0iZNY1NrW6ULRYUigrjQlaCLguDCjRv/h0s3/gHFv9ClKAiCICpEXFQrtRWlBGwNTUvSdpLM53vjwnlNunHTCw8el3vPOffc9whEOEkISFuUby3dtyw5BkABIHO00kf3VCnDRGmqSAjOuyv1ZQHLchfvPXhydX52mhjTti0ZAEBrhFGCMIrRCyL0wggA0Nn3s6AbIPA8WjtorwrEsbxRG//56ObllW6vnzqcawAUKsWNTIfzFEAGgIdKMYfz+H3bn73z/DGJXCIDoBtROr4b9kcqjhVcLI22jfwve/vVQGk+V3T9Kc8NADDbjlnGBTEA5LoOA6BW24fzL7Z3rzxb27xg2Jv9ULzdaS8+3Whce9lo1nKfWA4Oo8CEqrg2fK21SRSlyAqW1BNuAZ4lTW022MIAQNw+PfnjME42Ry15tI0RKdK705V6VC2JiYId5T2JATBSCID+2j6cfPV7Z+H1VquWs2TdJOWfWp3am63WzK+DrpfnaQDgFmG7HgFQzX5Y+aP1mY/NvZopiJVmm73gbH3fP/e51SnlHpjIhkdgRcH9MmN+uTTqG2UWZ9m4JQ+mHVufcp04V33MA5bPlC7NTa0DWB9+qiNS4OHCzIcc0MiPAcSkdSa45HoHrPI9SEuxUnq4mUCQnNEwYw6QbGe8mjEGguXIwvlL1xVQMAwcIJWPwIeMFmNlon+ABIBFG9/e0cl/4/F1AtIGkuj/XYMa/RciR9q33rl+dQAAABh0RVh0VGl0bGUATWFkZSB3aXRoIFNvZGlwb2Rpn/QvJwAAAA50RVh0QXV0aG9yAFVua25vd26MIQzyAAAAFXRFWHREZXNjcmlwdGlvbgBhIHBpY3R1cmVBqpqgAAAAAElFTkSuQmCC
Added lib/BWidget/images/bold.gif.

cannot compute difference between binary files

Added lib/BWidget/images/copy.gif.

cannot compute difference between binary files

Added lib/BWidget/images/cut.gif.

cannot compute difference between binary files

Added lib/BWidget/images/downarrow.gif.

cannot compute difference between binary files

Added lib/BWidget/images/dragfile.gif.

cannot compute difference between binary files

Added lib/BWidget/images/dragicon.gif.

cannot compute difference between binary files

Added lib/BWidget/images/error.gif.

cannot compute difference between binary files

Added lib/BWidget/images/file.gif.

cannot compute difference between binary files

Added lib/BWidget/images/folder.gif.

cannot compute difference between binary files

Added lib/BWidget/images/hourglass.gif.

cannot compute difference between binary files

Added lib/BWidget/images/info.gif.

cannot compute difference between binary files

Added lib/BWidget/images/italic.gif.

cannot compute difference between binary files

Added lib/BWidget/images/minus.xbm.










>
>
>
>
>
1
2
3
4
5
#define minus_width 9
#define minus_height 9
static char minus_bits[] = {
 0xff,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x7d,0x01,0x01,0x01,0x01,0x01,0x01,
 0x01,0xff,0x01};
Added lib/BWidget/images/new.gif.

cannot compute difference between binary files

Added lib/BWidget/images/opcopy.xbm.










>
>
>
>
>
1
2
3
4
5
#define opcopy_width 11
#define opcopy_height 11
static char opcopy_bits[] = {
 0xff,0xff,0x01,0xfc,0x21,0xfc,0x21,0xfc,0x21,0xfc,0xfd,0xfd,0x21,0xfc,0x21,
 0xfc,0x21,0xfc,0x01,0xfc,0xff,0xff};
Added lib/BWidget/images/open.gif.

cannot compute difference between binary files

Added lib/BWidget/images/openfold.gif.

cannot compute difference between binary files

Added lib/BWidget/images/oplink.xbm.










>
>
>
>
>
1
2
3
4
5
#define oplink_width 11
#define oplink_height 11
static char oplink_bits[] = {
 0xff,0xff,0x01,0xfc,0xf1,0xfc,0xe1,0xfc,0xf1,0xfc,0xb9,0xfc,0x19,0xfc,0x09,
 0xfc,0x11,0xfc,0x01,0xfc,0xff,0xff};
Added lib/BWidget/images/opmove.xbm.










>
>
>
>
>
1
2
3
4
5
#define opmove_width 11
#define opmove_height 11
static char opmove_bits[] = {
 0xff,0xff,0x01,0xfc,0x01,0xfc,0x51,0xfc,0x89,0xfc,0xfd,0xfd,0x89,0xfc,0x51,
 0xfc,0x01,0xfc,0x01,0xfc,0xff,0xff};
Added lib/BWidget/images/overstrike.gif.

cannot compute difference between binary files

Added lib/BWidget/images/palette.gif.

cannot compute difference between binary files

Added lib/BWidget/images/passwd.gif.

cannot compute difference between binary files

Added lib/BWidget/images/paste.gif.

cannot compute difference between binary files

Added lib/BWidget/images/plus.xbm.










>
>
>
>
>
1
2
3
4
5
#define plus_width 9
#define plus_height 9
static char plus_bits[] = {
 0xff,0x01,0x01,0x01,0x11,0x01,0x11,0x01,0x7d,0x01,0x11,0x01,0x11,0x01,0x01,
 0x01,0xff,0x01};
Added lib/BWidget/images/print.gif.

cannot compute difference between binary files

Added lib/BWidget/images/question.gif.

cannot compute difference between binary files

Added lib/BWidget/images/redo.gif.

cannot compute difference between binary files

Added lib/BWidget/images/save.gif.

cannot compute difference between binary files

Added lib/BWidget/images/target.xbm.


















>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
#define target_width 24
#define target_height 24
static unsigned char target_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00,
   0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x3e, 0xe0, 0x03, 0x3e, 0xe0, 0x03, 0x3e, 0xe0, 0x03, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00,
   0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Added lib/BWidget/images/underline.gif.

cannot compute difference between binary files

Added lib/BWidget/images/undo.gif.

cannot compute difference between binary files

Added lib/BWidget/images/uparrow.gif.

cannot compute difference between binary files

Added lib/BWidget/images/warning.gif.

cannot compute difference between binary files

Added lib/BWidget/init.tcl.








































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
if {[string equal $::tcl_platform(platform) "windows"]} {
    option add *ListBox.background      SystemWindow            widgetDefault
    option add *ButtonBox.padY          0                       widgetDefault
    option add *Dialog.padY             0                       widgetDefault
} elseif {[tk windowingsystem] eq "aqua"} {

} else {
    option add *Scrollbar.width         12                      widgetDefault
    option add *Scrollbar.borderWidth   1                       widgetDefault
    option add *Dialog.separator        1                       widgetDefault
    option add *MainFrame.relief        raised                  widgetDefault
    option add *MainFrame.separator     none                    widgetDefault
    option add *MessageDlg.usenative    0                       widgetDefault
}

option read [file join $::BWIDGET::LIBRARY lang en.rc]

## Add a TraverseIn binding to standard Tk widgets to handle
## some of the BWidget-specific things we do.
bind Entry   <<TraverseIn>> { %W selection range 0 end; %W icursor end }
bind Spinbox <<TraverseIn>> { %W selection range 0 end; %W icursor end }

bind all <Key-Tab>       { Widget::traverseTo [Widget::focusNext %W] }
bind all <<PrevWindow>>  { Widget::traverseTo [Widget::focusPrev %W] }

namespace eval ::BWidget {
    variable library     $::BWIDGET::LIBRARY
    variable langDir     [file join $library lang]
    variable imageDir    [file join $library images]
    variable imageFormat GIF

    variable iconLibrary
    if {![info exists iconLibrary]} {
        set iconLibrary BWidgetIcons
    }

    variable iconLibraryFile
    if {![info exists iconLibraryFile]} {
        set iconLibraryFile [file join $imageDir BWidget.gif.tkico]
    }

    variable colors
    if {[string equal $::tcl_platform(platform) "windows"]} {
        array set colors {
            SystemButtonFace    SystemButtonFace
            SystemButtonText    SystemButtonText
            SystemDisabledText  SystemDisabledText
            SystemHighlight     SystemHighlight
            SystemHighlightText SystemHighlightText
            SystemMenu          SystemMenu
            SystemMenuText      SystemMenuText
            SystemScrollbar     SystemScrollbar
            SystemWindow        SystemWindow
            SystemWindowFrame   SystemWindowFrame
            SystemWindowText    SystemWindowText
        }
    } else {
        array set colors {
            SystemButtonFace    #d9d9d9
            SystemButtonText    #000000
            SystemDisabledText  #a3a3a3
            SystemHighlight     #c3c3c3
            SystemHighlightText #FFFFFF
            SystemMenu          #d9d9d9
            SystemMenuText      #FFFFFF
            SystemScrollbar     #d9d9d9
            SystemWindow        #FFFFFF
            SystemWindowFrame   #d9d9d9
            SystemWindowText    #000000
        }
    }

    if {[lsearch -exact [font names] "TkTextFont"] < 0} {
        catch {font create TkTextFont}
        catch {font create TkDefaultFont}
        catch {font create TkHeadingFont}
        catch {font create TkCaptionFont}
        catch {font create TkTooltipFont}

        switch -- [tk windowingsystem] {
            win32 {
                if {$::tcl_platform(osVersion) >= 5.0} {
                    variable family "Tahoma"
                } else {
                    variable family "MS Sans Serif"
                }
                variable size 8

                font configure TkDefaultFont -family $family -size $size
                font configure TkTextFont    -family $family -size $size
                font configure TkHeadingFont -family $family -size $size
                font configure TkCaptionFont -family $family -size $size \
                    -weight bold
                font configure TkTooltipFont -family $family -size $size
            }

            classic - aqua {
                variable family "Lucida Grande"
                variable size 13
                variable viewsize 12
                variable smallsize 11

                font configure TkDefaultFont -family $family -size $size
                font configure TkTextFont    -family $family -size $size
                font configure TkHeadingFont -family $family -size $smallsize
                font configure TkCaptionFont -family $family -size $size \
                    -weight bold
                font configure TkTooltipFont -family $family -size $viewsize
            }

            x11 {
                if {![catch {tk::pkgconfig get fontsystem} fs]
                    && [string equal $fs "xft"]} {
                    variable family "sans-serif"
                } else {
                    variable family "Helvetica"
                }
                variable size -12
                variable ttsize -10
                variable capsize -14

                font configure TkDefaultFont -family $family -size $size
                font configure TkTextFont    -family $family -size $size
                font configure TkHeadingFont -family $family -size $size \
                    -weight bold
                font configure TkCaptionFont -family $family -size $capsize \
                    -weight bold
                font configure TkTooltipFont -family $family -size $ttsize
            }
        }
    }
} ; ## namespace eval ::BWidget
Added lib/BWidget/label.tcl.






















































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
# ------------------------------------------------------------------------------
#  label.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: label.tcl,v 1.10 2003/10/20 21:23:52 damonc Exp $
# ------------------------------------------------------------------------------
#  Index of commands:
#     - Label::create
#     - Label::configure
#     - Label::cget
#     - Label::setfocus
#     - Label::_drag_cmd
#     - Label::_drop_cmd
#     - Label::_over_cmd
# ------------------------------------------------------------------------------

namespace eval Label {
    Widget::define Label label DragSite DropSite DynamicHelp

    Widget::tkinclude Label label .l \
        remove { -foreground -state -text -textvariable -underline }

    Widget::declare Label {
        {-name               String     ""     0}
        {-text               String     ""     0}
        {-textvariable       String     ""     0}
        {-underline          Int        -1     0 "%d >= -1"}
        {-focus              String     ""     0}
        {-foreground         Color      "SystemButtonText"       0}
        {-disabledforeground Color      "SystemDisabledText"     0}
        {-state              Enum       normal 0  {normal disabled}}

        {-autowrap           Boolean    "0"    1}
        {-wrappadx           Int        "10"   0}

        {-elide              Boolean    "0"    1}
        {-ellipsis           String     "..."  0}
        {-elidepadx          Int        "5"    0}
        {-elideside          Enum       "right" 0 {center left right}}

        {-fg                 Synonym    -foreground}
    }

    DynamicHelp::include Label balloon
    DragSite::include    Label "" 1
    DropSite::include    Label {
        TEXT    {move {}}
        IMAGE   {move {}}
        BITMAP  {move {}}
        FGCOLOR {move {}}
        BGCOLOR {move {}}
        COLOR   {move {}}
    }

    Widget::syncoptions Label "" .l {-text {} -underline {}}

    bind BwLabel <FocusIn>   [list Label::setfocus %W]
    bind BwLabel <Destroy>   [list Label::_destroy %W]
}


# ------------------------------------------------------------------------------
#  Command Label::create
# ------------------------------------------------------------------------------
proc Label::create { path args } {
    Widget::initArgs Label $args maps

    frame $path -class Label -borderwidth 0 -highlightthickness 0 -relief flat
    Widget::initFromODB Label $path $maps(Label)

    Widget::getVariable $path data

    set data(width) 0

    eval [list label $path.l] $maps(.l)

    if {[string equal [Widget::cget $path -state] "normal"]} {
        set fg [Widget::cget $path -foreground]
    } else {
        set fg [Widget::cget $path -disabledforeground]
    }

    set var [Widget::cget $path -textvariable]
    if {$var == ""
        && [Widget::cget $path -image] == ""
        && [Widget::cget $path -bitmap] == ""} {
        set desc [BWidget::getname [Widget::cget $path -name]]
        if {[string length $desc]} {
            set text  [lindex $desc 0]
            set under [lindex $desc 1]
        } else {
            set text  [Widget::cget $path -text]
            set under [Widget::cget $path -underline]
        }
    } else {
        set under -1
        set text  ""
    }

    $path.l configure -text $text -underline $under -foreground $fg

    set accel [string tolower [string index $text $under]]
    if {[string length $accel]} {
        bind [winfo toplevel $path] <Alt-$accel> [list Label::setfocus $path]
    }

    bindtags $path   [list BwLabel [winfo toplevel $path] all]
    bindtags $path.l [list $path.l $path Label [winfo toplevel $path] all]
    pack $path.l -expand yes -fill both

    set dragendcmd [Widget::cget $path -dragendcmd]
    DragSite::setdrag $path $path.l Label::_init_drag_cmd $dragendcmd 1
    DropSite::setdrop $path $path.l Label::_over_cmd Label::_drop_cmd 1
    DynamicHelp::sethelp $path $path.l 1

    if {[string length $var]} {
        upvar #0 $var textvar
        _trace_variable $path
        if {![info exists textvar]} {
            set textvar [Widget::getoption $path -text]
        } else {
            _update_textvariable $path "" "" write
        }
    }

    if {[Widget::getoption $path -elide]
        || [Widget::getoption $path -autowrap]} {
        bind $path.l <Configure> [list Label::_redraw $path %w]
    }

    return [Widget::create Label $path]
}


# ------------------------------------------------------------------------------
#  Command Label::configure
# ------------------------------------------------------------------------------
proc Label::configure { path args } {
    set oldunder [$path.l cget -underline]
    if {$oldunder != -1} {
        set oldaccel [string index [$path.l cget -text] $oldunder]
        set oldaccel [string tolower $oldaccel]
    } else {
        set oldaccel ""
    }

    set oldvar [$path.l cget -textvariable]

    set res [Widget::configure $path $args]

    set cfg  [Widget::hasChanged $path -foreground fg]
    set cdfg [Widget::hasChanged $path -disabledforeground dfg]
    set cst  [Widget::hasChanged $path -state state]

    if { $cst || $cfg || $cdfg } {
        if { $state == "normal" } {
            $path.l configure -fg $fg
        } else {
            $path.l configure -fg $dfg
        }
    }

    set cv [Widget::hasChanged $path -textvariable var]
    set cb [Widget::hasChanged $path -image img]
    set ci [Widget::hasChanged $path -bitmap bmp]
    set cn [Widget::hasChanged $path -name name]
    set ct [Widget::hasChanged $path -text text]
    set cu [Widget::hasChanged $path -underline under]

    if { $cv || $cb || $ci || $cn || $ct || $cu } {
        if {  $var == "" && $img == "" && $bmp == "" } {
            set desc [BWidget::getname $name]
            if { $desc != "" } {
                set text  [lindex $desc 0]
                set under [lindex $desc 1]
            }
        } else {
            set under -1
            set text  ""
        }
        set top [winfo toplevel $path]
        if { $oldaccel != "" } {
            bind $top <Alt-$oldaccel> {}
        }
        set accel [string tolower [string index $text $under]]
        if { $accel != "" } {
            bind $top <Alt-$accel> [list Label::setfocus $path]
        }
        $path.l configure -text $text -underline $under -textvariable $var
    }

    if {$cv} {
        if {[string length $oldvar]} {
            trace remove variable $oldvar [list write unset] \
                [list Label::_update_textvariable $path]
        }

        _trace_variable $path
    }

    if {$ct && [Widget::getoption $path -elide]} {
        _redraw $path [winfo width $path]
    }

    set force [Widget::hasChanged $path -dragendcmd dragend]
    DragSite::setdrag $path $path.l Label::_init_drag_cmd $dragend $force
    DropSite::setdrop $path $path.l Label::_over_cmd Label::_drop_cmd
    DynamicHelp::sethelp $path $path.l

    return $res
}


# ------------------------------------------------------------------------------
#  Command Label::cget
# ------------------------------------------------------------------------------
proc Label::cget { path option } {
    return [Widget::cget $path $option]
}


# ------------------------------------------------------------------------------
#  Command Label::setfocus
# ------------------------------------------------------------------------------
proc Label::setfocus { path } {
    if {[string equal [Widget::cget $path -state] "normal"]} {
        set w [Widget::cget $path -focus]
        if { [winfo exists $w] && [Widget::focusOK $w] } {
            focus $w
        }
    }
}


# ------------------------------------------------------------------------------
#  Command Label::_init_drag_cmd
# ------------------------------------------------------------------------------
proc Label::_init_drag_cmd { path X Y top } {
    set path [winfo parent $path]
    if {[set cmd [Widget::cget $path -draginitcmd]] != ""} {
        return [uplevel \#0 $cmd [list $path $X $Y $top]]
    }
    if { [set data [$path.l cget -image]] != "" } {
        set type "IMAGE"
        pack [label $top.l -image $data]
    } elseif { [set data [$path.l cget -bitmap]] != "" } {
        set type "BITMAP"
        pack [label $top.l -bitmap $data]
    } else {
        set data [$path.l cget -text]
        set type "TEXT"
    }
    set usertype [Widget::getoption $path -dragtype]
    if { $usertype != "" } {
        set type $usertype
    }
    return [list $type {copy} $data]
}


# ------------------------------------------------------------------------------
#  Command Label::_drop_cmd
# ------------------------------------------------------------------------------
proc Label::_drop_cmd { path source X Y op type data } {
    set path [winfo parent $path]
    if {[set cmd [Widget::cget $path -dropcmd]] != ""} {
        return [uplevel \#0 $cmd [list $path $source $X $Y $op $type $data]]
    }
    if { $type == "COLOR" || $type == "FGCOLOR" } {
        configure $path -foreground $data
    } elseif { $type == "BGCOLOR" } {
        configure $path -background $data
    } else {
        set text   ""
        set image  ""
        set bitmap ""
        switch -- $type {
            IMAGE   {set image $data}
            BITMAP  {set bitmap $data}
            default {
                set text $data
                if { [set var [$path.l cget -textvariable]] != "" } {
                    configure $path -image "" -bitmap ""
                    BWidget::setglobal $var $data
                    return
                }
            }
        }
        configure $path -text $text -image $image -bitmap $bitmap
    }
    return 1
}


# ------------------------------------------------------------------------------
#  Command Label::_over_cmd
# ------------------------------------------------------------------------------
proc Label::_over_cmd { path source event X Y op type data } {
    set path [winfo parent $path]
    if { [set cmd [Widget::cget $path -dropovercmd]] != "" } {
        set opts [list $path $source $event $X $Y $op $type $data]
        return [uplevel \#0 $cmd $opts]
    }
    if {[Widget::getoption $path -state] == "normal" ||
         $type == "COLOR" || $type == "FGCOLOR" || $type == "BGCOLOR"} {
        DropSite::setcursor based_arrow_down
        return 1
    }
    DropSite::setcursor dot
    return 0
}


proc Label::_redraw { path width } {
    Widget::getVariable $path data

    ## If the width is the same as the requested width we recorded
    ## on the last redraw, this is an event caused by our redraw.
    ## We don't want to keep redrawing in a continous loop, so we'll
    ## just stop.
    if {$width == $data(width)} { return }

    if {[Widget::getoption $path -autowrap]} {
        set padx [Widget::getoption $path -wrappadx]
        $path.l configure -wraplength [expr {$width - $padx}]
    } elseif {[Widget::getoption $path -elide]} {
        set font     [$path.l cget -font]
        set text     [Widget::getoption $path -text]
        set side     [Widget::getoption $path -elideside]
        set ellipsis [Widget::getoption $path -ellipsis]

        set bd    [$path.l cget -bd]
        set padx  [$path.l cget -padx]
        set epadx [Widget::getoption $path -elidepadx]
        set width [expr {($width - (($bd + $padx) * 2)) - $epadx}]

        if {$width > 0} {
            set string $text
            while {[font measure $font $string] > $width} {
                switch -- $side {
                    "left"   {
                        set text   [string range $text 1 end]
                        set string $ellipsis$text
                    }

                    "right"  {
                        set text   [string range $text 0 end-1]
                        set string $text$ellipsis
                    }

                    "center" {
                        set x [expr {[string length $text] / 2}]
                        set l [string range $text 0 $x]
                        set r [string range $text [incr x 2] end]
                        set text   $l$r
                        set string $l$ellipsis$r
                    }
                }

                if {![string length $text]} { break }
            }

            $path.l configure -text $string
        }
    }

    set data(width) [winfo reqwidth $path.l]
}


proc Label::_trace_variable { path } {
    set varName [Widget::getoption $path -textvariable]

    if {[string length $varName]} {
        set ops     [list write unset]
        set command [list Label::_update_textvariable $path]

        uplevel #0 [list trace add variable $varName $ops $command]
    }
}


proc Label::_update_textvariable { path name1 name2 op } {
    set varName [Widget::getoption $path -textvariable]
    upvar #0 $varName var

    switch -- $op {
        "write" {
            Widget::setoption $path -text $var

            $path.l configure -text $var

            _redraw $path [winfo width $path]
        }

        "unset" {
            set var [Widget::getoption $path -text]
            _trace_variable $path
        }
    }
}


proc Label::_destroy { path } {
    set ops     [list write unset]
    set cmd     [list Label::_update_textvariable $path]
    set varName [Widget::getoption $path -textvariable]

    uplevel #0 [list trace remove variable $varName $ops $cmd]

    Widget::destroy $path
}
Added lib/BWidget/labelentry.tcl.






































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# ------------------------------------------------------------------------------
#  labelentry.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: labelentry.tcl,v 1.6 2003/10/20 21:23:52 damonc Exp $
# ------------------------------------------------------------------------------
#  Index of commands:
#     - LabelEntry::create
#     - LabelEntry::configure
#     - LabelEntry::cget
#     - LabelEntry::bind
# ------------------------------------------------------------------------------

namespace eval LabelEntry {
    Widget::define LabelEntry labelentry Entry LabelFrame

    Widget::bwinclude LabelEntry LabelFrame .labf \
        remove {-relief -borderwidth -focus} \
        rename {-text -label} \
        prefix {label -justify -width -anchor -height -font -textvariable}

    Widget::bwinclude LabelEntry Entry .e \
        remove {-fg -bg} \
        rename {-foreground -entryfg -background -entrybg}

    Widget::addmap LabelEntry "" :cmd { -background {} }

    Widget::syncoptions LabelEntry Entry .e {-text {}}
    Widget::syncoptions LabelEntry LabelFrame .labf {-label -text -underline {}}

    ::bind BwLabelEntry <FocusIn> [list focus %W.labf]
    ::bind BwLabelEntry <Destroy> [list LabelEntry::_destroy %W]
}


# ------------------------------------------------------------------------------
#  Command LabelEntry::create
# ------------------------------------------------------------------------------
proc LabelEntry::create { path args } {
    Widget::initArgs LabelEntry $args maps

    eval [list frame $path] $maps(:cmd) -class LabelEntry \
	    -relief flat -bd 0 -highlightthickness 0 -takefocus 0
    Widget::initFromODB LabelEntry $path $maps(LabelEntry)
	
    set labf  [eval [list LabelFrame::create $path.labf] $maps(.labf) \
                   [list -relief flat -borderwidth 0 -focus $path.e]]
    set subf  [LabelFrame::getframe $labf]
    set entry [eval [list Entry::create $path.e] $maps(.e)]

    pack $entry -in $subf -fill both -expand yes
    pack $labf  -fill both -expand yes

    bindtags $path [list $path BwLabelEntry [winfo toplevel $path] all]

    return [Widget::create LabelEntry $path]
}


# ------------------------------------------------------------------------------
#  Command LabelEntry::configure
# ------------------------------------------------------------------------------
proc LabelEntry::configure { path args } {
    return [Widget::configure $path $args]
}


# ------------------------------------------------------------------------------
#  Command LabelEntry::cget
# ------------------------------------------------------------------------------
proc LabelEntry::cget { path option } {
    return [Widget::cget $path $option]
}


# ------------------------------------------------------------------------------
#  Command LabelEntry::bind
# ------------------------------------------------------------------------------
proc LabelEntry::bind { path args } {
    return [eval [list ::bind $path.e] $args]
}


#------------------------------------------------------------------------------
#  Command LabelEntry::_path_command
#------------------------------------------------------------------------------
proc LabelEntry::_path_command { path cmd larg } {
    if { [string equal $cmd "configure"] ||
         [string equal $cmd "cget"] ||
         [string equal $cmd "bind"] } {
        return [eval [list LabelEntry::$cmd $path] $larg]
    } else {
        return [eval [list $path.e:cmd $cmd] $larg]
    }
}


proc LabelEntry::_destroy { path } {
    Widget::destroy $path
}
Added lib/BWidget/labelframe.tcl.






































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# ------------------------------------------------------------------------------
#  labelframe.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: labelframe.tcl,v 1.6 2003/10/20 21:23:52 damonc Exp $
# ------------------------------------------------------------------------------
#  Index of commands:
#     - LabelFrame::create
#     - LabelFrame::getframe
#     - LabelFrame::configure
#     - LabelFrame::cget
#     - LabelFrame::align
# ------------------------------------------------------------------------------

namespace eval LabelFrame {
    Widget::define LabelFrame labelframe Label

    Widget::bwinclude LabelFrame Label .l \
        remove     {
            -highlightthickness -highlightcolor -highlightbackground
            -takefocus -relief -borderwidth
            -cursor
            -dragenabled -draginitcmd -dragendcmd -dragevent -dragtype
            -dropenabled -droptypes -dropovercmd  -dropcmd} \
        initialize {-anchor w}

    Widget::declare LabelFrame {
        {-relief      TkResource flat 0 frame}
        {-borderwidth TkResource 0    0 frame}
        {-side        Enum       left 1 {left right top bottom}}
        {-bd          Synonym    -borderwidth}
    }

    Widget::addmap LabelFrame "" :cmd {-background {}}
    Widget::addmap LabelFrame "" .f   {-background {} -relief {} -borderwidth {}}

    Widget::syncoptions LabelFrame Label .l {-text {} -underline {}}

    bind BwLabelFrame <FocusIn> [list Label::setfocus %W.l]
    bind BwLabelFrame <Destroy> [list LabelFrame::_destroy %W]
}


# ----------------------------------------------------------------------------
#  Command LabelFrame::create
# ----------------------------------------------------------------------------
proc LabelFrame::create { path args } {
    Widget::initArgs LabelFrame $args maps

    eval [list frame $path] $maps(:cmd) \
        -relief flat -bd 0 -takefocus 0 -highlightthickness 0 -class LabelFrame

    Widget::init LabelFrame $path $args

    set label $path.l
    set frame $path.f

    eval [list Label::create $path.l] $maps(.l) \
           -takefocus 0 -highlightthickness 0 -relief flat \
           -borderwidth 0 -dropenabled 0 -dragenabled 0
    eval [list frame $path.f] $maps(.f) -highlightthickness 0 -takefocus 0

    switch  [Widget::getoption $path -side] {
        left   {set packopt "-side left"}
        right  {set packopt "-side right"}
        top    {set packopt "-side top -fill x"}
        bottom {set packopt "-side bottom -fill x"}
    }

    eval [list pack $label] $packopt
    pack $frame -fill both -expand yes

    bindtags $path [list $path BwLabelFrame [winfo toplevel $path] all]

    return [Widget::create LabelFrame $path]
}


# ----------------------------------------------------------------------------
#  Command LabelFrame::getframe
# ----------------------------------------------------------------------------
proc LabelFrame::getframe { path } {
    return $path.f
}


# ----------------------------------------------------------------------------
#  Command LabelFrame::configure
# ----------------------------------------------------------------------------
proc LabelFrame::configure { path args } {
    return [Widget::configure $path $args]
}


# ----------------------------------------------------------------------------
#  Command LabelFrame::cget
# ----------------------------------------------------------------------------
proc LabelFrame::cget { path option } {
    return [Widget::cget $path $option]
}


# ----------------------------------------------------------------------------
#  Command LabelFrame::align
#  This command align label of all widget given by args of class LabelFrame
#  (or "derived") by setting their width to the max one +1
# ----------------------------------------------------------------------------
proc LabelFrame::align { args } {
    set maxlen 0
    set wlist  {}
    foreach wl $args {
        foreach w $wl {
            if { ![info exists Widget::_class($w)] } {
                continue
            }
            set class $Widget::_class($w)
            if { [string equal $class "LabelFrame"] } {
                set textopt  -text
                set widthopt -width
            } else {
                upvar 0 Widget::${class}::map classmap
                set textopt  ""
                set widthopt ""
                set notdone  2
                foreach {option lmap} [array get classmap] {
                    foreach {subpath subclass realopt} $lmap {
                        if { [string equal $subclass "LabelFrame"] } {
                            if { [string equal $realopt "-text"] } {
                                set textopt $option
                                incr notdone -1
                                break
                            }
                            if { [string equal $realopt "-width"] } {
                                set widthopt $option
                                incr notdone -1
                                break
                            }
                        }
                    }
                    if { !$notdone } {
                        break
                    }
                }
                if { $notdone } {
                    continue
                }
            }
            set len [string length [$w cget $textopt]]
            if { $len > $maxlen } {
                set maxlen $len
            }
            lappend wlist $w $widthopt
        }
    }
    incr maxlen
    foreach {w widthopt} $wlist {
        $w configure $widthopt $maxlen
    }
}


proc LabelFrame::_destroy { path } {
    Widget::destroy $path
}
Added lib/BWidget/lang/de.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  de.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of german resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:   &Abbrechen
*retryName:   &Wiederholen
*ignoreName:  &Ignorieren
*okName:      &OK
*cancelName:  &Abbrechen
*yesName:     &Ja
*noName:      &Nein


! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       Fett
*italicName:     Kursiv
*underlineName:  Unterstrichen
*overstrikeName: Durchgestrichen
*fontName:       &Schriftart
*sizeName:       S&chriftgrad
*styleName:      Sc&hriftschnitt

! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    &Login
*passwordName: &Password


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:	    Schrift Auswahl
*SelectFont.sampletext:	    Beispieltext


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Meldung
*MessageDlg.infoTitle:      Hinweis
*MessageDlg.questionTitle:  Frage
*MessageDlg.warningTitle:   Warnung
*MessageDlg.errorTitle:     Fehler


! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Enter login and password
Added lib/BWidget/lang/en.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  en.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of english resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:   &Abort
*retryName:   &Retry
*ignoreName:  &Ignore
*okName:      &OK
*cancelName:  &Cancel
*yesName:     &Yes
*noName:      &No


! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       Bold
*italicName:     Italic
*underlineName:  Underline
*overstrikeName: Overstrike
*fontName:       &Font:
*sizeName:       &Size:
*styleName:      Font St&yle:


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    &Login
*passwordName: &Password


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:	    Font selection
*SelectFont.sampletext:	    Sample text


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Message
*MessageDlg.infoTitle:      Information
*MessageDlg.questionTitle:  Question
*MessageDlg.warningTitle:   Warning
*MessageDlg.errorTitle:     Error

! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Enter login and password
Added lib/BWidget/lang/es.rc.










































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
! ------------------------------------------------------------------------------
!  es.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of spanish resources
!  daniel@rawbyte.com
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:    A&bortar
*retryName:    &Reintentar
*ignoreName:   &Ignorar
*okName:       &OK
*cancelName:   &Anular
*yesName:      &Sí 
*noName:       &No

! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       &Negrita
*italicName:     &Cursiva
*underlineName:  &Subrayado
*overstrikeName: &Tachado
*fontName:       &Fuente
*sizeName:       &Tamaño
*styleName:      &Estilo


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    Nombre de &usuario
*passwordName: &Contraseña 

! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:        Selección de fuente
*SelectFont.sampletext:   Texto de Ejemplo


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Indicación
*MessageDlg.infoTitle:      Información
*MessageDlg.questionTitle:  Pregunta
*MessageDlg.warningTitle:   Atención
*MessageDlg.errorTitle:     Error


! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Introduzca su nombre de usuario y contraseña

Added lib/BWidget/lang/fr.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  fr.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of french resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:    A&bandonner
*retryName:    &Réessayer
*ignoreName:   &Ignorer
*okName:       &OK
*cancelName:   &Annuler
*yesName:      &Oui
*noName:       &Non

! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       &Gras
*italicName:     &Italique
*underlineName:  &Souligné
*overstrikeName: &Barré
*fontName:       &Police
*sizeName:       &Taille
*styleName:      St&yle


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    Nom de l'&utilisateur
*passwordName: Mot de &passe


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:        Sélection d'une police
*SelectFont.sampletext:	  Texte d'exemple


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Message
*MessageDlg.infoTitle:      Information
*MessageDlg.questionTitle:  Question
*MessageDlg.warningTitle:   Attention
*MessageDlg.errorTitle:     Erreur


! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Entrez le login et le mot de passe
Added lib/BWidget/lang/hu.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  hu.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of Hungarian resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:   &Kilép
*retryName:   &Ismétel
*ignoreName:  &Ignorál
*okName:      &OK
*cancelName:  &Kilép
*yesName:     &Igen
*noName:      &Nem


! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       Kövér
*italicName:     Dõlt
*underlineName:  Aláhúzott
*overstrikeName: Áthúzott
*fontName:       &Betûtípus
*sizeName:       B&etûméret
*styleName:      Be&tûstílus

! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    &Azonosító
*passwordName: &Jelszó


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:	    Betûtípus kiválasztása
*SelectFont.sampletext:	    Példaszöveg


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Információ
*MessageDlg.infoTitle:      Utalás
*MessageDlg.questionTitle:  Kérdés
*MessageDlg.warningTitle:   Figyelmeztetés
*MessageDlg.errorTitle:     Hiba


! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Azonosító és jelszó
Added lib/BWidget/lang/pl.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  en.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of english resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:   &Porzuć
*retryName:   P&onów
*ignoreName:  &Ignoruj
*okName:      &OK
*cancelName:  &Anyluj
*yesName:     &Tak
*noName:      &Nie


! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       Pogrubiona
*italicName:     Kursywa
*underlineName:  Podkreślenie
*overstrikeName: Przekreślenie
*fontName:       &Czcionka:
*sizeName:       &Rozmiar:
*styleName:      St&yl czcionki:


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    &Login
*passwordName: &Hasło


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:	    Wybór czcionki
*SelectFont.sampletext:	    Przykładowy tekst


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Wiadomość
*MessageDlg.infoTitle:      Informacja
*MessageDlg.questionTitle:  Pytanie
*MessageDlg.warningTitle:   Ostrzeżenie
*MessageDlg.errorTitle:     Błąd

! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Wpisz login i hasło
Added lib/BWidget/lang/pt_br.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  en.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of english resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:   &Abortar
*retryName:   &Repetir
*ignoreName:  &Ignorar
*okName:      &OK
*cancelName:  &Cancelar
*yesName:     &Sim
*noName:      &Não


! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       Negrito
*italicName:     Itálico
*underlineName:  Sublinhado
*overstrikeName: Sobreposto
*fontName:       &Fonte
*sizeName:       &Tamanho
*styleName:      Est&ilo


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    &Usuário
*passwordName: &Senha


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:	    Selecionar Fonte
*SelectFont.sampletext:	    Texto de amostra


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Mensagem
*MessageDlg.infoTitle:      Informação
*MessageDlg.questionTitle:  Questão
*MessageDlg.warningTitle:   Advertência
*MessageDlg.errorTitle:     Erro

! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Informe o usuário e a senha
Added lib/BWidget/license.txt.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
BWidget ToolKit
Copyright (c) 1998-1999 UNIFIX. 
Copyright (c) 2001-2002 ActiveState Corp. 

The following terms apply to all files associated with the software
unless explicitly disclaimed in individual files.

The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.

GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights"
in the software and related documentation as defined in the Federal 
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license. 
Added lib/BWidget/listbox.tcl.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
# ----------------------------------------------------------------------------
#  listbox.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: listbox.tcl,v 1.20 2004/04/23 17:54:29 hobbs Exp $
# ----------------------------------------------------------------------------
#  Index of commands:
#     - ListBox::create
#     - ListBox::configure
#     - ListBox::cget
#     - ListBox::insert
#     - ListBox::itemconfigure
#     - ListBox::itemcget
#     - ListBox::bindText
#     - ListBox::bindImage
#     - ListBox::delete
#     - ListBox::move
#     - ListBox::reorder
#     - ListBox::selection
#     - ListBox::exists
#     - ListBox::index
#     - ListBox::item - deprecated
#     - ListBox::items
#     - ListBox::see
#     - ListBox::edit
#     - ListBox::xview
#     - ListBox::yview
#     - ListBox::_update_edit_size
#     - ListBox::_destroy
#     - ListBox::_see
#     - ListBox::_update_scrollregion
#     - ListBox::_draw_item
#     - ListBox::_redraw_items
#     - ListBox::_redraw_selection
#     - ListBox::_redraw_listbox
#     - ListBox::_redraw_idle
#     - ListBox::_resize
#     - ListBox::_init_drag_cmd
#     - ListBox::_drop_cmd
#     - ListBox::_over_cmd
#     - ListBox::_auto_scroll
#     - ListBox::_scroll
# ----------------------------------------------------------------------------

namespace eval ListBox {
    Widget::define ListBox listbox DragSite DropSite DynamicHelp

    namespace eval Item {
        Widget::declare ListBox::Item {
            {-indent     Int        0   0 "%d >= 0"}
            {-text       String     ""  0}
            {-font       String     ""  0}
            {-foreground Color2     ""  0}
            {-image      String     ""  0}
            {-window     String     ""  0}
            {-data       String     ""  0}

            {-fg         Synonym    -foreground}
            {-fill       Synonym    -foreground}
        }
    }

    DynamicHelp::include ListBox::Item balloon

    Widget::tkinclude ListBox canvas .c \
        remove {
            -insertwidth -insertbackground -insertborderwidth -insertofftime
            -insertontime -selectborderwidth -closeenough -confine -scrollregion
            -xscrollincrement -yscrollincrement -width -height -bg -background
            -fg -foreground -selectbackground -selectforeground
        } initialize {
            -relief sunken -borderwidth 2 -takefocus 1
            -highlightthickness 0 -width 200
        }

    DragSite::include ListBox "LISTBOX_ITEM" 1
    DropSite::include ListBox {
        LISTBOX_ITEM {copy {} move {}}
    }

    Widget::declare ListBox {
        {-deltax           Int        10                        0 "%d >= 0"}
        {-deltay           Int        15                        0 "%d >= 0"}
        {-padx             Int        20                        0 "%d >= 0"}
        {-foreground       Color      "SystemButtonText"        0 listbox}
        {-background       Color      "SystemWindow"            0 listbox}
        {-selectbackground Color      "SystemHighlight"         0 listbox}
        {-selectforeground Color      "SystemHighlightText"     0 listbox}
        {-font             String     "TkTextFont"              0 listbox}
        {-width            TkResource ""                        0 listbox}
        {-height           TkResource ""                        0 listbox}
        {-redraw           Boolean    1                         0}
        {-multicolumn      Boolean    0                         0}
        {-dropovermode     Flag       "wpi"                     0 "wpi"}
	{-selectmode       Enum       none                      1
            {none single multiple}}
        {-dropcmd          String     "ListBox::_drag_and_drop" 0}
        {-autofocus        Boolean    1                         1}
        {-selectfill       Boolean    0                         1}

        {-sortargs         String     ""                        0}
        {-sortinsert       Boolean    0                         0}

        {-fg               Synonym    -foreground}
        {-bg               Synonym    -background}
    }

    bind ListBox <FocusIn>   [list after idle {BWidget::refocus %W %W.c}]
    bind ListBox <Destroy>   [list ListBox::_destroy %W]
    bind ListBox <Configure> [list ListBox::_resize  %W]
    bind ListBoxFocus <1>    [list focus %W]
    bind ListBox <Key-Up>    [list ListBox::_keyboard_navigation %W -1]
    bind ListBox <Key-Down>  [list ListBox::_keyboard_navigation %W  1]

    BWidget::bindMouseWheel ListBoxCanvas

    variable _edit
}


# ----------------------------------------------------------------------------
#  Command ListBox::create
# ----------------------------------------------------------------------------
proc ListBox::create { path args } {
    Widget::initArgs ListBox $args maps

    frame $path -class ListBox -bd 0 -highlightthickness 0 -relief flat \
        -takefocus 0

    # For 8.4+ we don't want to inherit the padding
    if {[package vsatisfies $::tk_version 8.4]} {
        $path configure -padx 0 -pady 0
    }

    Widget::initFromODB ListBox $path $maps(ListBox)

    Widget::getVariable $path data

    # widget informations
    set data(nrows) -1

    # items informations
    set data(items)    {}
    set data(anchor)   ""
    set data(selitems) {}

    # update informations
    set data(upd,level)   0
    set data(upd,afterid) ""
    set data(upd,level)   0
    set data(upd,delete)  {}

    # drag and drop informations
    set data(dnd,scroll)   ""
    set data(dnd,afterid)  ""
    set data(dnd,item)     ""

    eval [list canvas $path.c] $maps(.c) -xscrollincrement 8 \
        -background [Widget::getoption $path -background]
    pack $path.c -expand yes -fill both

    DragSite::setdrag $path $path.c ListBox::_init_drag_cmd \
	    [Widget::cget $path -dragendcmd] 1
    DropSite::setdrop $path $path.c ListBox::_over_cmd ListBox::_drop_cmd 1

    Widget::create ListBox $path

    set w  [Widget::cget $path -width]
    set h  [Widget::cget $path -height]
    set dy [Widget::cget $path -deltay]
    $path.c configure -width [expr {$w*8}] -height [expr {$h*$dy}] \
        -yscrollincrement $dy

    # Insert $path into the canvas bindings, so that anyone binding
    # directly onto the widget will see their bindings activated when
    # the canvas has focus.
    set bindtags [bindtags $path.c]
    set bindtags [linsert $bindtags 1 $path ListBoxCanvas]

    # Let any click within the canvas focus on the canvas so that
    # MouseWheel scroll events will be properly handled by the canvas.
    if {[Widget::cget $path -autofocus]} {
	lappend bindtags ListBoxFocus
    }
    bindtags $path.c $bindtags

    # Add slightly modified up/down bindings to the canvas, in case
    # it gets the focus (like with -autofocus).
    bind $path.c <Key-Up>   {ListBox::_keyboard_navigation [winfo parent %W] -1}
    bind $path.c <Key-Down> {ListBox::_keyboard_navigation [winfo parent %W] 1}

    if {![string equal [Widget::getoption $path -selectmode] "none"]} {
        set cmd ListBox::_multiple_select
        $path bindText <Button-1>          [list $cmd $path none]
        $path bindText <Shift-Button-1>    [list $cmd $path shift]
        $path bindText <Control-Button-1>  [list $cmd $path control]

        $path bindImage <Button-1>         [list $cmd $path none]
        $path bindImage <Shift-Button-1>   [list $cmd $path shift]
        $path bindImage <Control-Button-1> [list $cmd $path control]
    }

    return $path
}


# ----------------------------------------------------------------------------
#  Command ListBox::cget
# ----------------------------------------------------------------------------
proc ListBox::cget { path option } {
    return [Widget::cget $path $option]
}


# ----------------------------------------------------------------------------
#  Command ListBox::configure
# ----------------------------------------------------------------------------
proc ListBox::configure { path args } {
    set res [Widget::configure $path $args]

    set chdy [Widget::hasChanged $path -deltay dy]

    set ch1 [expr {$chdy
                   || [Widget::hasChanged $path -padx val]
                   || [Widget::hasChanged $path -font font]
                   || [Widget::hasChanged $path -multicolumn val]
                   || [Widget::hasChanged $path -foreground fg]}]

    set ch2 [expr {[Widget::hasChanged $path -selectbackground val] |
                   [Widget::hasChanged $path -selectforeground val]}]

    if {[Widget::hasChanged $path -height h]} {
        $path.c configure -height [expr {$h*$dy}]
    }

    if {[Widget::hasChanged $path -width w]} {
        $path.c configure -width [expr {$w*8}]
    }

    if {[Widget::hasChanged $path -background bg]} {
        $path.c configure -background $bg
        $path.c itemconfigure box -fill $bg
    }

    if {$chdy} {
        $path.c configure -yscrollincrement $dy
    }

    if {$ch1} {
        _redraw_idle $path 2
    } elseif {$ch2} {
        _redraw_idle $path 1
    }

    if {[Widget::hasChanged $path -redraw bool] && $bool} {
        Widget::getVariable $path data
        set lvl $data(upd,level)
        set data(upd,level) 0
        _redraw_idle $path $lvl
    }

    set force [Widget::hasChanged $path -dragendcmd dragend]
    DragSite::setdrag $path $path.c ListBox::_init_drag_cmd $dragend $force
    DropSite::setdrop $path $path.c ListBox::_over_cmd ListBox::_drop_cmd

    return $res
}


proc ListBox::activate { path index } {

}


# ----------------------------------------------------------------------------
#  Command ListBox::insert
# ----------------------------------------------------------------------------
proc ListBox::insert { path index item args } {
    Widget::getVariable $path data

    set item [Widget::nextIndex $path $item]

    if {[info exists data(item,$item)]} {
        return -code error "item \"$item\" already exists"
    }

    Widget::init ListBox::Item $path.$item $args

    if {[string equal $index "end"]} {
        lappend data(items) $item
    } else {
        set data(items) [linsert $data(items) $index $item]
    }

    set data(item,$item) 0
    set data(upd,create,$item) $item

    if {[Widget::getoption $path -sortinsert]} {
        ListBox::_sort_idle $path
    } else {
        ListBox::_redraw_idle $path 2
    }

    return $item
}

# Bastien Chevreux (bach@mwgdna.com)
# The multipleinsert command performs inserts several items at once into
#  the list. It is faster than calling insert multiple times as it uses the
#  Widget::copyinit command for initializing all items after the 1st. The 
#  speedup factor is between 2 and 3 for typical usage, but could be higher
#  for inserts with many options.
#
# Syntax: path and index are as in the insert command
#	args is a list of even numbered elements where the 1st of each pair
#	corresponds to the item of 'insert' and the second to args of 'insert'.
# ----------------------------------------------------------------------------
#  Command ListBox::multipleinsert
# ----------------------------------------------------------------------------
proc ListBox::multipleinsert { path index args } {
    Widget::getVariable $path data

    # If we got only one list as arg, take the first element as args
    # This enables callers to use 
    #	$list multipleinsert index $thelist
    # instead of
    #	eval $list multipleinsert index $thelist

    if {[llength $args] == 1} {
	set args [lindex $args 0]
    }

    set count 0
    foreach {item iargs} $args {
	if { [lsearch -exact $data(items) $item] != -1 } {
	    return -code error "item \"$item\" already exists"
	}
	
	if {$count==0} {
	    Widget::init ListBox::Item $path.$item $iargs
	    set firstpath $path.$item
	} else {
	    Widget::copyinit ListBox::Item $firstpath $path.$item $iargs
	}

	set data(items) [linsert $data(items) $index $item]
	set data(upd,create,$item) $item

	incr count
    }

    _redraw_idle $path 2
    return $item
}


# ----------------------------------------------------------------------------
#  Command ListBox::itemcget
# ----------------------------------------------------------------------------
proc ListBox::itemcget { path item option } {
    return [Widget::cget $path.$item $option]
}


# ----------------------------------------------------------------------------
#  Command ListBox::itemconfigure
# ----------------------------------------------------------------------------
proc ListBox::itemconfigure { path item args } {
    Widget::getVariable $path data

    if {![info exists data(item,$item)]} {
        return -code error "item \"$item\" does not exist"
    }

    set oldind [Widget::getoption $path.$item -indent]

    set res   [Widget::configure $path.$item $args]
    set chind [Widget::hasChanged $path.$item -indent indent]
    set chw   [Widget::hasChanged $path.$item -window win]
    set chi   [Widget::hasChanged $path.$item -image  img]
    set cht   [Widget::hasChanged $path.$item -text txt]
    set chf   [Widget::hasChanged $path.$item -font fnt]
    set chfg  [Widget::hasChanged $path.$item -foreground fg]
    set idn   [lindex $data(item,$item) 0]

    _set_help $path $item

    if {![string length $idn]} {
        ## Item is not drawn yet.
        _redraw_idle $path 2
        return $res
    }

    set oldb   [$path.c bbox $idn]
    set coords [$path.c coords $idn]
    set padx   [Widget::getoption $path -padx]
    set x0     [expr {[lindex $coords 0]-$padx-$oldind+$indent}]
    set y0     [lindex $coords 1]

    if {$chw || $chi} {
        # -window or -image modified
        set idi  [$path.c find withtag i:$item]
        set type [lindex [$path.c gettags $idi] 0]
        if { [string length $win] } {
            if { [string equal $type "win"] } {
                $path.c itemconfigure $idi -window $win
            } else {
                $path.c delete $idi
                $path.c create window $x0 $y0 -window $win -anchor w \
		    -tags [list win i:$item]
            }
        } elseif { [string length $img] } {
            if { [string equal $type "img"] } {
                $path.c itemconfigure $idi -image $img
            } else {
                $path.c delete $idi
                $path.c create image $x0 $y0 -image $img -anchor w \
		    -tags [list img i:$item]
            }
        } else {
            $path.c delete $idi
        }
    }

    if {$cht || $chf || $chfg} {
        # -text or -font modified, or -foreground modified
        set fnt [_getoption $path $item -font]
        set fg  [_getoption $path $item -foreground]
        $path.c itemconfigure $idn -text $txt -font $fnt -fill $fg
        _redraw_idle $path 1
    }

    if {$chind} {
        # -indent modified
        $path.c coords $idn [expr {$x0+$padx}] $y0
        $path.c coords i:$item $x0 $y0
        _redraw_idle $path 1
    }

    if {[Widget::getoption $path -multicolumn] && ($cht || $chf || $chind)} {
        set bbox [$path.c bbox $idn]
        if {[lindex $bbox 2] > [lindex $oldb 2]} {
            _redraw_idle $path 2
        }
    }

    return $res
}


# ----------------------------------------------------------------------------
#  Command ListBox::bindText
# ----------------------------------------------------------------------------
proc ListBox::bindText { path event script } {
    if {[string length $script]} {
        set map    [list %W $path]
        set script [string map $map $script]
	append script " \[ListBox::_get_current [list $path]\]"
    }
    $path.c bind "click" $event $script
}


# ----------------------------------------------------------------------------
#  Command ListBox::bindImage
# ----------------------------------------------------------------------------
proc ListBox::bindImage { path event script } {
    if {[string length $script]} {
        set map    [list %W $path]
        set script [string map $map $script]
	append script " \[ListBox::_get_current [list $path]\]"
    }
    $path.c bind "img" $event $script
}


# ----------------------------------------------------------------------------
#  Command ListBox::delete
# ----------------------------------------------------------------------------
proc ListBox::delete { path args } {
    Widget::getVariable $path data

    foreach litems $args {
        foreach item $litems {
            if {[set idx [lsearch -exact $data(items) $item]] != -1} {
                set data(items) [lreplace $data(items) $idx $idx]
                Widget::destroy $path.$item 0
                unset data(item,$item)
                if {[info exists data(upd,create,$item)]} {
                    unset data(upd,create,$item)
                } else {
                    lappend data(upd,delete) $item
                }
            }
        }
    }

    set sel $data(selitems)
    set data(selitems) {}
    eval [list ListBox::selection $path set] $sel
    _redraw_idle $path 2

    return
}


proc ListBox::clear { path } {
    eval [list ListBox::delete $path] [ListBox::items $path]
}


# ----------------------------------------------------------------------------
#  Command ListBox::move
# ----------------------------------------------------------------------------
proc ListBox::move { path item index } {
    Widget::getVariable $path data

    if {![info exists data(item,$item)]} {
        return -code error "item \"$item\" does not exist"
    }

    set idx [lsearch -exact $data(items) $item]
    set data(items) [linsert [lreplace $data(items) $idx $idx] $index $item]

    _redraw_idle $path 2
}


# ----------------------------------------------------------------------------
#  Command ListBox::reorder
# ----------------------------------------------------------------------------
proc ListBox::reorder { path neworder } {
    Widget::getVariable $path data

    set data(items) [BWidget::lreorder $data(items) $neworder]
    _redraw_idle $path 2
}


# ----------------------------------------------------------------------------
#  Command ListBox::selection
# ----------------------------------------------------------------------------
proc ListBox::selection { path cmd args } {
    Widget::getVariable $path data

    switch -- $cmd {
        "add" {
            foreach item $args {
                if { [lsearch -exact $data(selitems) $item] == -1 } {
                    if { [lsearch -exact $data(items) $item] != -1 } {
                        lappend data(selitems) $item
                    }
                }
            }
        }

        "clear" {
            set data(selitems) {}
        }

        "get" {
            return $data(selitems)
        }

        "includes" {
            return [expr {[lsearch -exact $data(selitems) $args] != -1}]
        }

        "range" {
            foreach {item1 item2} $args {break}

            if {![info exists data(item,$item1)]} {
                return -code error "item \"$item1\" does not exist"
            }

            if {![info exists data(item,$item2)]} {
                return -code error "item \"$item2\" does not exist"
            }

            set index1  [ListBox::index $path $item1]
            set index2  [ListBox::index $path $item2]
            set indexes [list $index1 $index2]
            if {$index1 > $index2} {
                set indexes [list $index2 $index1]
            }

            set data(selitems) [eval [list ListBox::items $path] $indexes]
        }

        "remove" {
            foreach item $args {
                if {[set idx [lsearch -exact $data(selitems) $item]] != -1} {
                    set data(selitems) [lreplace $data(selitems) $idx $idx]
                }
            }
        }

        "set" {
            set data(selitems) {}
            foreach item $args {
                if { [lsearch -exact $data(selitems) $item] == -1 } {
                    if { [lsearch -exact $data(items) $item] != -1 } {
                        lappend data(selitems) $item
                    }
                }
            }
        }

        "toggle" {
            foreach item $args {
                if {[set idx [lsearch -exact $data(selitems) $item]] != -1} {
                    set data(selitems) [lreplace $data(selitems) $idx $idx]
                } else {
                    lappend data(selitems) $item
                }
            }
        }

        default {
            return
        }
    }

    _redraw_idle $path 1
}


# ----------------------------------------------------------------------------
#  Command ListBox::exists
# ----------------------------------------------------------------------------
proc ListBox::exists { path item } {
    Widget::getVariable $path data
    return [info exists data(item,$item)]
}


# ----------------------------------------------------------------------------
#  Command ListBox::index
# ----------------------------------------------------------------------------
proc ListBox::index { path item } {
    Widget::getVariable $path data

    switch -glob -- $item {
        "active" {
            return [ListBox::selection $path get]
        }

        "end" {
            return [llength $data(items)]
        }

        "@*" {
            return [ListBox::find $path $item]
        }

        default {
            return [lsearch -exact $data(items) $item]
        }
    }
}


# ----------------------------------------------------------------------------
#  ListBox::find
#     Returns the item given a position.
#  findInfo     @x,y ?confine?
#               lineNumber
# ----------------------------------------------------------------------------
proc ListBox::find { path findInfo {confine ""} } {
    Widget::getVariable $path data

    if {[regexp -- {^@([0-9]+),([0-9]+)$} $findInfo match x y]} {
        set x [$path.c canvasx $x]
        set y [$path.c canvasy $y]
    } elseif {[regexp -- {^[0-9]+$} $findInfo lineNumber]} {
        set dy [Widget::cget $path -deltay]
        set y  [expr {$dy*($lineNumber+0.5)}]
        set confine ""
    } else {
        return -code error "invalid find spec \"$findInfo\""
    }

    set found 0
    set xi    0
    foreach xs $data(xlist) {
        if {$x <= $xs} {
            foreach id [$path.c find overlapping $xi $y $xs $y] {
                set ltags [$path.c gettags $id]
                set item  [lindex $ltags 0]
                if { [string equal $item "item"] ||
                     [string equal $item "img"]  ||
                     [string equal $item "win"] } {
                    # item is the label or image/window of the node
                    set item [string range [lindex $ltags 1] 2 end]
                    set found 1
                    break
                }
            }
            break
        }
        set  xi  $xs
    }

    if {$found} {
        if {[string equal $confine "confine"]} {
            # test if x stand inside node bbox
            set xi [expr {[lindex [$path.c coords n:$item] 0]-[Widget::getoption $path -padx]}]
            set xs [lindex [$path.c bbox n:$item] 2]
            if {$x >= $xi && $x <= $xs} {
                return $item
            }
        } else {
            return $item
        }
    }
    return ""
}


# ----------------------------------------------------------------------------
#  Command ListBox::item - deprecated
# ----------------------------------------------------------------------------
proc ListBox::item { path first {last ""} } {
    Widget::getVariable $path data

    if { ![string length $last] } {
        return [lindex $data(items) $first]
    } else {
        return [lrange $data(items) $first $last]
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::items
# ----------------------------------------------------------------------------
proc ListBox::items { path {first ""} {last ""}} {
    Widget::getVariable $path data
    if {![string length $first]} { return $data(items) }
    if {![string length $last]}  { return [lindex $data(items) $first] }
    return [lrange $data(items) $first $last]
}


# ----------------------------------------------------------------------------
#  Command ListBox::see
# ----------------------------------------------------------------------------
proc ListBox::see { path item } {
    Widget::getVariable $path data

    if {[Widget::getoption $path -redraw] && $data(upd,afterid) != ""} {
        after cancel $data(upd,afterid)
        _redraw_listbox $path
    }
    set idn [$path.c find withtag n:$item]
    if {[string length $idn]} {
        ListBox::_see $path $idn right
        ListBox::_see $path $idn left
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::edit
# ----------------------------------------------------------------------------
proc ListBox::edit { path item text {verifycmd ""} {clickres 0} {select 1}} {
    variable _edit
    Widget::getVariable $path data

    if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } {
        after cancel $data(upd,afterid)
        _redraw_listbox $path
    }
    set idn [$path.c find withtag n:$item]
    if { $idn != "" } {
        ListBox::_see $path $idn right
        ListBox::_see $path $idn left

        set oldfg  [$path.c itemcget $idn -fill]
        set sbg    [Widget::cget $path -selectbackground]
        set coords [$path.c coords $idn]
        set x      [lindex $coords 0]
        set y      [lindex $coords 1]
        set ht     [$path.c cget -highlightthickness]
        set bd     [expr {[$path.c cget -borderwidth] + $ht}]
        set w      [expr {[winfo width $path] - 2 * $bd}]
        set wmax   [expr {[$path.c canvasx $w] - $x}]

	$path.c itemconfigure $idn    -fill [Widget::cget $path -background]
        $path.c itemconfigure s:$item -fill {} -outline {}

        set _edit(text) $text
        set _edit(wait) 0

        set frame  [frame $path.edit \
                    -relief flat -borderwidth 0 -highlightthickness 0 \
                    -background [Widget::cget $path -background]]

        set ent    [entry $frame.edit \
                    -width              0     \
                    -relief             solid \
                    -borderwidth        1     \
                    -highlightthickness 0     \
                    -foreground         [_getoption $path $item -foreground] \
                    -background         [Widget::cget $path -background] \
                    -selectforeground   [Widget::cget $path -selectforeground] \
                    -selectbackground   $sbg  \
                    -font               [_getoption $path $item -font] \
                    -textvariable       ListBox::_edit(text)]
        pack $ent -ipadx 8 -anchor w

        set idw [$path.c create window $x $y -window $frame -anchor w]
        trace variable ListBox::_edit(text) w \
            [list ListBox::_update_edit_size $path $ent $idw $wmax]
        tkwait visibility $ent
        grab  $frame
        BWidget::focus set $ent
        _update_edit_size $path $ent $idw $wmax
        update

        if {$select} {
            $ent selection range 0 end
            $ent icursor end
            $ent xview end
        }

        bindtags $ent [list $ent Entry]
        bind $ent <Escape> {set ListBox::_edit(wait) 0}
        bind $ent <Return> {set ListBox::_edit(wait) 1}

	if {$clickres == 0 || $clickres == 1} {
	    bind $frame <Button>  [list set ListBox::_edit(wait) $clickres]
	}

        set ok 0
        while {!$ok} {
            tkwait variable ListBox::_edit(wait)
            if { !$_edit(wait) || [llength $verifycmd]==0 ||
                 [uplevel \#0 $verifycmd [list $_edit(text)]] } {
                set ok 1
            }
        }

        trace vdelete ListBox::_edit(text) w \
            [list ListBox::_update_edit_size $path $ent $idw $wmax]
        grab release $frame
        BWidget::focus release $ent
        destroy $frame
        $path.c delete $idw
        $path.c itemconfigure $idn    -fill $oldfg
        $path.c itemconfigure s:$item -fill $sbg -outline $sbg

        if {$_edit(wait)} {
            return $_edit(text)
        }
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::xview
# ----------------------------------------------------------------------------
proc ListBox::xview { path args } {
    return [eval [linsert $args 0 $path.c xview]]
}


# ----------------------------------------------------------------------------
#  Command ListBox::yview
# ----------------------------------------------------------------------------
proc ListBox::yview { path args } {
    return [eval [linsert $args 0 $path.c yview]]
}


proc ListBox::getcanvas { path } {
    return $path.c
}


proc ListBox::curselection { path } {
    return [$path selection get]
}


proc ListBox::sort { path } {
    Widget::getVariable $path data

    foreach item $data(items) {
        lappend list [list [Widget::getoption $path.$item -text] $item]
    }

    set data(items) [list]
    foreach pair [eval lsort [Widget::getoption $path -sortargs] [list $list]] {
        lappend data(items) [lindex $pair 1]
    }

    if {[info exists data(sort,afterid)]} {
        unset data(sort,afterid)
    }

    _redraw_idle $path 2
}


proc ListBox::_sort_idle { path } {
    Widget::getVariable $path data

    if {![info exists data(sort,afterid)]} {
        set data(sort,afterid) [after idle [list ListBox::sort $path]]
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::_update_edit_size
# ----------------------------------------------------------------------------
proc ListBox::_update_edit_size { path entry idw wmax args } {
    set entw [winfo reqwidth $entry]
    if { $entw >= $wmax } {
        $path.c itemconfigure $idw -width $wmax
    } else {
        $path.c itemconfigure $idw -width 0
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::_getoption
#     Returns the value of option for node. If empty, returned value is those
#  of the ListBox.
# ----------------------------------------------------------------------------
proc ListBox::_getoption { path item option } {
    set value [Widget::getoption $path.$item $option]
    if {![string length $value]} {
        set value [Widget::getoption $path $option]
    }
    return $value
}


# ----------------------------------------------------------------------------
#  Command ListBox::_destroy
# ----------------------------------------------------------------------------
proc ListBox::_destroy { path } {
    Widget::getVariable $path data

    if {$data(upd,afterid) != ""} {
        after cancel $data(upd,afterid)
    }

    if {$data(dnd,afterid) != ""} {
        after cancel $data(dnd,afterid)
    }

    foreach item $data(items) {
        Widget::destroy $path.$item 0
    }

    Widget::destroy $path
}


# ----------------------------------------------------------------------------
#  Command ListBox::_see
# ----------------------------------------------------------------------------
proc ListBox::_see { path idn side } {
    set bbox [$path.c bbox $idn]
    set scrl [$path.c cget -scrollregion]

    set ymax [lindex $scrl 3]
    set dy   [$path.c cget -yscrollincrement]
    set yv   [$path.c yview]
    set yv0  [expr {round([lindex $yv 0]*$ymax/$dy)}]
    set yv1  [expr {round([lindex $yv 1]*$ymax/$dy)}]
    set y    [expr {int([lindex [$path.c coords $idn] 1]/$dy)}]
    if { $y < $yv0 } {
        $path.c yview scroll [expr {$y-$yv0}] units
    } elseif { $y >= $yv1 } {
        $path.c yview scroll [expr {$y-$yv1+1}] units
    }

    set xmax [lindex $scrl 2]
    set dx   [$path.c cget -xscrollincrement]
    set xv   [$path.c xview]
    if { [string equal $side "right"] } {
        set xv1 [expr {round([lindex $xv 1]*$xmax/$dx)}]
        set x1  [expr {int([lindex $bbox 2]/$dx)}]
        if { $x1 >= $xv1 } {
            $path.c xview scroll [expr {$x1-$xv1+1}] units
        }
    } else {
        set xv0 [expr {round([lindex $xv 0]*$xmax/$dx)}]
        set x0  [expr {int([lindex $bbox 0]/$dx)}]
        if { $x0 < $xv0 } {
            $path.c xview scroll [expr {$x0-$xv0}] units
        }
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::_update_scrollregion
# ----------------------------------------------------------------------------
proc ListBox::_update_scrollregion { path } {
    set bd   [$path.c cget -borderwidth]
    set ht   [$path.c cget -highlightthickness]
    set bd   [expr {2*($bd + $ht)}]
    set w    [expr {[winfo width  $path] - $bd}]
    set h    [expr {[winfo height $path] - $bd}]
    set xinc [$path.c cget -xscrollincrement]
    set yinc [$path.c cget -yscrollincrement]
    set bbox [$path.c bbox item win img]
    if { [llength $bbox] } {
        set xs [lindex $bbox 2]
        set ys [lindex $bbox 3]

        if { $w < $xs } {
            set w [expr {int($xs)}]
            if { [set r [expr {$w % $xinc}]] } {
                set w [expr {$w+$xinc-$r}]
            }
        }
        if { $h < $ys } {
            set h [expr {int($ys)}]
            if { [set r [expr {$h % $yinc}]] } {
                set h [expr {$h+$yinc-$r}]
            }
        }
    }

    $path.c configure -scrollregion [list 0 0 $w $h]
}


proc ListBox::_update_select_fill { path } {
    Widget::getVariable $path data

    set width [winfo width $path]

    foreach item $data(items) {
        set bbox [$path.c bbox [lindex $data(item,$item) 0]]
        set bbox [list 0 [lindex $bbox 1] $width [lindex $bbox 3]]
        $path.c coords [lindex $data(item,$item) 2] $bbox
    }

    _redraw_selection $path
}


# ----------------------------------------------------------------------------
#  Command ListBox::_draw_item
# ----------------------------------------------------------------------------
proc ListBox::_draw_item {path item x0 x1 y bg selfill multi ww} {
    set indent  [Widget::getoption $path.$item -indent]
    set i [$path.c create text [expr {$x1+$indent}] $y \
        -text   [Widget::getoption $path.$item -text] \
        -fill   [_getoption        $path $item -foreground] \
        -font   [_getoption        $path $item -font] \
        -anchor w \
        -tags   [list item n:$item click]]

    lappend citems $i

    if { [set win [Widget::getoption $path.$item -window]] != "" } {
        set i [$path.c create window [expr {$x0+$indent}] $y \
            -window $win -anchor w -tags [list win i:$item]]
        lappend citems $i
    } elseif { [set img [Widget::getoption $path.$item -image]] != "" } {
        set i [$path.c create image [expr {$x0+$indent}] $y \
            -image $img -anchor w -tags [list img i:$item]]
        lappend citems $i
    } else {
        lappend citems ""
    }


    if {$selfill && !$multi} {
        set bbox  [$path.c bbox n:$item]
        set bbox  [list 0 [lindex $bbox 1] $ww [lindex $bbox 3]]
        set tags  [list box b:$item click]
        set i [$path.c create rect $bbox -fill $bg -width 0 -tags $tags]
        $path.c lower $i
        lappend citems $i
    } else {
        lappend citems ""
    }

    Widget::getVariable $path data
    set data(item,$item) $citems

    _set_help $path $item
}


# ----------------------------------------------------------------------------
#  Command ListBox::_redraw_items
# ----------------------------------------------------------------------------
proc ListBox::_redraw_items { path } {
    Widget::getVariable $path data

    set cursor [$path.c cget -cursor]
    $path.c configure -cursor watch
    update idletasks ; # make sure watch cursor is reflected

    set dx    [Widget::getoption $path -deltax]
    set dy    [Widget::cget $path -deltay]
    set padx  [Widget::getoption $path -padx]
    set y0    [expr {$dy/2}]
    set x0    4
    set x1    [expr {$x0+$padx}]
    set drawn [list]
    set nitems 0
    set data(xlist) [list]

    if {[Widget::getoption $path -multicolumn]} {
        set nrows $data(nrows)
    } else {
        set nrows [llength $data(items)]
    }

    foreach item $data(upd,delete) {
        $path.c delete i:$item n:$item s:$item b:$item
    }

    # Pass these to _draw_item so it doesn't have to request them
    # for each item.
    set bg      [Widget::cget $path -background]
    set selfill [Widget::cget $path -selectfill]
    set multi   [Widget::cget $path -multicolumn]
    set ww      [winfo width $path]
    foreach item $data(items) {
        if {[info exists data(upd,create,$item)]} {
            _draw_item $path $item $x0 $x1 $y0 $bg $selfill $multi $ww
            set nitem  [lindex $data(item,$item) 0]
            set iitem  [lindex $data(item,$item) 1]
            set bitem  [lindex $data(item,$item) 2]
            unset data(upd,create,$item)
        } else {
            set nitem  [lindex $data(item,$item) 0]
            set iitem  [lindex $data(item,$item) 1]
            set bitem  [lindex $data(item,$item) 2]
            set indent [Widget::getoption $path.$item -indent]
            $path.c coords $nitem [list [expr {$x1+$indent}] $y0]
            if {[string length $iitem]} {
                $path.c coords $iitem [list [expr {$x0+$indent}] $y0]
            }

            $path.c itemconfigure $nitem \
                -font [ListBox::_getoption $path $item -font] \
                -fill [ListBox::_getoption $path $item -foreground]
        }

        incr y0 $dy
        incr nitems
        if {$selfill} {
            lappend drawn $bitem
        } else {
            lappend drawn $nitem
        }

        if {$nitems == $nrows} {
            set y0     [expr {$dy/2}]
            set bbox   [eval [linsert $drawn 0 $path.c bbox]]
            set drawn  [list]
            set x0     [expr {[lindex $bbox 2]+$dx}]
            set x1     [expr {$x0+$padx}]
            set nitems 0
            lappend data(xlist) [lindex $bbox 2]
        }
    }

    if {$nitems && $nitems < $nrows} {
        set bbox  [eval [linsert $drawn 0 $path.c bbox]]
        lappend data(xlist) [lindex $bbox 2]
    }

    set data(upd,delete) {}
    $path.c configure -cursor $cursor
}


# ----------------------------------------------------------------------------
#  Command ListBox::_redraw_selection
# ----------------------------------------------------------------------------
proc ListBox::_redraw_selection { path } {
    Widget::getVariable $path data

    set selbg   [Widget::cget $path -selectbackground]
    set selfg   [Widget::cget $path -selectforeground]
    set selfill [Widget::getoption $path -selectfill]
    set multi   [Widget::getoption $path -multicolumn]
    foreach id [$path.c find withtag sel] {
        set item [string range [lindex [$path.c gettags $id] 1] 2 end]
        $path.c itemconfigure [lindex $data(item,$item) 0] \
            -fill [_getoption $path $item -foreground]
    }
    $path.c delete sel
    if {$selfill && !$multi} {
	# cache window width for use below
	set width [winfo width $path]
    }
    foreach item $data(selitems) {
        set nitem [lindex $data(item,$item) 0]
        set bbox [$path.c bbox $nitem]

        if {[llength $bbox]} {
	    if {$selfill && !$multi} {
		# With -selectfill, make box occupy full width of widget
		set bbox [list 0 [lindex $bbox 1] $width [lindex $bbox 3]]
	    }
            set tags [list sel s:$item click]
            set id [$path.c create rectangle $bbox \
                -fill $selbg -outline $selbg -tags $tags]
            $path.c itemconfigure $nitem -fill $selfg
            $path.c lower $id
            $path.c lower b:$item
        }
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::_redraw_listbox
# ----------------------------------------------------------------------------
proc ListBox::_redraw_listbox { path } {
    Widget::getVariable $path data

    if {[Widget::getoption $path -redraw]} {
        if {$data(upd,level) == 2} {
            _redraw_items $path
        }

        _redraw_selection $path
        _update_scrollregion $path

        if {[Widget::cget $path -selectfill]} {
            _update_select_fill $path
        }

        set data(upd,level)   0
        set data(upd,afterid) ""
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::_redraw_idle
# ----------------------------------------------------------------------------
proc ListBox::_redraw_idle { path level } {
    Widget::getVariable $path data

    if {$data(nrows) != -1} {
        # widget is realized
        if {[Widget::getoption $path -redraw] && $data(upd,afterid) == ""} {
            set data(upd,afterid) \
		[after idle [list ListBox::_redraw_listbox $path]]
        }
    }
    if {$level > $data(upd,level)} {
        set data(upd,level) $level
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::_resize
# ----------------------------------------------------------------------------
proc ListBox::_resize { path } {
    Widget::getVariable $path data

    if {[Widget::getoption $path -multicolumn]} {
        set bd    [$path.c cget -borderwidth]
        set ht    [$path.c cget -highlightthickness]
        set bd    [expr {$bd + $ht}]
        set h     [expr {[winfo height $path] - 2*$bd}]
        set nrows [expr {$h/[$path.c cget -yscrollincrement]}]
        if {$nrows == 0} {
            set nrows 1
        }

        if {$nrows != $data(nrows)} {
            set data(nrows) $nrows
            _redraw_idle $path 2
        } else {
            _update_scrollregion $path
        }
    } elseif {$data(nrows) == -1} {
        # first Configure event
        set data(nrows) 0
        ListBox::_redraw_listbox $path
        if {[Widget::cget $path -selectfill]} {
            _update_select_fill $path
        }
    } else {
        if {[Widget::cget $path -selectfill]} {
            _update_select_fill $path
        }

        _update_scrollregion $path
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::_init_drag_cmd
# ----------------------------------------------------------------------------
proc ListBox::_init_drag_cmd { path X Y top } {
    set path [winfo parent $path]
    set ltags [$path.c gettags current]
    set item  [lindex $ltags 0]
    if {[string equal $item "item"]
        || [string equal $item "img"]
        || [string equal $item "win"]} {
        set item [string range [lindex $ltags 1] 2 end]
        if {[llength [set cmd [Widget::getoption $path -draginitcmd]]]} {
            return [uplevel \#0 $cmd [list $path $item $top]]
        }
        if { [set type [Widget::getoption $path -dragtype]] == "" } {
            set type "LISTBOX_ITEM"
        }
        if { [set img [Widget::getoption $path.$item -image]] != "" } {
            pack [label $top.l -image $img -padx 0 -pady 0]
        }
        return [list $type {copy move link} $item]
    }
    return {}
}


# ----------------------------------------------------------------------------
#  Command ListBox::_drop_cmd
# ----------------------------------------------------------------------------
proc ListBox::_drop_cmd { path source X Y op type dnddata } {
    set path [winfo parent $path]
    Widget::getVariable $path data

    if { [string length $data(dnd,afterid)] } {
        after cancel $data(dnd,afterid)
        set data(dnd,afterid) ""
    }
    $path.c delete drop
    set data(dnd,scroll) ""
    if { [llength $data(dnd,item)] || ![llength $data(items)] } {
        if {[llength [set cmd [Widget::getoption $path -dropcmd]]]} {
            return [uplevel \#0 $cmd [list $path $source $data(dnd,item) $op $type $dnddata]]
        }
    }
    return 0
}


# ----------------------------------------------------------------------------
#  Command ListBox::_over_cmd
# ----------------------------------------------------------------------------
proc ListBox::_over_cmd { path source event X Y op type dnddata } {
    set path [winfo parent $path]
    Widget::getVariable $path data

    if { [string equal $event "leave"] } {
        # we leave the window listbox
        $path.c delete drop
        if { [string length $data(dnd,afterid)] } {
            after cancel $data(dnd,afterid)
            set data(dnd,afterid) ""
        }
        set data(dnd,scroll) ""
        return 0
    }

    if { [string equal $event "enter"] } {
        # we enter the window listbox - dnd data initialization
        set mode [Widget::getoption $path -dropovermode]
        set data(dnd,mode) 0
        foreach c {w p i} {
            set data(dnd,mode) [expr {($data(dnd,mode) << 1) | ([string first $c $mode] != -1)}]
        }
    }

    set x [expr {$X-[winfo rootx $path]}]
    set y [expr {$Y-[winfo rooty $path]}]
    $path.c delete drop
    set data(dnd,item) ""

    # test for auto-scroll unless mode is widget only
    if { $data(dnd,mode) != 4 && [_auto_scroll $path $x $y] != "" } {
        return 2
    }

    if { $data(dnd,mode) & 4 } {
        # dropovermode includes widget
        set target [list widget]
        set vmode  4
    } else {
        set target [list ""]
        set vmode  0
    }
    if { ($data(dnd,mode) & 2) && ![llength $data(items)] } {
        # dropovermode includes position and listbox is empty
        lappend target "" 0
        set vmode [expr {$vmode | 2}]
    }

    if { ($data(dnd,mode) & 3) && [llength $data(items)]} {
        # dropovermode includes item or position
        # we extract the box (xi,yi,xs,ys) where we can find item around x,y
        set len  [llength $data(items)]
        set xc   [$path.c canvasx $x]
        set yc   [$path.c canvasy $y]
        set dy   [$path.c cget -yscrollincrement]
        set line [expr {int($yc/$dy)}]
        set yi   [expr {$line*$dy}]
        set ys   [expr {$yi+$dy}]
        set xi   0
        set pos  $line
        if { [Widget::getoption $path -multicolumn] } {
            set nrows $data(nrows)
        } else {
            set nrows $len
        }
        if { $line < $nrows } {
            foreach xs $data(xlist) {
                if { $xc <= $xs } {
                    break
                }
                set  xi  $xs
                incr pos $nrows
            }
            if { $pos < $len } {
                set item [lindex $data(items) $pos]
                set xi   [expr {[lindex [$path.c coords n:$item] 0]-[Widget::getoption $path -padx]-1}]
                if { $data(dnd,mode) & 1 } {
                    # dropovermode includes item
                    lappend target $item
                    set vmode [expr {$vmode | 1}]
                } else {
                    lappend target ""
                }

                if { $data(dnd,mode) & 2 } {
                    # dropovermode includes position
                    if { $yc >= $yi+$dy/2 } {
                        # position is after $item
                        incr pos
                        set yl $ys
                    } else {
                        # position is before $item
                        set yl $yi
                    }
                    lappend target $pos
                    set vmode [expr {$vmode | 2}]
                } else {
                    lappend target ""
                }
            } else {
                lappend target "" ""
            }
        } else {
            lappend target "" ""
        }

        if { ($vmode & 3) == 3 } {
            # result have both item and position
            # we compute what is the preferred method
            if { $yc-$yi <= 3 || $ys-$yc <= 3 } {
                lappend target "position"
            } else {
                lappend target "item"
            }
        }
    }

    if {$vmode && [llength [set cmd [Widget::getoption $path -dropovercmd]]]} {
        # user-defined dropover command
        set res   [uplevel \#0 $cmd [list $source $target $op $type $dnddata]]
        set code  [lindex $res 0]
        set vmode 0
        if {$code & 1} {
            # update vmode
            switch -exact -- [lindex $res 1] {
                item     {set vmode 1}
                position {set vmode 2}
                widget   {set vmode 4}
            }
        }
    } else {
        if { ($vmode & 3) == 3 } {
            # result have both item and position
            # we choose the preferred method
            if { [string equal [lindex $target 3] "position"] } {
                set vmode [expr {$vmode & ~1}]
            } else {
                set vmode [expr {$vmode & ~2}]
            }
        }

        if { $data(dnd,mode) == 4 || $data(dnd,mode) == 0 } {
            # dropovermode is widget or empty - recall is not necessary
            set code 1
        } else {
            set code 3
        }
    }

    # draw dnd visual following vmode
    if {[llength $data(items)]} {
        if { $vmode & 1 } {
            set data(dnd,item) [list "item" [lindex $target 1]]
            if {[Widget::getoption $path -selectfill]} { incr xs -8 }
            $path.c create rectangle $xi $yi $xs $ys -tags drop
        } elseif { $vmode & 2 } {
            set data(dnd,item) [concat "position" [lindex $target 2]]
            $path.c create line $xi $yl $xs $yl -tags drop
        } elseif { $vmode & 4 } {
            set data(dnd,item) [list "widget"]
        } else {
            set code [expr {$code & 2}]
        }
    }

    if { $code & 1 } {
        DropSite::setcursor based_arrow_down
    } else {
        DropSite::setcursor dot
    }
    return $code
}


# ----------------------------------------------------------------------------
#  Command ListBox::_auto_scroll
# ----------------------------------------------------------------------------
proc ListBox::_auto_scroll { path x y } {
    Widget::getVariable $path data

    set xmax   [winfo width  $path]
    set ymax   [winfo height $path]
    set scroll {}
    if { $y <= 6 } {
        if { [lindex [$path.c yview] 0] > 0 } {
            set scroll [list yview -1]
            DropSite::setcursor sb_up_arrow
        }
    } elseif { $y >= $ymax-6 } {
        if { [lindex [$path.c yview] 1] < 1 } {
            set scroll [list yview 1]
            DropSite::setcursor sb_down_arrow
        }
    } elseif { $x <= 6 } {
        if { [lindex [$path.c xview] 0] > 0 } {
            set scroll [list xview -1]
            DropSite::setcursor sb_left_arrow
        }
    } elseif { $x >= $xmax-6 } {
        if { [lindex [$path.c xview] 1] < 1 } {
            set scroll [list xview 1]
            DropSite::setcursor sb_right_arrow
        }
    }

    if { [string length $data(dnd,afterid)] && ![string equal $data(dnd,scroll) $scroll] } {
        after cancel $data(dnd,afterid)
        set data(dnd,afterid) ""
    }

    set data(dnd,scroll) $scroll
    if { [llength $scroll] && ![string length $data(dnd,afterid)] } {
        set data(dnd,afterid) [after 200 [list ListBox::_scroll $path $scroll]]
    }
    return $data(dnd,afterid)

}

# -----------------------------------------------------------------------------
#  Command ListBox::_multiple_select
# -----------------------------------------------------------------------------
proc ListBox::_multiple_select { path mode item } {
    Widget::getVariable $path data

    if {![info exists data(item,$data(anchor))]} { set data(anchor) $item }

    if {[string equal [Widget::getoption $path -selectmode] "single"]} {
        set mode none
    }

    switch -exact -- $mode {
	"none" {
	    _mouse_select $path set $item
	    set data(anchor) $item
	}

	"control" {
            _mouse_select $path toggle $item
	    set data(anchor) $item
	}

	"shift" {
            _mouse_select $path range $data(anchor) $item
        }
    }
}


# ----------------------------------------------------------------------------
#  Command ListBox::_scroll
# ----------------------------------------------------------------------------
proc ListBox::_scroll { path cmd dir } {
    Widget::getVariable $path data

    if { ($dir == -1 && [lindex [$path.c $cmd] 0] > 0) ||
         ($dir == 1  && [lindex [$path.c $cmd] 1] < 1) } {
        $path $cmd scroll $dir units
        set data(dnd,afterid) \
	    [after 100 [list ListBox::_scroll $path $cmd $dir]]
    } else {
        set data(dnd,afterid) ""
        DropSite::setcursor dot
    }
}

# ListBox::_set_help --
#
#	Register dynamic help for an item in the listbox.
#
# Arguments:
#	path		ListBox to query
#	item		Item in the listbox
#       force		Optional argument to force a reset of the help
#
# Results:
#	none
proc ListBox::_set_help { path node } {
    Widget::getVariable $path help

    set item $path.$node
    set opts [list -helptype -helptext -helpvar]
    foreach {cty ctx cv} [eval [linsert $opts 0 Widget::hasChangedX $item]] break
    set text [Widget::getoption $item -helptext]

    ## If we've never set help for this item before, and text is not blank,
    ## we need to setup help.  We also need to reset help if any of the
    ## options have changed.
    if { (![info exists help($node)] && $text != "") || $cty || $ctx || $cv } {
	set help($node) 1
	set type [Widget::getoption $item -helptype]
        switch $type {
            balloon {
		DynamicHelp::register $path.c balloon n:$node $text
		DynamicHelp::register $path.c balloon i:$node $text
		DynamicHelp::register $path.c balloon b:$node $text
            }
            variable {
		set var [Widget::getoption $item -helpvar]
		DynamicHelp::register $path.c variable n:$node $var $text
		DynamicHelp::register $path.c variable i:$node $var $text
		DynamicHelp::register $path.c variable b:$node $var $text
            }
        }
    }
}

# ListBox::_mouse_select --
#
#       Handle selection commands that are done by the mouse.  If the
#       selection command returns true, we generate a <<ListboxSelect>>
#       event for the listbox.
#
# Arguments:
#       Standard arguments passed to a selection command.
#
# Results:
#	none
proc ListBox::_mouse_select { path cmd args } {
    eval [linsert $args 0 selection $path $cmd]
    switch -- $cmd {
        "add" - "clear" - "remove" - "set" - "toggle" - "range" {
            event generate $path <<ListboxSelect>>
        }
    }
}


proc ListBox::_get_current { path } {
    set t [$path.c gettags current]
    return [string range [lindex $t 1] 2 end]
}


# ListBox::_drag_and_drop --
#
#	A default command to handle drag-and-drop functions local to this
#       listbox.  With this as the default -dropcmd, the user can simply
#       enable drag-and-drop and be able to move items within this list
#       with no further code.
#
# Arguments:
#       Standard arguments passed to a dropcmd.
#
# Results:
#	none
proc ListBox::_drag_and_drop { path from endItem operation type startItem } {
    ## This proc only handles drag-and-drop commands within itself.
    ## If the widget this came from is not our widget (minus the canvas),
    ## we don't want to do anything.  They need to handle this themselves.
    if {[winfo parent $from] != $path} { return }

    set place [lindex $endItem 0]
    set i     [lindex $endItem 1]

    switch -- $place {
        "position" {
            set idx $i
        } 

        "item" {
            set idx [$path index $i]
        }

        default {
            return
        }
    }

    if {$idx > [$path index $startItem]} { incr idx -1 }

    if {[string equal $operation "copy"]} {
        set options [Widget::options $path.$startItem]
        eval [linsert $options 0 $path insert $idx $startItem\#auto]
    } else {
        $path move $startItem $idx
    }
}


proc ListBox::_keyboard_navigation { path dir } {
    Widget::getVariable $path data

    set sel [$path index [lindex [$path selection get] end]]
    if {$dir > 0} {
	incr sel
	if {$sel >= [llength $data(items)]} { return }
    } else {
	incr sel -1
	if {$sel < 0} { return }
    }
    set item [lindex $data(items) $sel]
    ListBox::see $path $item
    _mouse_select $path set $item
}
Added lib/BWidget/mainframe.tcl.
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
# ----------------------------------------------------------------------------
#  mainframe.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: mainframe.tcl,v 1.16 2004/02/04 00:11:43 hobbs Exp $
# ------------------------------------------------------------------------------
#  Index of commands:
#     - MainFrame::create
#     - MainFrame::configure
#     - MainFrame::cget
#     - MainFrame::getframe
#     - MainFrame::addtoolbar
#     - MainFrame::gettoolbar
#     - MainFrame::addindicator
#     - MainFrame::getindicator
#     - MainFrame::getmenu
#     - MainFrame::menuonly
#     - MainFrame::showtoolbar
#     - MainFrame::showstatusbar
#     - MainFrame::_create_menubar
#     - MainFrame::_create_entries
#     - MainFrame::_parse_name
#     - MainFrame::_parse_accelerator
# ----------------------------------------------------------------------------

namespace eval MainFrame {
    Widget::define MainFrame mainframe ProgressBar

    Widget::bwinclude MainFrame ProgressBar .status.prg \
	    remove {
	-fg -bg -bd -troughcolor -background -borderwidth
	-relief -orient -width -height
    } \
	    rename {
	-maximum    -progressmax
	-variable   -progressvar
	-type       -progresstype
	-foreground -progressfg
    }

    Widget::declare MainFrame {
	{-width        TkResource 0      0 frame}
	{-height       TkResource 0      0 frame}
	{-background   Color      "SystemButtonFace" 0}
	{-textvariable String     ""     0}
	{-menu         String     {}     1}
	{-separator    Enum       both   1 {none top bottom both}}
	{-bg           Synonym    -background}

	{-menubarfont   String     ""  0}
	{-menuentryfont String     ""  0}
	{-statusbarfont String     ""  0}
    }

    Widget::addmap MainFrame "" .frame  {-width {} -height {} -background {}}
    Widget::addmap MainFrame "" .topf   {-background {}}
    Widget::addmap MainFrame "" .botf   {-background {}}
    Widget::addmap MainFrame "" .status {-background {}}
    Widget::addmap MainFrame "" .status.label {-background {}}
    Widget::addmap MainFrame "" .status.indf  {-background {}}
    Widget::addmap MainFrame "" .status.prgf  {-background {}}
    Widget::addmap MainFrame ProgressBar .status.prg {-background {} -background -troughcolor}

    variable _widget
}


# ----------------------------------------------------------------------------
#  Command MainFrame::create
# ----------------------------------------------------------------------------
proc MainFrame::create { path args } {
    variable _widget

    set path [frame $path -takefocus 0 -highlightthickness 0]
    set top  [winfo parent $path]
    if {![string equal [winfo toplevel $path] $top]} {
        destroy $path
        return -code error "parent must be a toplevel"
    }
    Widget::init MainFrame $path $args

    if {[string equal $::tcl_platform(platform) "unix"]} {
        set relief raised
        set bd     1
    } else {
        set relief flat
        set bd     0
    }
    set topframe  [eval [list frame $path.topf] \
		       -relief flat -borderwidth 0 \
		       [Widget::subcget $path .topf]]
    set userframe [eval [list frame $path.frame] \
		       [Widget::subcget $path .frame] \
                       -relief $relief -borderwidth $bd]
    set botframe  [eval [list frame $path.botf] \
		       -relief $relief -borderwidth $bd \
		       [Widget::subcget $path .botf]]

    pack $topframe -fill x
    grid columnconfigure $topframe 0 -weight 1

    set bg [Widget::cget $path -background]
    $path configure -background $bg
    if {![string equal $::tcl_platform(platform) "unix"]} {
        set sepopt [Widget::getoption $path -separator]
        if { $sepopt == "both" || $sepopt == "top" } {
            set sep [Separator::create $path.sep -orient horizontal -background $bg]
            pack $sep -fill x
        }
        if { $sepopt == "both" || $sepopt == "bottom" } {
            set sep [Separator::create $botframe.sep -orient horizontal -background $bg]
            pack $sep -fill x
        }
    }

    # --- status bar ---------------------------------------------------------
    if {[string length [Widget::getoption $path -statusbarfont]] >0 } {
	set sbfnt [list -font [Widget::getoption $path -statusbarfont]]
    } else {
	set sbfnt ""
    }

    set status   [frame $path.status -relief flat -borderwidth 0 \
                      -takefocus 0 -highlightthickness 0 -background $bg]
    set label    [eval [list label $status.label \
	    -textvariable [Widget::getoption $path -textvariable] \
	    -takefocus 0 -highlightthickness 0 -background $bg] $sbfnt]
    set indframe [frame $status.indf -relief flat -borderwidth 0 \
                      -takefocus 0 -highlightthickness 0 -background $bg]
    set prgframe [frame $status.prgf -relief flat -borderwidth 0 \
                      -takefocus 0 -highlightthickness 0 -background $bg]

    place $label    -anchor w -x 0 -rely 0.5
    place $indframe -anchor ne -relx 1 -y 0 -relheight 1
    pack  $prgframe -in $indframe -side left -padx 2
    $status configure -height [winfo reqheight $label]

    set progress [eval [list ProgressBar::create $status.prg] \
		      [Widget::subcget $path .status.prg] \
                      -width       50 \
                      -height      [expr {[winfo reqheight $label]-2}] \
                      -borderwidth 1 \
                      -relief      sunken]
    pack $status    -in $botframe -fill x -pady 2
    pack $botframe  -side bottom -fill x
    pack $userframe -fill both -expand yes

    set _widget($path,top)      $top
    set _widget($path,ntoolbar) 0
    set _widget($path,nindic)   0

    set menu [Widget::getoption $path -menu]
    if { [llength $menu] } {
        _create_menubar $path $menu
    }

    bind $path <Destroy> [list MainFrame::_destroy %W]

    return [Widget::create MainFrame $path]
}


# ----------------------------------------------------------------------------
#  Command MainFrame::configure
# ----------------------------------------------------------------------------
proc MainFrame::configure { path args } {
    variable _widget

    set res [Widget::configure $path $args]

    if { [Widget::hasChanged $path -textvariable newv] } {
        uplevel \#0 $path.status.label configure -textvariable [list $newv]
    }

    if { [Widget::hasChanged $path -background bg] } {
	if {[string equal $::tcl_platform(platform) "unix"]} {
	    set listmenu [$_widget($path,top) cget -menu]
	    while { [llength $listmenu] } {
		set newlist {}
		foreach menu $listmenu {
		    $menu configure -background $bg
		    set newlist [concat $newlist [winfo children $menu]]
		}
		set listmenu $newlist
	    }
	}
        foreach sep {.sep .botf.sep} {
            if { [winfo exists $path.$sep] } {
                Separator::configure $path.$sep -background $bg
            }
        }
        foreach w [winfo children $path.topf] {
            $w configure -background $bg
        }
    }

    if { [Widget::hasChanged $path -menubarfont newmbfnt] } {
	if {[string length $newmbfnt]} {
	    set mbfnt [list -font $newmbfnt]
	} else {
	    set mbfnt ""
	}
	set top     $_widget($path,top)
	if {[string equal $top .]} {
	    eval [list .menubar configure] $mbfnt
	} else {
	    eval [list $top.menubar configure] $mbfnt
	}
    }
    if { [Widget::hasChanged $path -menuentryfont newmefnt] } {
	if {[string length $newmefnt]} {
	    set mefnt [list -font $newmefnt]
	} else {
	    set mefnt ""
	}
	set top     $_widget($path,top)
	if {[string equal $top .]} {
	    set mb .menubar
	} else {
	    set mb $top.menubar
	}
	set l [winfo children $mb]
	while {[llength $l]} {
	    set e [lindex $l 0]
	    set l [lrange $l 1 end]
	    if {[string length $e] == 0} {continue}
	    lappend l [winfo children $e]
	    eval [list $e configure] $mefnt
	}
    }


    if { [Widget::hasChanged $path -statusbarfont newsbfnt] } {
	if {[string length $newsbfnt]} {
	    set sbfnt [list -font $newsbfnt]
	} else {
	    set sbfnt ""
	}
	for {set index 0} {$index<$_widget($path,nindic)} {incr index} {
	    set indic $path.status.indf.f$index
	    eval [list $indic configure] $sbfnt
	}
	eval [list $path.status.label configure] $sbfnt
	$path.status configure -height [winfo reqheight $path.status.label]

	$path.status.prg configure \
		-height [expr {[winfo reqheight $path.status.label]-2}]
    }

    return $res
}


# ----------------------------------------------------------------------------
#  Command MainFrame::cget
# ----------------------------------------------------------------------------
proc MainFrame::cget { path option } {
    return [Widget::cget $path $option]
}


# ----------------------------------------------------------------------------
#  Command MainFrame::getframe
# ----------------------------------------------------------------------------
proc MainFrame::getframe { path } {
    return $path.frame
}


# ----------------------------------------------------------------------------
#  Command MainFrame::addtoolbar
# ----------------------------------------------------------------------------
proc MainFrame::addtoolbar { path } {
    variable _widget

    set index     $_widget($path,ntoolbar)
    set toolframe $path.topf.f$index
    set toolbar   $path.topf.tb$index
    set bg        [Widget::cget $path -background]
    if {[string equal $::tcl_platform(platform) "unix"]} {
        frame $toolframe -relief raised -borderwidth 1 \
            -takefocus 0 -highlightthickness 0 -background $bg
    } else {
        frame $toolframe -relief flat -borderwidth 0 -takefocus 0 \
            -highlightthickness 0 -background $bg
        set sep [Separator::create $toolframe.sep -orient horizontal -background $bg]
        pack $sep -fill x
    }
    set toolbar [frame $toolbar -relief flat -borderwidth 2 \
                     -takefocus 0 -highlightthickness 0 -background $bg]
    pack $toolbar -in $toolframe -anchor w -expand yes -fill x
    incr _widget($path,ntoolbar)
    grid $toolframe -column 0 -row $index -sticky ew
    return $toolbar
}


# ----------------------------------------------------------------------------
#  Command MainFrame::gettoolbar
# ----------------------------------------------------------------------------
proc MainFrame::gettoolbar { path index } {
    return $path.topf.tb$index
}


# ----------------------------------------------------------------------------
#  Command MainFrame::addindicator
# ----------------------------------------------------------------------------
proc MainFrame::addindicator { path args } {
    variable _widget

    if {[string length [Widget::getoption $path -statusbarfont]]} {
	set sbfnt [list -font [Widget::getoption $path -statusbarfont]]
    } else {
	set sbfnt ""
    }

    set index $_widget($path,nindic)
    set indic $path.status.indf.f$index
    eval [list label $indic] $args -relief sunken -borderwidth 1 \
        -takefocus 0 -highlightthickness 0 $sbfnt

    pack $indic -side left -anchor w -padx 2 -fill y -expand 1

    incr _widget($path,nindic)

    return $indic
}


# ----------------------------------------------------------------------------
#  Command MainFrame::getindicator
# ----------------------------------------------------------------------------
proc MainFrame::getindicator { path index } {
    return $path.status.indf.f$index
}


# ----------------------------------------------------------------------------
#  Command MainFrame::getmenu
# ----------------------------------------------------------------------------
proc MainFrame::getmenu { path menuid } {
    variable _widget

    if { [info exists _widget($path,menuid,$menuid)] } {
        return $_widget($path,menuid,$menuid)
    }
    return ""
}


# -----------------------------------------------------------------------------
#  Command MainFrame::setmenustate
# -----------------------------------------------------------------------------
proc MainFrame::setmenustate { path tag state } {
    variable _widget

    #    if { [info exists _widget($path,tags,$tag)] } {
    #        foreach {menu entry} $_widget($path,tags,$tag) {
    #            $menu entryconfigure $entry -state $state
    #        }
    #    }

    # We need a more sophisticated state system.
    # The original model was this:  each menu item has a list of tags;
    # whenever any one of those tags changed state, the menu item did too.
    # This makes it hard to have items that are enabled only when both tagA and
    # tagB are.  The new model therefore only sets the menustate to enabled
    # when ALL of its tags are enabled.

    # First see if this is a real tag
    if { [info exists _widget($path,tagstate,$tag)] } {
	if { ![string equal $state "disabled"] } {
	    set _widget($path,tagstate,$tag) 1
	} else {
	    set _widget($path,tagstate,$tag) 0
	}
	foreach {menu entry} $_widget($path,tags,$tag) {
	    set expression "1"
	    foreach menutag $_widget($path,menutags,[list $menu $entry]) {
		append expression " && $_widget($path,tagstate,$menutag)"
	    }
	    if { [expr $expression] } {
		set state normal
	    } else {
		set state disabled
	    }
	    $menu entryconfigure $entry -state $state
	}
    }
    return
}


# -----------------------------------------------------------------------------
#  Command MainFrame::menuonly
# ----------------------d------------------------------------------------------
proc MainFrame::menuonly { path } {
    variable _widget

    catch {pack forget $path.sep}
    catch {pack forget $path.botf.sep}
    catch {pack forget $path.frame}
}

# ----------------------------------------------------------------------------
#  Command MainFrame::showtoolbar
# ----------------------------------------------------------------------------
proc MainFrame::showtoolbar { path index bool } {
    variable _widget

    set toolframe $path.topf.f$index
    if { [winfo exists $toolframe] } {
        if { !$bool && [llength [grid info $toolframe]] } {
            grid forget $toolframe
            $path.topf configure -height 1
        } elseif { $bool && ![llength [grid info $toolframe]] } {
            grid $toolframe -column 0 -row $index -sticky ew
        }
    }
}


# ----------------------------------------------------------------------------
#  Command MainFrame::showstatusbar
# ----------------------------------------------------------------------------
proc MainFrame::showstatusbar { path name } {
    set status $path.status
    if { [string equal $name "none"] } {
        pack forget $status
    } else {
        pack $status -fill x
        switch -- $name {
            status {
                catch {pack forget $status.prg}
            }
            progression {
                pack $status.prg -in $status.prgf
            }
        }
    }
}


# ----------------------------------------------------------------------------
#  Command MainFrame::_destroy
# ----------------------------------------------------------------------------
proc MainFrame::_destroy { path } {
    variable _widget

    Widget::destroy $path
    catch {destroy [$_widget($path,top) cget -menu]}
    $_widget($path,top) configure -menu {}

    # Unset all of the state vars associated with this main frame.
    foreach index [array names _widget $path,*] {
	unset _widget($index)
    }
}


# ----------------------------------------------------------------------------
#  Command MainFrame::_create_menubar
# ----------------------------------------------------------------------------
proc MainFrame::_create_menubar { path descmenu } {
    variable _widget

    set top $_widget($path,top)

    foreach {v x} {mbfnt -menubarfont mefnt -menuentryfont} {
	if {[string length [Widget::getoption $path $x]]} {
	    set $v [list -font [Widget::getoption $path $x]]
	} else {
	    set $v ""
	}
    }

    if {[string equal $::tcl_platform(platform) "unix"]} {
	set menuopts [list -background [Widget::cget $path -background] \
			  -borderwidth 1]
    } else {
	set menuopts [list]
    }
    set menubar [eval [list menu $top.menubar -tearoff 0] $menuopts $mbfnt]
    $top configure -menu $menubar

    set count 0
    foreach {name tags menuid tearoff entries} $descmenu {
        set opt  [_parse_name $name]
        if {[string length $menuid]
	    && ![info exists _widget($path,menuid,$menuid)] } {
            # menu has identifier
	    # we use it for its pathname, to enable special menu entries
	    # (help, system, ...)
	    set menu $menubar.$menuid
        } else {
	    set menu $menubar.menu$count
	}
        eval [list $menubar add cascade] $opt [list -menu $menu]
        eval [list menu $menu -tearoff $tearoff] $menuopts $mefnt
        foreach tag $tags {
            lappend _widget($path,tags,$tag) $menubar $count
	    # ericm@scriptics:  Add a tagstate tracker
	    if { ![info exists _widget($path,tagstate,$tag)] } {
		set _widget($path,tagstate,$tag) 1
	    }
        }
	# ericm@scriptics:  Add mapping from menu items to tags
	set _widget($path,menutags,[list $menubar $count]) $tags

        if { [string length $menuid] } {
            # menu has identifier
            set _widget($path,menuid,$menuid) $menu
        }
        _create_entries $path $menu $menuopts $entries
        incr count
    }
}


# ----------------------------------------------------------------------------
#  Command MainFrame::_create_entries
# ----------------------------------------------------------------------------
proc MainFrame::_create_entries { path menu menuopts entries } {
    variable _widget

    set count      [$menu cget -tearoff]
    set registered 0
    foreach entry $entries {
        set len  [llength $entry]
        set type [lindex $entry 0]

        if { [string equal $type "separator"] } {
            $menu add separator
            incr count
            continue
        }

        # entry name and tags
        set opt  [_parse_name [lindex $entry 1]]
        set tags [lindex $entry 2]
        foreach tag $tags {
            lappend _widget($path,tags,$tag) $menu $count
	    # ericm@scriptics:  Add a tagstate tracker
	    if { ![info exists _widget($path,tagstate,$tag)] } {
		set _widget($path,tagstate,$tag) 1
	    }
        }
	# ericm@scriptics:  Add mapping from menu items to tags
	set _widget($path,menutags,[list $menu $count]) $tags

        if {[string equal $type "cascade"] || [string equal $type "cascad"]} {
            set menuid  [lindex $entry 3]
            set tearoff [lindex $entry 4]
            set submenu $menu.menu$count
            eval [list $menu add cascade] $opt [list -menu $submenu]
            eval [list menu $submenu -tearoff $tearoff] $menuopts
            if { [string length $menuid] } {
                # menu has identifier
                set _widget($path,menuid,$menuid) $submenu
            }
            _create_entries $path $submenu $menuopts [lindex $entry 5]
            incr count
            continue
        }

        # entry help description
        set desc [lindex $entry 3]
        if { [string length $desc] } {
            if { !$registered } {
                DynamicHelp::register $menu menu [Widget::getoption $path -textvariable]
                set registered 1
            }
            DynamicHelp::register $menu menuentry $count $desc
        }

        # entry accelerator
        set accel [_parse_accelerator [lindex $entry 4]]
        if { [llength $accel] } {
            lappend opt -accelerator [lindex $accel 0]
            bind $_widget($path,top) [lindex $accel 1] [list $menu invoke $count]
        }

        # user options
        set useropt [lrange $entry 5 end]
        if { [string equal $type "command"] ||
             [string equal $type "radiobutton"] ||
             [string equal $type "checkbutton"] } {
            eval [list $menu add $type] $opt $useropt
        } else {
            return -code error "invalid menu type \"$type\""
        }
        incr count
    }
}


# ----------------------------------------------------------------------------
#  Command MainFrame::_parse_name
# ----------------------------------------------------------------------------
proc MainFrame::_parse_name { menuname } {
    set idx [string first "&" $menuname]
    if { $idx == -1 } {
        return [list -label $menuname]
    } else {
        set beg [string range $menuname 0 [expr {$idx-1}]]
        set end [string range $menuname [expr {$idx+1}] end]
        append beg $end
        return [list -label $beg -underline $idx]
    }
}


# MainFrame::_parse_accelerator --
#
#	Given a key combo description, construct an appropriate human readable
#	string (for display on as a menu accelerator) and the corresponding
#	bind event.
#
# Arguments:
#	desc	a list with the following format:
#			?sequence? key
#		sequence may be None, Ctrl, Alt, or CtrlAlt
#		key may be any key
#
# Results:
#	{accel event}	a list containing the accelerator string and the event

proc MainFrame::_parse_accelerator { desc } {
    if { [llength $desc] == 1 } {
	set seq None
	set key [string tolower [lindex $desc 0]]
	# If the key is an F key (ie, F1, F2, etc), it has to be capitalized
	if {[regexp {f1?[0-9]} $key]} {
	    set key [string toupper $key]
	}
    } elseif { [llength $desc] == 2 } {
        set seq [lindex $desc 0]
        set key [string tolower [lindex $desc 1]]
	# If the key is an F key (ie, F1, F2, etc), it has to be capitalized
	if {[regexp {f1?[0-9]} $key]} {
	    set key [string toupper $key]
	}
    } else {
	return {}
    }
    switch -- $seq {
	None {
	    set accel "[string toupper $key]"
	    set event "<Key-$key>"
	}
	Ctrl {
	    set accel "Ctrl+[string toupper $key]"
	    set event "<Control-Key-$key>"
	}
	Alt {
	    set accel "Alt+[string toupper $key]"
	    set event "<Alt-Key-$key>"
	}
	CtrlAlt {
	    set accel "Ctrl+Alt+[string toupper $key]"
	    set event "<Control-Alt-Key-$key>"
	}
	default {
	    return -code error "invalid accelerator code $seq"
	}
    }
    return [list $accel $event]
}
Added lib/BWidget/messagedlg.tcl.




























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# ------------------------------------------------------------------------------
#  messagedlg.tcl
#  This file is part of Unifix BWidget Toolkit
# ------------------------------------------------------------------------------
#  Index of commands:
#     - MessageDlg::create
# ------------------------------------------------------------------------------

namespace eval MessageDlg {
    Widget::define MessageDlg messagedlg Dialog

    if {[BWidget::using ttk]} {
        Widget::tkinclude MessageDlg ttk::label .frame.msg \
            rename {
                -text -message
            } initialize {
                -anchor w -justify left
            }
    } else {
        Widget::tkinclude MessageDlg label .frame.msg \
            remove {
                -cursor -highlightthickness -relief -borderwidth -bd
                -takefocus -textvariable
            } rename {
                -text -message
            } initialize {
                -anchor w -justify left
            }
    }

    Widget::bwinclude MessageDlg Dialog :cmd \
        remove {
            -modal -image -bitmap -side -anchor -separator
            -homogeneous -padx -pady -spacing
        }

    Widget::declare MessageDlg {
        {-name       String     ""     0}
        {-icon       Enum       "info" 0 {none error info question warning}}
        {-type       Enum       "user" 0 
            {abortretryignore ok okcancel retrycancel yesno yesnocancel user}}
        {-buttons     String    ""     0}
        {-buttonwidth String    0      0}
        {-usenative   Boolean   1      0}
    }

    Widget::addmap MessageDlg "" tkMBox {
	-parent {} -message {} -default {} -title {}
    }
}


# ------------------------------------------------------------------------------
#  Command MessageDlg::create
# ------------------------------------------------------------------------------
proc MessageDlg::create { path args } {
    variable dialogs

    array set _args $args

    ## If this dialog has a name, and the user has already opted to
    ## remember the value from last time, just return the saved value.
    if {[info exists _args(-name)] && [info exists dialogs($_args(-name))]} {
        return $dialogs($_args(-name))
    }

    BWidget::LoadBWidgetIconLibrary

    set dialog "$path#Message"

    Widget::initArgs MessageDlg $args maps
    Widget::initFromODB MessageDlg $dialog $maps(MessageDlg)

    set type   [Widget::getoption $dialog -type]
    set icon   [Widget::getoption $dialog -icon]
    set width  [Widget::getoption $dialog -buttonwidth]
    set native [Widget::getoption $dialog -usenative]

    set user  0
    set defb  -1
    set canb  -1
    switch -- $type {
        abortretryignore {set lbut {abort retry ignore}; set defb 0}
        ok               {set lbut {ok}; set defb 0 }
        okcancel         {set lbut {ok cancel}; set defb 0; set canb 1}
        retrycancel      {set lbut {retry cancel}; set defb 0; set canb 1}
        yesno            {set lbut {yes no}; set defb 0; set canb 1}
        yesnocancel      {set lbut {yes no cancel}; set defb 0; set canb 2}
        user             {
            set user   1
            set native 0
            set lbut [Widget::cget $dialog -buttons]
        }
    }

    # If the user didn't specify a default button, use our type-specific
    # default, adding its flag/value to the "user" settings and to the tkMBox
    # settings
    array set dialogArgs $maps(:cmd)

    if {!$user && ![info exists dialogArgs(-default)]} {
        lappend maps(:cmd)   -default [lindex $lbut $defb]
        lappend maps(tkMBox) -default [lindex $lbut $defb]
    }

    if {![info exists dialogArgs(-cancel)]} {
        lappend maps(:cmd) -cancel $canb
    }

    # Same with title as with default
    if {![info exists dialogArgs(-title)]} {
        set frame [frame $path -class MessageDlg]
        set title [option get $frame "${icon}Title" MessageDlg]
        destroy $frame
        if {![string length $title]} {
            set title "Message"
        }
	lappend maps(:cmd) -title $title
	lappend maps(tkMBox) -title $title
    }

    set name [Widget::getoption $dialog -name]
    if {[string length $name]} { set native 0 }

    ## If the user specified a "user" dialog, or we're on UNIX, we
    ## want to create the dialog ourselves.
    if {!$native} {
        if {!$user && !$width} { set width 12 }

        set image ""
        if {![string equal $icon "none"]} {
            set image [BWidget::Icon dialog$icon]
        }

        eval [list Dialog::create $path] $maps(:cmd) \
	    [list -image $image -modal local -side bottom -anchor c]
        wm resizable $path 0 0

        bind $path <Key-Left>  [list MessageDlg::_key_traversal $path left]
        bind $path <Key-Right> [list MessageDlg::_key_traversal $path right]

        foreach but $lbut {
            Dialog::add $path -text $but -name $but -width $width
        }

        set frame [Dialog::getframe $path]

        if {[BWidget::using ttk]} {
            eval [list ttk::label $frame.msg] $maps(.frame.msg) -wraplength 800
        } else {
            eval [list label $frame.msg] $maps(.frame.msg) \
                -relief flat -bd 0 -highlightthickness 0 -wraplength 800
        }

        pack $frame.msg -fill both -expand 1 -padx {5 10} -pady {5 0}

        if {[string length $name]} {
            set msg "Don't ask me again"
            set varName [Widget::widgetVar $dialog dontAskAgain]
            if {[BWidget::using ttk]} {
                ttk::checkbutton $path.check -text $msg -variable $varName
            } else {
                checkbutton $path.check -text $msg -variable $varName
            }

            pack $path.check -anchor w -side bottom -pady {0 2}

            bind $path.bbox <Map> [list pack configure $path.bbox -pady 5]
        }

        set res [Dialog::draw $path]
        if {!$user} { set res [lindex $lbut $res] }

	destroy $path
    } else {
	array set tkMBoxArgs $maps(tkMBox)

	if {![string equal $icon "none"]} {
	    set tkMBoxArgs(-icon) $icon
	}

	if {[info exists tkMBoxArgs(-parent)]
	    && ![winfo exists $tkMBoxArgs(-parent)]} {
            unset tkMBoxArgs(-parent)
	}

	set tkMBoxArgs(-type) $type
	set res [eval tk_messageBox [array get tkMBoxArgs]]
    }

    ## If this dialog has a name, and the user checked to remember
    ## the value, store it in the dialogs array for next time.
    if {[string length $name]} {
        upvar #0 $varName var
        if {$var} { set dialogs($name) $res }
    }

    Widget::destroy $dialog

    return $res
}


proc MessageDlg::_key_traversal { path dir } {
    set but [focus -lastfor $path]
    if {$but eq $path} {
        set def [ButtonBox::index $path.bbox default]
        set but [ButtonBox::index $path.bbox $def]
        ButtonBox::configure $path.bbox -default -1
    }

    set idx [ButtonBox::index $path.bbox $but]
    set max [ButtonBox::index $path.bbox end]

    if {$dir eq "left"} { incr idx -1 }
    if {$dir eq "right"} { incr idx 1 }

    if {$idx < 0} { set idx $max }
    if {$idx > $max} { set idx 0 }

    focus [ButtonBox::buttons $path.bbox $idx]
}
Added lib/BWidget/notebook.tcl.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
# ---------------------------------------------------------------------------
#  notebook.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: notebook.tcl,v 1.20 2003/11/26 18:42:24 hobbs Exp $
# ---------------------------------------------------------------------------
#  Index of commands:
#
#   Public Commands:
#     - NoteBook::bindtabs
#     - NoteBook::cget
#     - NoteBook::compute_size
#     - NoteBook::configure
#     - NoteBook::create
#     - NoteBook::delete
#     - NoteBook::index
#     - NoteBook::insert
#     - NoteBook::itemcget
#     - NoteBook::itemconfigure
#     - NoteBook::getframe
#     - NoteBook::raise
#     - NoteBook::see
#     - NoteBook::page
#     - NoteBook::pages
#
#   Private Commands:
#     - NoteBook::_compute_width
#     - NoteBook::_draw_area
#     - NoteBook::_draw_arrows
#     - NoteBook::_draw_page
#     - NoteBook::_get_x_page
#     - NoteBook::_highlight
#     - NoteBook::_itemconfigure
#     - NoteBook::_redraw
#     - NoteBook::_resize
#     - NoteBook::_select
#     - NoteBook::_test_page
#     - NoteBook::_xview
# ---------------------------------------------------------------------------

namespace eval NoteBook {
    Widget::define NoteBook notebook ArrowButton DynamicHelp

    namespace eval Page {
        Widget::declare NoteBook::Page {
            {-anchor             Enum       "w"      0
                {center e n ne nw s se sw s w}}
            {-ipadx              Padding    "8 4"    0 "%d > -1"}
            {-ipady              Int        "2 6"    0 "%d > -1"}
            {-imagepad           Int        "2"      0 "%d > -1"}
            {-container          Boolean    "0"      1}
            {-state              Enum       "normal" 0 {normal disabled}}
            {-createcmd          String     ""       0}
            {-raisecmd           String     ""       0}
            {-leavecmd           String     ""       0}
            {-image              String     ""       0}
            {-text               String     ""       0}
            {-drawtab            Boolean    "1"      0}
            {-foreground         String     ""       0}
            {-background         String     ""       0}
            {-activeforeground   String     ""       0}
            {-activebackground   String     ""       0}
            {-disabledforeground String     ""       0}
        }
    }

    DynamicHelp::include NoteBook::Page balloon

    Widget::bwinclude NoteBook ArrowButton .c.fg \
	    include {-foreground -background -activeforeground \
		-activebackground -disabledforeground -repeatinterval \
		-repeatdelay -borderwidth} \
	    initialize {-borderwidth 1}

    Widget::bwinclude NoteBook ArrowButton .c.fd \
	    include {-foreground -background -activeforeground \
		-activebackground -disabledforeground -repeatinterval \
		-repeatdelay -borderwidth} \
	    initialize {-borderwidth 1}

    if {[BWidget::using ttk]} {
        Widget::tkinclude NoteBook ttk::frame :cmd \
            remove { -class -background -width -height }
    } else {
        Widget::tkinclude NoteBook frame :cmd \
            remove { -class -colormap -visual -background -width -height }
    }

    Widget::declare NoteBook {
        {-background		Color      "SystemButtonFace"       0}
	{-foreground		Color      "SystemButtonText"       0}
        {-activebackground	Color      "SystemButtonFace"       0}
        {-activeforeground	Color      "SystemButtonText"       0}
        {-disabledforeground	Color      "SystemDisabledText"     0}
        {-font			String     "TkTextFont"             0}
        {-side			Enum       top      0 {top bottom}}
        {-homogeneous		Boolean    0        0}
 	{-internalborderwidth	Int        10       0 "%d >= 0"}
        {-width			Int        0        0 "%d >= 0"}
        {-height		Int        0        0 "%d >= 0"}
        {-state                 Enum       "normal" 0 {normal disabled}}
        {-repeatdelay           BwResource ""       0 ArrowButton}
        {-repeatinterval        BwResource ""       0 ArrowButton}
	{-arcradius             Int        2        0 "%d >= 0 && %d <= 8"}
	{-tabbevelsize          Int        0        0 "%d >= 0 && %d <= 8"}

        {-fg                    Synonym    -foreground}
        {-bg                    Synonym    -background}
        {-bd                    Synonym    -borderwidth}
        {-ibd                   Synonym    -internalborderwidth}
    }

    Widget::addmap NoteBook "" .c { -background {} }

    variable _warrow 12

    bind NoteBook <Configure> [list NoteBook::_resize  %W]
    bind NoteBook <Destroy>   [list NoteBook::_destroy %W]
}


# ---------------------------------------------------------------------------
#  Command NoteBook::create
# ---------------------------------------------------------------------------
proc NoteBook::create { path args } {
    Widget::initArgs NoteBook $args maps

    if {[BWidget::using ttk]} {
        eval [list ttk::frame $path -class NoteBook] $maps(:cmd)
    } else {
        eval [list frame $path -class NoteBook] $maps(:cmd)
    }

    Widget::initFromODB NoteBook $path $maps(NoteBook)

    Widget::getVariable $path data

    array set data {
        cpt      0
        base     0
        pages    {}
        wpage    0
        select   ""
        realized 0
    }

    _compute_height $path

    ## Create the canvas.
    eval [list canvas $path.c] $maps(.c) -highlightthickness 0
    pack $path.c -expand yes -fill both

    # Removing the Canvas global bindings from our canvas as
    # application specific bindings on that tag may interfere with its
    # operation here. [SF item #459033]
    bindtags $path.c [BWidget::lremove [bindtags $path.c] Canvas]

    ## Create the arrow buttons.
    eval [list ArrowButton::create $path.c.fg] $maps(.c.fg) \
	    [list -highlightthickness 0 -type button -dir left \
	    -armcommand [list NoteBook::_xview $path -1]]

    eval [list ArrowButton::create $path.c.fd] $maps(.c.fd) \
	    [list -highlightthickness 0 -type button -dir right \
	    -armcommand [list NoteBook::_xview $path 1]]

    Widget::create NoteBook $path

    set bg [$path.c cget -background]
    foreach {data(dbg) data(lbg)} [BWidget::get3dcolor $path $bg] {break}

    return $path
}


# ---------------------------------------------------------------------------
#  Command NoteBook::configure
# ---------------------------------------------------------------------------
proc NoteBook::configure { path args } {
    Widget::getVariable $path data

    set res    [Widget::configure $path $args]
    set redraw 0

    set opts [list -font -homogeneous]
    BWidget::lassign [eval [list Widget::hasChangedX $path] $opts] cf ch
    if {$cf || $ch} {
        if {$cf} {
            _compute_height $path
        }
        _compute_width $path
        set redraw 1
    }

    set chbg  [Widget::hasChanged $path -background bg]
    set chibd [Widget::hasChanged $path -internalborderwidth ibd]
    if {$chibd || $chbg} {
        foreach page $data(pages) {
            $path.f$page configure -borderwidth $ibd -background $bg
        }
    }

    if {$chbg} {
        set col [BWidget::get3dcolor $path $bg]
        set data(dbg)  [lindex $col 0]
        set data(lbg)  [lindex $col 1]
        set redraw 1
    }

    set wc [Widget::hasChanged $path -width  w]
    set hc [Widget::hasChanged $path -height h]
    if {$wc || $hc} {
        $path.c configure \
            -width  [expr {$w + 4}] \
            -height [expr {$h + $data(hpage) + 4}]
    }

    if {[Widget::hasChanged $path -state state]} {
        set redraw 1
        foreach page $data(pages) {
            _itemconfigure $path $page [list -state $state]
        }
    }

    set list [list -foreground -borderwidth -arcradius -tabbevelsize -side]
    if {[eval [list Widget::anyChangedX $path] $list]} { set redraw 1 }

    if {$redraw} {
        _redraw $path
    }

    return $res
}


# ---------------------------------------------------------------------------
#  Command NoteBook::cget
# ---------------------------------------------------------------------------
proc NoteBook::cget { path option } {
    return [Widget::cget $path $option]
}


# ---------------------------------------------------------------------------
#  Command NoteBook::compute_size
# ---------------------------------------------------------------------------
proc NoteBook::compute_size { path } {
    Widget::getVariable $path data

    set wmax 0
    set hmax 0
    update idletasks
    foreach page $data(pages) {
        set w    [winfo reqwidth  $path.f$page]
        set h    [winfo reqheight $path.f$page]
        set wmax [expr {$w>$wmax ? $w : $wmax}]
        set hmax [expr {$h>$hmax ? $h : $hmax}]
    }
    configure $path -width $wmax -height $hmax
    # Sven... well ok so this is called twice in some cases...
    NoteBook::_redraw $path
    # Sven end
}


# ---------------------------------------------------------------------------
#  Command NoteBook::insert
# ---------------------------------------------------------------------------
proc NoteBook::insert { path index page args } {
    Widget::getVariable $path data

    set page [Widget::nextIndex $path $page]

    if {[exists $path $page]} {
        return -code error "page \"$page\" already exists"
    }

    set f $path.f$page
    Widget::init NoteBook::Page $f $args

    set data(pages) [linsert $data(pages) $index $page]
    # If the page doesn't exist, create it; if it does reset its bg and ibd
    if { ![winfo exists $f] } {
        frame $f \
	    -relief      flat \
            -container   [Widget::cget $f -container] \
	    -background  [$path.c cget -background] \
	    -borderwidth [Widget::cget $path -internalborderwidth]
        set data($page,realized) 0
    } else {
	$f configure \
	    -background  [$path.c cget -background] \
	    -borderwidth [Widget::cget $path -internalborderwidth]
    }
    _compute_height $path
    _compute_width  $path
    _draw_page $path $page 1
    _set_help  $path $page
    _redraw $path

    return $f
}


# ---------------------------------------------------------------------------
#  Command NoteBook::delete
# ---------------------------------------------------------------------------
proc NoteBook::delete { path page {destroyframe 1} } {
    Widget::getVariable $path data

    set pos [_test_page $path $page]
    set data(pages) [lreplace $data(pages) $pos $pos]
    _compute_width $path
    $path.c delete p:$page
    if { $data(select) == $page } {
        set data(select) ""
    }
    if { $pos < $data(base) } {
        incr data(base) -1
    }
    if { $destroyframe } {
        destroy $path.f$page
    }
    _redraw $path
}


proc NoteBook::exists { path page } {
    return [expr [index $path $page] != -1]
}


# ---------------------------------------------------------------------------
#  Command NoteBook::itemconfigure
# ---------------------------------------------------------------------------
proc NoteBook::itemconfigure { path page args } {
    _test_page $path $page

    set res [_itemconfigure $path $page $args]

    _set_help $path $page

    _redraw $path

    return $res
}


# ---------------------------------------------------------------------------
#  Command NoteBook::itemcget
# ---------------------------------------------------------------------------
proc NoteBook::itemcget { path page option } {
    _test_page $path $page
    return [Widget::cget $path.f$page $option]
}


# ---------------------------------------------------------------------------
#  Command NoteBook::bindtabs
# ---------------------------------------------------------------------------
proc NoteBook::bindtabs { path event script } {
    if { $script != "" } {
	append script " \[NoteBook::_get_page_name [list $path] current 2\]"
        $path.c bind "page" $event $script
    } else {
        $path.c bind "page" $event {}
    }
}


# ---------------------------------------------------------------------------
#  Command NoteBook::move
# ---------------------------------------------------------------------------
proc NoteBook::move { path page index } {
    Widget::getVariable $path data

    set pos [_test_page $path $page]
    set data(pages) [linsert [lreplace $data(pages) $pos $pos] $index $page]
    _redraw $path
}


# ---------------------------------------------------------------------------
#  Command NoteBook::raise
# ---------------------------------------------------------------------------
proc NoteBook::raise { path {page ""} } {
    Widget::getVariable $path data

    if { $page != "" } {
        _test_page $path $page
        _select $path $page
    }
    return $data(select)
}


proc NoteBook::clear { path } {
    Widget::getVariable $path data

    set data(select) ""
    _redraw $path
}


# ---------------------------------------------------------------------------
#  Command NoteBook::see
# ---------------------------------------------------------------------------
proc NoteBook::see { path page } {
    Widget::getVariable $path data

    set pos [_test_page $path $page]
    if { $pos < $data(base) } {
        set data(base) $pos
        _redraw $path
    } else {
        set w     [expr {[winfo width $path]-1}]
        set fpage [expr {[_get_x_page $path $pos] + $data($page,width) + 6}]
        set idx   $data(base)
        while { $idx < $pos && $fpage > $w } {
            set fpage [expr {$fpage - $data([lindex $data(pages) $idx],width)}]
            incr idx
        }
        if { $idx != $data(base) } {
            set data(base) $idx
            _redraw $path
        }
    }
}


# ---------------------------------------------------------------------------
#  Command NoteBook::page
# ---------------------------------------------------------------------------
proc NoteBook::page { path first {last ""} } {
    Widget::getVariable $path data

    if { $last == "" } {
        return [lindex $data(pages) $first]
    } else {
        return [lrange $data(pages) $first $last]
    }
}


# ---------------------------------------------------------------------------
#  Command NoteBook::pages
# ---------------------------------------------------------------------------
proc NoteBook::pages { path {first ""} {last ""}} {
    Widget::getVariable $path data

    if { ![string length $first] } {
	return $data(pages)
    }

    if { ![string length $last] } {
        return [lindex $data(pages) $first]
    } else {
        return [lrange $data(pages) $first $last]
    }
}


# ---------------------------------------------------------------------------
#  Command NoteBook::index
# ---------------------------------------------------------------------------
proc NoteBook::index { path page } {
    Widget::getVariable $path data
    return [lsearch -exact $data(pages) $page]
}


# ---------------------------------------------------------------------------
#  Command NoteBook::getframe
# ---------------------------------------------------------------------------
proc NoteBook::getframe { path page } {
    return $path.f$page
}


# ---------------------------------------------------------------------------
#  Command NoteBook::_test_page
# ---------------------------------------------------------------------------
proc NoteBook::_test_page { path page } {
    Widget::getVariable $path data

    if { [set pos [lsearch -exact $data(pages) $page]] == -1 } {
        return -code error "page \"$page\" does not exists"
    }
    return $pos
}

proc NoteBook::_getoption { path page option } {
    set value [Widget::cget $path.f$page $option]
    if {![string length $value]} {
        set value [Widget::cget $path $option]
    }
    return $value
}

# ---------------------------------------------------------------------------
#  Command NoteBook::_itemconfigure
# ---------------------------------------------------------------------------
proc NoteBook::_itemconfigure { path page lres } {
    Widget::getVariable $path data

    set res [Widget::configure $path.f$page $lres]
    if {[Widget::hasChanged $path.f$page -text text]} {
        _compute_width $path
    } elseif {[Widget::hasChanged $path.f$page -image image]} {
        _compute_height $path
        _compute_width  $path
    }

    if {[Widget::hasChanged $path.f$page -anchor anchor]} {
        _draw_page $path $page 0
    }

    if {[Widget::getoption $path.f$page -drawtab]
        && [Widget::hasChanged $path.f$page -state state]
        && [string equal $state "disabled"]
        && [string equal $data(select) $page]} {
        set data(select) ""
    }

    return $res
}


# ---------------------------------------------------------------------------
#  Command NoteBook::_compute_width
# ---------------------------------------------------------------------------
proc NoteBook::_compute_width { path } {
    Widget::getVariable $path data

    set wmax 0
    set wtot 0
    set hmax $data(hpage)
    set font [Widget::cget $path -font]
    if {![info exists data(textid)]} {
        set data(textid) [$path.c create text 0 -100 -font $font -anchor nw]
    }
    set id $data(textid)
    $path.c itemconfigure $id -font $font
    foreach page $data(pages) {
        set frame $path.f$page
        set data($page,width) 0
        if {![Widget::getoption $frame -drawtab]} { continue }
        $path.c itemconfigure $id -text [Widget::getoption $frame -text]

	# Get the bbox for this text to determine its width, then substract
	# 6 from the width to account for canvas bbox oddness w.r.t. widths of
	# simple text.
	foreach {x1 y1 x2 y2} [$path.c bbox $id] break

        set data($page,textwidth)  [expr {$x2 - $x1 - 2}]
        set data($page,itemwidth)  $data($page,textwidth)
        set data($page,itemheight) [expr {$y2 - $y1 - 2}]

	set x2 [expr {$x2 - 6}]
        set wtext [expr {$x2 - $x1 + 20}]
        if { [set img [Widget::cget $path.f$page -image]] != "" } {
            set imgw [image width  $img]
            set imgh [image height $img]
            incr data($page,itemwidth) $imgw
            incr data($page,itemwidth) [Widget::getoption $frame -imagepad]
            set wtext [expr {$wtext + $imgw + 4}]
            set himg  [expr {$imgh + 6}]
            if { $himg > $hmax } {
                set hmax $himg
            }

            if {$imgh > $data($page,itemheight)} {
                set data($page,itemheight) $imgh
            }
        }
        set  wmax  [expr {$wtext > $wmax ? $wtext : $wmax}]
        incr wtot  $wtext
        set  data($page,width) $wtext
    }

    if {[Widget::cget $path -homogeneous]} {
        foreach page $data(pages) {
            if {![Widget::cget $path.f$page -drawtab]} { continue }
            set data($page,width) $wmax
        }
        set wtot [expr {$wmax * [llength $data(pages)]}]
    }

    set data(hpage) $hmax
    set data(wpage) $wtot
}


# ---------------------------------------------------------------------------
#  Command NoteBook::_compute_height
# ---------------------------------------------------------------------------
proc NoteBook::_compute_height { path } {
    Widget::getVariable $path data

    set font    [Widget::cget $path -font]
    set metrics [font metrics $font -linespace]
    set imgh    0
    set padh    0
    set lines   1
    foreach page $data(pages) {
        set frame $path.f$page
        set img   [Widget::cget $frame -image]
        set text  [Widget::cget $frame -text]
        set len   [llength [split $text \n]]
        set pady0 [Widget::_get_padding $frame -ipady 0]
        set pady1 [Widget::_get_padding $frame -ipady 1]
        set padding [expr {$pady0 + $pady1}]
        if {$len > $lines} { set lines $len}
        if {[string length $img]} {
            set h [image height $img]
            if {$h > $imgh} { set imgh $h }
        }

        if {$padding > $padh} { set padh $padding }
    }
    set height [expr {$metrics * $lines}]
    if {$imgh > $height} { set height $imgh }
    set data(hpage) [expr {$height + $padh}]
}


# ---------------------------------------------------------------------------
#  Command NoteBook::_get_x_page
# ---------------------------------------------------------------------------
proc NoteBook::_get_x_page { path pos } {
    Widget::getVariable $path data

    set base $data(base)
    # notebook tabs start flush with the left side of the notebook
    set x 0
    if { $pos < $base } {
        foreach page [lrange $data(pages) $pos [expr {$base-1}]] {
            if {![Widget::cget $path.f$page -drawtab]} { continue }
            incr x [expr {-$data($page,width)}]
        }
    } elseif { $pos > $base } {
        foreach page [lrange $data(pages) $base [expr {$pos-1}]] {
            if {![Widget::cget $path.f$page -drawtab]} { continue }
            incr x $data($page,width)
        }
    }
    return $x
}


# ---------------------------------------------------------------------------
#  Command NoteBook::_xview
# ---------------------------------------------------------------------------
proc NoteBook::_xview { path inc } {
    Widget::getVariable $path data

    if { $inc == -1 } {
        set base [expr {$data(base)-1}]
        set dx $data([lindex $data(pages) $base],width)
    } else {
        set dx [expr {-$data([lindex $data(pages) $data(base)],width)}]
        set base [expr {$data(base)+1}]
    }

    if { $base >= 0 && $base < [llength $data(pages)] } {
        set data(base) $base
        $path.c move page $dx 0
        _draw_area   $path
        _draw_arrows $path
    }
}


# ---------------------------------------------------------------------------
#  Command NoteBook::_highlight
# ---------------------------------------------------------------------------
proc NoteBook::_highlight { type path page } {
    Widget::getVariable $path data

    if { [string equal [Widget::cget $path.f$page -state] "disabled"] } {
        return
    }

    switch -- $type {
        on {
            $path.c itemconfigure "$page:poly" \
		    -fill [_getoption $path $page -activebackground]
            $path.c itemconfigure "$page:text" \
		    -fill [_getoption $path $page -activeforeground]
        }
        off {
            $path.c itemconfigure "$page:poly" \
		    -fill [_getoption $path $page -background]
            $path.c itemconfigure "$page:text" \
		    -fill [_getoption $path $page -foreground]
        }
    }
}


# ---------------------------------------------------------------------------
#  Command NoteBook::_select
# ---------------------------------------------------------------------------
proc NoteBook::_select { path page } {
    Widget::getVariable $path data

    set draw  [Widget::cget $path.f$page -drawtab]
    set state [Widget::cget $path.f$page -state]

    ## If we want to draw the tab for this page and the state is
    ## not normal, we can't select it.  Pages with no tab can
    ## still be raised by the code even in a disabled state
    ## because they are often used to display a page of data
    ## while the rest of the notebook is disabled.
    if {$draw && ![string equal $state "normal"] } { return }

    set oldsel $data(select)

    if {[string equal $page $oldsel]} { return }

    if { ![string equal $oldsel ""] } {
	set cmd [Widget::cget $path.f$oldsel -leavecmd]
	if { ![string equal $cmd ""] } {
	    set code [catch {uplevel \#0 $cmd} res]
	    if { $code == 1 || $res == 0 } {
		return -code $code $res
	    }
	}
	set data(select) ""
	_draw_page $path $oldsel 0
    }

    set data(select) $page
    if { ![string equal $page ""] } {
	if { !$data($page,realized) } {
	    set data($page,realized) 1
	    set cmd [Widget::cget $path.f$page -createcmd]
	    if { ![string equal $cmd ""] } {
		uplevel \#0 $cmd
	    }
	}
	set cmd [Widget::cget $path.f$page -raisecmd]
	if { ![string equal $cmd ""] } {
	    uplevel \#0 $cmd
	}
	_draw_page $path $page 0
    }

    _draw_area $path
}


# -----------------------------------------------------------------------------
#  Command NoteBook::_redraw
# -----------------------------------------------------------------------------
proc NoteBook::_redraw { path } {
    Widget::getVariable $path data

    if { !$data(realized) } { return }

    _compute_height $path

    foreach page $data(pages) {
        _draw_page $path $page 0
    }
    _draw_area   $path
    _draw_arrows $path
}


# ----------------------------------------------------------------------------
#  Command NoteBook::_draw_page
# ----------------------------------------------------------------------------
proc NoteBook::_draw_page { path page create } {
    Widget::getVariable $path data

    set frame $path.f$page

    if {![Widget::cget $frame -drawtab]} { return }

    # --- calcul des coordonnees et des couleurs de l'onglet ------------------
    set pos [lsearch -exact $data(pages) $page]
    set bg  [_getoption $path $page -background]

    # lookup the tab colors
    set fgt   $data(lbg)
    set fgb   $data(dbg)

    set h   $data(hpage)
    set xd  [_get_x_page $path $pos]
    set xf  [expr {$xd + $data($page,width)}]

    foreach {textx texty textanchor imagex imagey imageanchor} \
        [_get_tab_positions $path $page] {break}

    # Coordinates of the tab corners are:
    #     c3        c4
    #
    # c2                c5
    #
    # c1                c6
    #
    # where
    # c1 = $xd,	  $h
    # c2 = $xd+$xBevel,	           $arcRadius+2
    # c3 = $xd+$xBevel+$arcRadius, $arcRadius
    # c4 = $xf+1-$xBevel,          $arcRadius
    # c5 = $xf+$arcRadius-$xBevel, $arcRadius+2
    # c6 = $xf+$arcRadius,         $h

    set top       2
    set xBevel    [Widget::getoption $path -tabbevelsize]
    set arcRadius [Widget::getoption $path -arcradius]

    # Precompute some coord values that we use a lot
    set topPlusRadius	[expr {$top + $arcRadius}]
    set rightPlusRadius	[expr {$xf + $arcRadius}]
    set leftPlusRadius	[expr {$xd + $arcRadius}]

    # Sven
    set tabsOnBottom [string equal [Widget::getoption $path -side] "bottom"]

    set h1 [expr {[winfo height $path]}]
    set bd [Widget::cget $path -borderwidth]
    if {$bd < 1} { set bd 1 }

    if { $tabsOnBottom } {
	set top [expr {$top * -1}]
	set topPlusRadius [expr {$topPlusRadius * -1}]
	# Hrm... the canvas has an issue with drawing diagonal segments
	# of lines from the bottom to the top, so we have to draw this line
	# backwards (ie, lt is actually the bottom, drawn from right to left)
        set lt  [list \
		$rightPlusRadius			[expr {$h1-$h-1}] \
		[expr {$rightPlusRadius - $xBevel}]	[expr {$h1 + $topPlusRadius}] \
		[expr {$xf - $xBevel}]			[expr {$h1 + $top}] \
		[expr {$leftPlusRadius + $xBevel}]	[expr {$h1 + $top}] \
		]
        set lb  [list \
		[expr {$leftPlusRadius + $xBevel}]	[expr {$h1 + $top}] \
		[expr {$xd + $xBevel}]			[expr {$h1 + $topPlusRadius}] \
		$xd					[expr {$h1-$h-1}] \
		]
	# Because we have to do this funky reverse order thing, we have to
	# swap the top/bottom colors too.
	set tmp $fgt
	set fgt $fgb
	set fgb $tmp
    } else {
	set lt [list \
		$xd					$h \
		[expr {$xd + $xBevel}]			$topPlusRadius \
		[expr {$leftPlusRadius + $xBevel}]	$top \
		[expr {$xf + 1 - $xBevel}]		$top \
		]
	set lb [list \
		[expr {$xf + 1 - $xBevel}] 		[expr {$top + 1}] \
		[expr {$rightPlusRadius - $xBevel}]	$topPlusRadius \
		$rightPlusRadius			$h \
		]
    }

    set img [Widget::cget $path.f$page -image]

    if {[string equal $data(select) $page]} {
        set bd    [Widget::cget $path -borderwidth]
	if {$bd < 1} { set bd 1 }
        set fg    [_getoption $path $page -foreground]
    } else {
        set bd    1
        if { [Widget::cget $path.f$page -state] == "normal" } {
            set fg [_getoption $path $page -foreground]
        } else {
            set fg [_getoption $path $page -disabledforeground]
        }
    }

    # --- creation ou modification de l'onglet --------------------------------
    # Sven
    if { $create } {
	# Create the tab region
        eval [list $path.c create polygon] [concat $lt $lb] [list \
		-tags		[list page p:$page $page:poly] \
		-outline	$bg \
		-fill		$bg \
		]
        eval [list $path.c create line] $lt [list \
            -tags [list page p:$page $page:top top] -fill $fgt -width $bd]
        eval [list $path.c create line] $lb [list \
            -tags [list page p:$page $page:bot bot] -fill $fgb -width $bd]
        $path.c create text $textx $texty 			\
		-text	[Widget::cget $path.f$page -text]	\
		-font	[Widget::cget $path -font]		\
		-fill	$fg					\
		-anchor	$textanchor					\
		-tags	[list page p:$page $page:text]

        $path.c bind p:$page <ButtonPress-1> \
		[list NoteBook::_select $path $page]
        $path.c bind p:$page <Enter> \
		[list NoteBook::_highlight on  $path $page]
        $path.c bind p:$page <Leave> \
		[list NoteBook::_highlight off $path $page]
    } else {
        $path.c coords "$page:text" $textx $texty

        $path.c itemconfigure "$page:text" \
            -text [Widget::cget $path.f$page -text] \
            -font [Widget::cget $path -font] \
            -fill $fg -anchor $textanchor
    }
    eval [list $path.c coords "$page:poly"] [concat $lt $lb]
    eval [list $path.c coords "$page:top"]  $lt
    eval [list $path.c coords "$page:bot"]  $lb
    $path.c itemconfigure "$page:poly" -fill $bg  -outline $bg
    $path.c itemconfigure "$page:top"  -fill $fgt -width $bd
    $path.c itemconfigure "$page:bot"  -fill $fgb -width $bd
    
    # Sven end

    if {[string length $img]} {
        # Sven
	set id [$path.c find withtag $page:img]
        if {![string length $id]} {
	    set id [$path.c create image $imagex $imagey \
		    -anchor $imageanchor    \
		    -tags   [list page p:$page $page:img]]
        }
        $path.c coords $id $imagex $imagey
        $path.c itemconfigure $id -image $img -anchor $imageanchor
        # Sven end
    } else {
        $path.c delete $page:img
    }

    if {[string equal $data(select) $page]} {
        $path.c raise p:$page
    } elseif { $pos == 0 } {
        if { $data(select) == "" } {
            $path.c raise p:$page
        } else {
            $path.c lower p:$page p:$data(select)
        }
    } else {
        set pred [lindex $data(pages) [expr {$pos-1}]]
        if { $data(select) != $pred || $pos == 1 } {
            $path.c lower p:$page p:$pred
        } else {
            $path.c lower p:$page p:[lindex $data(pages) [expr {$pos-2}]]
        }
    }
}


# -----------------------------------------------------------------------------
#  Command NoteBook::_draw_arrows
# -----------------------------------------------------------------------------
proc NoteBook::_draw_arrows { path } {
    variable _warrow
    Widget::getVariable $path data

    set w       [expr {[winfo width $path]-1}]
    set h       [expr {$data(hpage)-1}]
    set nbpages [llength $data(pages)]
    set xl      0
    set xr      [expr {$w-$_warrow+1}]
    # Sven
    set side [Widget::cget $path -side]
    if { [string equal $side "bottom"] } {
        set h1 [expr {[winfo height $path]-1}]
        set bd [Widget::cget $path -borderwidth]
	if {$bd < 1} { set bd 1 }
        set y0 [expr {$h1 - $data(hpage) + $bd}]
    } else {
        set y0 1
    }
    # Sven end (all y positions where replaced with $y0 later)

    if { $data(base) > 0 } {
        # Sven 
        if { ![llength [$path.c find withtag "leftarrow"]] } {
            $path.c create window $xl $y0 \
                -width  $_warrow            \
                -height $h                  \
                -anchor nw                  \
                -window $path.c.fg            \
                -tags   "leftarrow"
        } else {
            $path.c coords "leftarrow" $xl $y0
            $path.c itemconfigure "leftarrow" -width $_warrow -height $h
        }
        # Sven end
    } else {
        $path.c delete "leftarrow"
    }

    if { $data(base) < $nbpages-1 &&
         $data(wpage) + [_get_x_page $path 0] + 6 > $w } {
        # Sven
        if { ![llength [$path.c find withtag "rightarrow"]] } {
            $path.c create window $xr $y0 \
                -width  $_warrow            \
                -height $h                  \
                -window $path.c.fd            \
                -anchor nw                  \
                -tags   "rightarrow"
        } else {
            $path.c coords "rightarrow" $xr $y0
            $path.c itemconfigure "rightarrow" -width $_warrow -height $h
        }
        # Sven end
    } else {
        $path.c delete "rightarrow"
    }
}


# -----------------------------------------------------------------------------
#  Command NoteBook::_draw_area
# -----------------------------------------------------------------------------
proc NoteBook::_draw_area { path } {
    Widget::getVariable $path data

    set w   [expr {[winfo width  $path] - 1}]
    set h   [expr {[winfo height $path] - 1}]
    set bd  [Widget::cget $path -borderwidth]
    if {$bd < 1} { set bd 1 }
    set x0  [expr {$bd - 1}]

    set arcRadius [Widget::cget $path -arcradius]

    set side [Widget::cget $path -side]

    if {[string equal $side "bottom"]} {
        set y0 0
        set y1 [expr {$h - $data(hpage)}]
        set yo $y1
    } else {
        set y0 $data(hpage)
        set y1 $h
        set yo [expr {$h-$y0}]
    }

    set dbg $data(dbg)
    set sel $data(select)

    if {$sel == ""} {
        set xd  [expr {$w/2}]
        set xf  $xd
        set lbg $data(dbg)
    } else {
        set xd [_get_x_page $path [lsearch -exact $data(pages) $sel]]
        set xf [expr {$xd + $data($sel,width) + $arcRadius + 1}]
        set lbg $data(lbg)
    }

    if { [llength [$path.c find withtag rect]] == 0} {
        $path.c create line $xd $y0 $x0 $y0 $x0 $y1 \
            -tags "rect toprect1" 
        $path.c create line $w $y0 $xf $y0 \
            -tags "rect toprect2"
        $path.c create line 1 $h $w $h $w $y0 \
            -tags "rect botrect"
    }

    if {[string equal $side "bottom"]} {
        $path.c coords "toprect1" $w $y0 $x0 $y0 $x0 $y1
        $path.c coords "toprect2" $x0 $y1 $xd $y1
        $path.c coords "botrect"  $xf $y1 $w $y1 $w $y0
        $path.c itemconfigure "toprect1" -fill $lbg -width $bd
        $path.c itemconfigure "toprect2" -fill $dbg -width $bd
        $path.c itemconfigure "botrect" -fill $dbg -width $bd
    } else {
        $path.c coords "toprect1" $xd $y0 $x0 $y0 $x0 $y1
        $path.c coords "toprect2" $w $y0 $xf $y0
        $path.c coords "botrect"  $x0 $h $w $h $w $y0
        $path.c itemconfigure "toprect1" -fill $lbg -width $bd
        $path.c itemconfigure "toprect2" -fill $lbg -width $bd
        $path.c itemconfigure "botrect" -fill $dbg -width $bd
    }

    $path.c raise "rect"

    if { $sel != "" } {
        if { [llength [$path.c find withtag "window"]] == 0 } {
            $path.c create window 2 [expr {$y0+1}] \
                -width  [expr {$w-3}]           \
                -height [expr {$yo-3}]          \
                -anchor nw                      \
                -tags   "window"                \
                -window $path.f$sel
        }
        $path.c coords "window" 2 [expr {$y0+1}]
        $path.c itemconfigure "window"    \
            -width  [expr {$w-3}]           \
            -height [expr {$yo-3}]          \
            -window $path.f$sel
    } else {
        $path.c delete "window"
    }
}


# -----------------------------------------------------------------------------
#  Command NoteBook::_resize
# -----------------------------------------------------------------------------
proc NoteBook::_resize { path } {
    Widget::getVariable $path data

    if {!$data(realized)} {
	if { [set width  [Widget::cget $path -width]]  == 0 ||
	     [set height [Widget::cget $path -height]] == 0 } {
	    compute_size $path
	}
	set data(realized) 1
    }

    NoteBook::_redraw $path
}


# Tree::_set_help --
#
#	Register dynamic help for a node in the tree.
#
# Arguments:
#	path		Tree to query
#	node		Node in the tree
#       force		Optional argument to force a reset of the help
#
# Results:
#	none
proc NoteBook::_set_help { path page } {
    Widget::getVariable $path help

    set item $path.f$page
    set change [Widget::anyChangedX $item -helptype -helptext -helpvar]
    set text   [Widget::getoption $item -helptext]

    ## If we've never set help for this item before, and text is not blank,
    ## we need to setup help.  We also need to reset help if any of the
    ## options have changed.
    if { (![info exists help($page)] && $text != "") || $change } {
	set help($page) 1
	set type [Widget::getoption $item -helptype]
        switch $type {
            balloon {
		DynamicHelp::register $path.c balloon p:$page $text
            }
            variable {
		set var [Widget::getoption $item -helpvar]
		DynamicHelp::register $path.c variable p:$page $var $text
            }
        }
    }
}


proc NoteBook::_get_page_name { path {item current} {tagindex end-1} } {
    return [string range [lindex [$path.c gettags $item] $tagindex] 2 end]
}


proc NoteBook::_get_tab_positions { path page } {
    Widget::getVariable $path data

    set frame $path.f$page

    set image     [Widget::getoption $frame -image]
    set anchor    [Widget::getoption $frame -anchor]
    set haveimage [string length $image]

    set top     2
    set pady    [Widget::_get_padding $frame -ipady 0]
    set padx    [Widget::_get_padding $frame -ipadx 0]
    set imgpad  [Widget::_get_padding $frame -imagepad 0]
    set pos     [lsearch -exact $data(pages) $page]
    set offset  [_get_x_page $path $pos]
    set width   $data($page,width)
    set height  $data(hpage)
    set cheight [winfo height $path]

    set textx  [expr {($width / 2) + $offset}]
    set texty  [expr {($height / 2) + $pady}]
    set texta  $anchor
    set imagex $textx
    set imagey $texty
    set imagea $texta

    if {$haveimage} { set iwidth [image width $image] }

    if {[string match "n*" $anchor]} {
        set texty  [expr {$top + $pady + ($data($page,itemheight) / 2)}]
        set imagey $texty
    } elseif {[string match "s*" $anchor]} {
        set texty  [expr {$height - ($data($page,itemheight) / 2) - $pady}]
        incr texty $top
        set imagey $texty
    }

    if {[string match "*e" $anchor]} {
        set texta  e
        set imagea e

        set pad   [Widget::_get_padding $frame -ipadx 1]
        set textx [expr {$width - $pad}]
        if {$haveimage} {
            set imagex [expr {$textx - $data($page,textwidth) - $imgpad}]
        }
    } elseif {[string match "*w" $anchor]} {
        set texta  w
        set imagea w

        set textx [expr {$offset + $padx}]
        if {$haveimage} {
            set imagex $textx
            incr textx [expr {$iwidth + $imgpad}]
        }
    } elseif {$haveimage} {
        set x [expr {($width - $data($page,textwidth) - $iwidth) / 2}]
        set textx  [expr {$x + $iwidth + $imgpad}]
        set imagex $x
        set texta  w
        set imagea w
    }

    if {[string equal [Widget::getoption $path -side] "bottom"]} {
	incr texty  [expr {$cheight - $height}]
        incr imagey [expr {$cheight - $height}]
    }

    if {[string equal $data(select) $page]} {
	# The selected page's text is raised higher than the others
        incr texty  -2
        incr imagey -2
    }

    return [list $textx $texty $texta $imagex $imagey $imagea]
}


# ---------------------------------------------------------------------------
#  Command NoteBook::_destroy
# ---------------------------------------------------------------------------
proc NoteBook::_destroy { path } {
    Widget::getVariable $path data

    foreach page $data(pages) {
        Widget::destroy $path.f$page 0
    }

    Widget::destroy $path
}
Added lib/BWidget/optiontree.tcl.


































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
# ----------------------------------------------------------------------------
#  optiontree.tcl
#  $Id$
# ----------------------------------------------------------------------------
#  Index of commands:
# ----------------------------------------------------------------------------

namespace eval OptionTree {
    Widget::define OptionTree optiontree Tree

    namespace eval Node {
        Widget::declare OptionTree::Node {
            {-type              Enum      "none"  1
                {checkbutton none radiobutton}}
            {-command            String    ""      0}
            {-variable           String    ""      0}
            
            {-on                 Boolean   "0"     0}
            {-value              String    ""      0}
            {-onvalue            String    ""      0}
            {-offvalue           String    ""      0}

            {-state              Enum      "normal" 0 {disabled normal}}
            {-disabledforeground Color     "SystemDisabledText" 0}
        }
    }

    Widget::declare OptionTree {
        {-command             String       ""   0}
        {-toggleselect        Boolean      1    1}

        {-radioimage          String       ""   1}
        {-radioselectimage    String       ""   1}

        {-checkimage          String       ""   1}
        {-checkselectimage    String       ""   1}
    }

    bind OptionTree <Destroy> [list OptionTree::_destroy %W]
}


proc OptionTree::create { path args } {
    set opath $path#opttree

    array set maps [list Tree {} .c {} OptionTree {}]
    array set maps [Widget::splitArgs $args Tree OptionTree]

    eval [list Tree::create $path -bg #FFFFFF -showlines 0] $maps(Tree)
    eval [list $path.c configure] $maps(.c)

    Widget::initFromODB OptionTree $opath $maps(OptionTree)

    if {![string length [Widget::getoption $opath -radioimage]]} {
        Widget::setoption $opath -radioimage [BWidget::Icon radio-off]
    }

    if {![string length [Widget::getoption $opath -radioselectimage]]} {
        Widget::setoption $opath -radioselectimage [BWidget::Icon radio-on]
    }

    if {![string length [Widget::getoption $opath -checkimage]]} {
        Widget::setoption $opath -checkimage [BWidget::Icon check-off]
    }

    if {![string length [Widget::getoption $opath -checkselectimage]]} {
        Widget::setoption $opath -checkselectimage [BWidget::Icon check-on]
    }

    set opts [list]
    
    ## Figure out the dimensions of our images and setup
    ## the tree's defaults.  If the user passes in these
    ## options, they will be overridden.
    set image  [Widget::getoption $opath -checkimage]
    set width  [image width $image]
    set height [image height $image]
    lappend opts -padx [expr {$width + 4}]
    lappend opts -deltax $width -deltay [expr {$height + 4}]

    eval [list Tree::configure $path] $opts $maps(Tree)

    bindtags $path [list $path OptionTree Tree [winfo toplevel $path] all]

    set toggle [Widget::getoption $opath -toggleselect]

    $path bindText  <Button-1> [list OptionTree::_select $path $toggle]
    $path bindText  <Double-1> [list OptionTree::_select $path 1]
    $path bindImage <Button-1> [list OptionTree::_select $path 1]
    $path bindImage <Double-1> [list OptionTree::_select $path 1]

    set c [$path getcanvas]
    bind $c <Key-space> [list OptionTree::_select $path 1]

    proc ::$path { cmd args } \
    	"return \[OptionTree::_path_command [list $path] \$cmd \$args\]"

    return $path
}


proc OptionTree::cget { path option } {
    if {[string match "*#opttree" $path]} {
        set opath $path
    } else {
        set opath $path#opttree
    }

    if {[Widget::optionExists Tree $option]} {
        return [Tree::cget $path $option]
    } else {
        return [Widget::cget $opath $option]
    }
}


proc OptionTree::clear { path } {
    eval [list OptionTree::delete $path] [Tree::nodes $path root]
}


proc OptionTree::configure { path args } {
    set opath $path#opttree

    if {![llength $args]} {
        set res [Tree::configure $path]
        eval lappend res [Widget::configure $opath $args]
        return [lsort $res]
    }

    if {[llength $args] == 1} {
        if {[Widget::optionExists Tree $args]} {
            return [Tree::configure $path $args]
        } else {
            return [Widget::configure $opath $args]
        }
    }

    array set maps [list Tree {} .c {} OptionTree {}]
    array set maps [Widget::splitArgs $args Tree OptionTree]

    if {[llength $maps(Tree)] || [llength $maps(.c)]} {
        eval [list Tree::configure $path] $maps(Tree) $maps(.c)
    }

    if {[llength $maps(OptionTree)]} {
        Widget::configure $opath $maps(OptionTree)
    }
}


proc OptionTree::delete { path args } {
    Widget::getVariable $path traces
    Widget::getVariable $path variables

    foreach node $args {
        eval [list OptionTree::delete $path] [$path nodes $node]

        Widget::destroy $path.$node#opttree 0

        if {![info exists variables($node)]} { continue }

        set varName $variables($node)
        set command [list OptionTree::_redraw_node $path $node 0]
        uplevel #0 [list trace remove variable $varName write $command]

        if {[set idx [lsearch -exact $traces($varName) $node]] > -1} {
            set traces($varName) [lreplace $traces($varName) $idx $idx]
        }
    }

    eval [list Tree::delete $path] $args
}


proc OptionTree::insert { path index parent node args } {
    array set maps [Widget::splitArgs $args OptionTree::Node Tree::Node]

    set deltax [Widget::getoption $path -deltax]
    if {[string equal $parent "root"]} {
        set deltax 0
    } else {
        ## If this item is going into a parent node that has
        ## a deltax of 0 but has opted to draw a cross, we need
        ## to adjust the deltax to make room for the cross.
        set dx [Widget::getoption $path.$parent -deltax]
        set dc [Widget::getoption $path.$parent -drawcross]
        if {$dx == 0 && $dc ne "never"} {
            Tree::itemconfigure $path $parent -deltax 10
        }
    }

    set args [concat -deltax $deltax $maps(Tree::Node)]
    set node [eval [list Tree::insert $path $index $parent $node] $args]

    set onode $path.$node#opttree
    Widget::init OptionTree::Node $onode $maps(OptionTree::Node)

    ## If this item has no type, and it has no image, and
    ## the user didn't pass us a -padx, set the default
    ## -padx to 4 pixels.  Items without images look too
    ## spaced in the OptionTree due to every other item
    ## always having an image.
    set type [Widget::getoption $onode -type]
    array set tmp $maps(Tree::Node)
    if {[string equal $type "none"] && ![info exists tmp(-padx)]
        && ![string length [Tree::itemcget $path $node -image]]} {
        Tree::itemconfigure $path $node -padx 4
    }

    OptionTree::_set_variable $path $node
    OptionTree::_redraw_node  $path $node 0

    return $node
}


proc OptionTree::itemcget { path node option } {
    set onode $path.$node#opttree

    if {[Widget::optionExists OptionTree::Node $option]} {
        return [Widget::getoption $onode $option]
    } else {
        return [Tree::itemcget $path $node $option]
    }
}


proc OptionTree::itemconfigure { path node args } {
    set onode $path.$node#opttree

    if {![llength $args]} {
        set res [Tree::itemconfigure $path $node]
        eval lappend res [Widget::configure $onode $args]
        return [lsort $res]
    }

    if {[llength $args] == 1} {
        if {[Widget::optionExists Tree::Node $args]} {
            return [Tree::itemconfigure $path $node $args]
        } else {
            return [Widget::configure $onode $args]
        }
    }

    array set maps [Widget::splitArgs $args OptionTree::Node Tree::Node]

    if {[info exists maps(Tree::Node)]} {
        eval [list Tree::itemconfigure $path $node] $maps(Tree::Node)
    }

    set oldVarName [Widget::getoption $onode -variable]

    if {[info exists maps(OptionTree::Node)]} {
        Widget::configure $onode $maps(OptionTree::Node)
    }

    set redraw 0

    if {[Widget::hasChanged $onode -variable varName]} {
        Widget::getVariable $path traces
        if {[string length $oldVarName]} {
            set idx [lsearch -exact $traces($oldVarName) $node]
            set traces($oldVarName) [lreplace $traces($oldVarName) $idx $idx]

            set command [list OptionTree::_redraw_node $path $node 0]
            uplevel #0 [list trace remove variable $oldVarName write $command]
        }

        OptionTree::_set_variable $path $node

        set redraw 1
    }

    if {[Widget::anyChangedX $onode -on -value -onvalue -offvalue -state]} {
        set redraw 1
    }

    if {$redraw} { _redraw_node $path $node 1 }
}


proc OptionTree::toggle { path node {force 0} } {
    set onode $path.$node#opttree

    if {$force || [Widget::getoption $onode -state] ne "disabled"} {
        if {[Widget::getoption $onode -on]} {
            OptionTree::itemconfigure $path $node -on 0
        } else {
            OptionTree::itemconfigure $path $node -on 1
        }

        event generate $path <<TreeModify>>
    }
}


proc OptionTree::_path_command { path cmd larg } {
    if {[string length [info commands ::OptionTree::$cmd]]} {
        return [eval [linsert $larg 0 OptionTree::$cmd $path]]
    } else {
        return [eval [linsert $larg 0 Tree::$cmd $path]]
    }
}


proc OptionTree::_select { path toggle {node ""} } {
    if {$node eq ""} { set node [$path selection get] }

    set opath $path#opttree
    set onode $path.$node#opttree

    $path selection set $node

    if {[Widget::getoption $onode -state] ne "disabled" && $toggle} {
        OptionTree::toggle $path $node
        set cmd [Widget::cgetOption -command "" $onode $opath]
        OptionTree::_eval_command $path $node $cmd
    }

    event generate $path <<TreeSelect>>
}


proc OptionTree::_eval_command { path node command } {
    if {[string length $command]} {
        set onode   $path.$node#opttree
        set parent  [Tree::parent $path $node]
        set varName [Widget::getoption $onode -variable]
        set map     [list %W $path %p $parent %n $node %v $varName]

        uplevel #0 [string map $map $command]
    }
}


proc OptionTree::_set_variable { path node } {
    Widget::getVariable $path traces
    Widget::getVariable $path variables

    set onode $path.$node#opttree

    set varName [Widget::getoption $onode -variable]
    if {![string length $varName]} { return }

    set variables($node) $varName
    lappend traces($varName) $node

    set command [list OptionTree::_redraw_node $path $node 0]
    uplevel #0 [list trace add variable $varName write $command]
}


proc OptionTree::_redraw_node { path node force args } {
    set opath $path#opttree
    set onode $path.$node#opttree

    set varName [Widget::getoption $onode -variable]

    set opts [list]

    if {[Widget::getoption $onode -state] eq "disabled"} {
        lappend opts -fill [Widget::getoption $onode -disabledforeground]
    }

    switch -- [Widget::getoption $onode -type] {
        "checkbutton" {
            set on [Widget::getoption $onode -on]

            if {[string length $varName]} {
                upvar #0 $varName var

                set onvalue  [Widget::getoption $onode -onvalue]
                set offvalue [Widget::getoption $onode -offvalue]

                if {$force || ![info exists var]} {
                    if {$onvalue  eq ""} { set onvalue  1 }
                    if {$offvalue eq ""} { set offvalue 0 }
                    if {$on} {
                        set var $onvalue
                    } else {
                        set var $offvalue
                    }
                } else {
                    if {$offvalue eq "" && [string is false -strict $var]} {
                        set on 0
                    } elseif {$onvalue eq "" && [string is true -strict $var]} {
                        set on 1
                    } elseif {$var == $onvalue} {
                        set on 1
                    } else {
                        set on 0
                    }
                }
            }

            if {$on} {
                set image [Widget::getoption $opath -checkselectimage]
            } else {
                set image [Widget::getoption $opath -checkimage]
            }

            Widget::setoption $onode -on $on
            lappend opts -image $image
        }

        "radiobutton" {
            ## If no variable exists, the radiobutton always appears on.
            set on 1
            set image [Widget::getoption $opath -radioselectimage]

            if {[string length $varName]} {
                upvar #0 $varName var

                set value [Widget::getoption $onode -value]

                if {$force} { set var $value }

                ## If the radiobuton's variable does not exist,
                ## it stays on until it does.
                if {[info exists var] && $var != $value} {
                    set on 0
                    set image [Widget::getoption $opath -radioimage]
                }
            }

            Widget::setoption $onode -on $on
            lappend opts -image $image
        }
    }

    eval [list Tree::itemconfigure $path $node] $opts
}


proc OptionTree::_destroy { path } {
    Widget::getVariable $path traces

    OptionTree::delete $path root

    foreach varName [array names traces] {
        foreach node $traces($varName) {
            set command [list OptionTree::_redraw_node $path $node 0]
            uplevel #0 [list trace remove variable $varName write $command]
        }
    }

    Widget::destroy $path#opttree
}
Added lib/BWidget/pagesmgr.tcl.














































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# ------------------------------------------------------------------------------
#  pagesmgr.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: pagesmgr.tcl,v 1.6 2003/10/20 21:23:52 damonc Exp $
# ------------------------------------------------------------------------------
#  Index of commands:
#
#   Public Command
#     - PagesManager::add
#     - PagesManager::cget
#     - PagesManager::create
#     - PagesManager::compute_size
#     - PagesManager::configure
#     - PagesManager::delete
#     - PagesManager::getframe
#     - PagesManager::page
#     - PagesManager::pages
#     - PagesManager::raise
#
#   Private Commands
#     - PagesManager::_test_page
# ------------------------------------------------------------------------------

namespace eval PagesManager {
    Widget::define PagesManager pagesmgr

    Widget::tkinclude PagesManager frame :cmd \
        remove { -class -colormap -container -visual }
}


# ------------------------------------------------------------------------------
#  Command PagesManager::create
# ------------------------------------------------------------------------------
proc PagesManager::create { path args } {
    Widget::initArgs PagesManager $args maps

    eval [list frame $path] $maps(:cmd) -class PagesManager

    Widget::initFromODB PagesManager $path $maps(PagesManager)

    Widget::getVariable $path data

    set data(pages)  [list]
    set data(select) ""

    grid rowconfigure    $path 0 -weight 1
    grid columnconfigure $path 0 -weight 1

    return [Widget::create PagesManager $path]
}


# ------------------------------------------------------------------------------
#  Command PagesManager::configure
# ------------------------------------------------------------------------------
proc PagesManager::configure { path args } {
    return [Widget::configure $path $args]
}


# ------------------------------------------------------------------------------
#  Command PagesManager::cget
# ------------------------------------------------------------------------------
proc PagesManager::cget { path option } {
    return [Widget::cget $path $option]
}


proc PagesManager::itemcget { path page option } {
    _test_page $path $page
    return [$path.f$page cget $option]
}


proc PagesManager::itemconfigure { path page args } {
    _test_page $path $page
    return [eval [list $path.f$page configure] $args]
}


# ------------------------------------------------------------------------------
#  Command PagesManager::compute_size
# ------------------------------------------------------------------------------
proc PagesManager::compute_size { path } {
    Widget::getVariable $path data

    set wmax 0
    set hmax 0
    update idletasks
    foreach page $data(pages) {
        set w    [winfo reqwidth  $path.f$page]
        set h    [winfo reqheight $path.f$page]
        set wmax [expr {$w>$wmax ? $w : $wmax}]
        set hmax [expr {$h>$hmax ? $h : $hmax}]
    }
    configure $path -width $wmax -height $hmax
}


# ------------------------------------------------------------------------------
#  Command PagesManager::add
# ------------------------------------------------------------------------------
proc PagesManager::add { path page } {
    Widget::getVariable $path data

    set page [Widget::nextIndex $path $page]

    if {[exists $path $page]} {
        return -code error "page \"$page\" already exists"
    }

    lappend data(pages) $page

    frame $path.f$page -relief flat \
	    -background [Widget::cget $path -background] -borderwidth 0

    return $path.f$page
}


# ------------------------------------------------------------------------------
#  Command PagesManager::delete
# ------------------------------------------------------------------------------
proc PagesManager::delete { path page } {
    Widget::getVariable $path data

    set pos [_test_page $path $page]
    set data(pages) [lreplace $data(pages) $pos $pos]
    if {[string equal $data(select) $page]} {
        set data(select) ""
    }
    destroy $path.f$page
}


# ------------------------------------------------------------------------------
#  Command PagesManager::raise
# ------------------------------------------------------------------------------
proc PagesManager::raise { path {page ""} } {
    Widget::getVariable $path data

    if {![string equal $page ""]} {
        _test_page $path $page

        if {![string equal $page $data(select)]} {
            if {![string equal $data(select) ""]} {
                grid forget [getframe $path $data(select)]
            }
            grid [getframe $path $page] -row 0 -column 0 -sticky news
            set data(select) $page
        }
    }
    return $data(select)
}


# ------------------------------------------------------------------------------
#  Command PagesManager::page - deprecated, use pages
# ------------------------------------------------------------------------------
proc PagesManager::page { path first {last ""} } {
    Widget::getVariable $path data

    if { $last == "" } {
        return [lindex $data(pages) $first]
    } else {
        return [lrange $data(pages) $first $last]
    }
}


# ------------------------------------------------------------------------------
#  Command PagesManager::pages
# ------------------------------------------------------------------------------
proc PagesManager::pages { path {first ""} {last ""} } {
    Widget::getVariable $path data

    if { ![string length $first] } {
	return $data(pages)
    }

    if { ![string length $last] } {
        return [lindex $data(pages) $first]
    } else {
        return [lrange $data(pages) $first $last]
    }
}


# ------------------------------------------------------------------------------
#  Command PagesManager::getframe
# ------------------------------------------------------------------------------
proc PagesManager::getframe { path page } {
    _test_page $path $page
    return $path.f$page
}


proc PagesManager::exists { path page } {
    Widget::getVariable $path data
    return [expr [lsearch -exact $data(pages) $page] > -1]
}


# ------------------------------------------------------------------------------
#  Command PagesManager::_test_page
# ------------------------------------------------------------------------------
proc PagesManager::_test_page { path page } {
    Widget::getVariable $path data

    if {[set pos [lsearch -exact $data(pages) $page]] == -1} {
        return -code error "page \"$page\" does not exists"
    }
    return $pos
}
Added lib/BWidget/panedw.tcl.










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
# ----------------------------------------------------------------------------
#  panedw.tcl
#  This file is part of Unifix BWidget Toolkit
# ----------------------------------------------------------------------------
#  Index of commands:
#
#   Public Commands:
#     - PanedWindow::create
#     - PanedWindow::configure
#     - PanedWindow::cget
#     - PanedWindow::add
#     - PanedWindow::getframe
#
#   Private Commands:
#     - PanedWindow::_destroy
#     - PanedWindow::_redraw
#     - PanedWindow::_resize
#     - PanedWindow::_sash_move
#     - PanedWindow::_sash_move_begin
#     - PanedWindow::_sash_move_end
# ----------------------------------------------------------------------------

namespace eval PanedWindow {
    Widget::define PanedWindow panedw

    namespace eval Pane {
        Widget::declare PanedWindow::Pane {
            {-after   String   ""       1}
            {-before  String   ""       0}
            {-minsize Int      0        0 "%d >= 0"}
            {-width   Int      0        0 "%d >= 0"}
            {-height  Int      0        0 "%d >= 0"}
            {-weight  Int      0        0 "%d >= 0"}
            {-padx    Int      0        0}
            {-pady    Int      0        0}
            {-hide    Boolean  0        0}
            {-sticky  String   "nesw"   0}
            {-stretch Enum     "always" 0 {always first last middle never}}
        }
    }

    Widget::tkinclude PanedWindow frame :cmd \
        include {
            -relief -bd -borderwidth -bg -background -cursor -width -height
        }

    Widget::declare PanedWindow {
        {-side         Enum       top      1 {top left bottom right}}
        {-activator    Enum       "line"   1 {line button}}
	{-weights      Enum       "extra"  1 {extra available}}
        {-opaqueresize Boolean    "0"      0}

        {-sashpad      Int        4        1 "%d >= 0"}
        {-sashcursor   String     ""       0}
        {-sashwidth    Int        4        0}
        {-sashrelief   Enum       "raised" 0
                                  {flat groove raised ridge solid sunken}}

        {-handlepad    Int        "6"      0 "%d >= 0"}
        {-handlesize   Int        "10"     0 "%d >= 0"}
        {-showhandle   Boolean    "0"      0}
        {-handlemove   Boolean    "0"      0}

        {-pad          Synonym    -sashpad}
    }

    bind PanedWindow <Destroy>   [list PanedWindow::_destroy %W]
    bind PanedWindow <Configure> [list PanedWindow::_resize %W %w %h]
}


# ----------------------------------------------------------------------------
#  Command PanedWindow::create
# ----------------------------------------------------------------------------
proc PanedWindow::create { path args } {
    Widget::initArgs PanedWindow $args maps

    eval [list frame $path -class PanedWindow] $maps(:cmd)

    Widget::initFromODB PanedWindow $path $maps(PanedWindow)

    Widget::getVariable $path data

    array set data {
        npanes          0
        curpanes        0
        realized        0
        resizing        0
        horizontal      0
        lastpane        ""
        firstpane       ""
        panes           {}
        frames          {}
        sashes          {}
        handles         {}
        allwidgets      {}
        curwidgets      {}
    }
    
    set side [Widget::getoption $path -side]
    if {[string equal $side "top"] || [string equal $side "bottom"]} {
        set data(horizontal) 1
    }

    if {[string equal [Widget::getoption $path -activator] "button"]} {
        Widget::configure $path [list -showhandle 1]
    }

    return [Widget::create PanedWindow $path]
}


# ----------------------------------------------------------------------------
#  Command PanedWindow::configure
# ----------------------------------------------------------------------------
proc PanedWindow::configure { path args } {
    Widget::getVariable $path data

    set res [Widget::configure $path $args]

    if {[Widget::hasChanged $path -background bg] && $data(npanes) > 0 } {
        $path:cmd configure -background $bg
        foreach widget $data(allwidgets) {
            $widget configure -background $bg
        }
    }

    return $res
}


# ----------------------------------------------------------------------------
#  Command PanedWindow::cget
# ----------------------------------------------------------------------------
proc PanedWindow::cget { path option } {
    return [Widget::cget $path $option]
}


proc PanedWindow::itemconfigure { path pane args } {
    Widget::getVariable $path data
    set frame [lindex $data(frames) [index $path $pane]]

    set res [Widget::configure $frame $args]

    set resize 0
    if {[Widget::hasChanged $frame -hide hide]} {
        set resize 1
        _redraw $path
    }

    $frame configure \
        -width  [Widget::getoption $frame -width] \
        -height [Widget::getoption $frame -height]

    if {$resize || [Widget::anyChangedX $frame -stretch -width -height]} {
        _resize $path
    }

    return $res
}


## Compatibility proc for Tcl 8.4's panedwindow.
proc PanedWindow::paneconfigure { path pane args } {
    return [eval [list PanedWindow::itemconfigure $path $pane] $args]
}


proc PanedWindow::itemcget { path pane option } {
    Widget::getVariable $path data
    set frame [lindex $data(frames) [index $path $pane]]
    return [Widget::cget $frame $option]
}


## Compatibility proc for Tcl 8.4's panedwindow.
proc PanedWindow::panecget { path pane option } {
    return [PanedWindow::itemcget $path $pane $option]
}


# ----------------------------------------------------------------------------
#  Command PanedWindow::add
# ----------------------------------------------------------------------------
proc PanedWindow::add { path args } {
    Widget::getVariable $path data

    set num    $data(npanes)
    set pane   $path.f$num
    set user   $pane.frame
    set create 1

    ## It's optional that the user can pass us a widget instead of
    ## creating a new frame.  See if we were passed an existing
    ## widget as our first argument.
    if {[llength $args] && [winfo exists [lindex $args 0]]} {
        set user   [lindex $args 0]
        set args   [lrange $args 1 end]
        set create 0
    }

    Widget::init PanedWindow::Pane $pane $args

    set index  end
    set after  [Widget::getoption $pane -after]
    set before [Widget::getoption $pane -before]

    if {[string length $after]} {
        set idx [lsearch -exact $data(panes) $after]
        if {$idx > 0} { set index [expr {$idx + 1}] }
    }

    if {[string length $before]} {
        set idx [lsearch -exact $data(panes) $before]
        if {$idx > 0} { set index $idx }
    }

    set data(panes)  [linsert $data(panes)  $index $user]
    set data(frames) [linsert $data(frames) $index $pane]

    set bg      [Widget::cget $path -background]
    set sashw   [Widget::getoption $path -sashwidth]
    set sashc   [Widget::getoption $path -sashcursor]
    set sashr   [Widget::getoption $path -sashrelief]
    set handlew [Widget::getoption $path -handlesize]

    if { $num > 0 } {
        set sep $path.sash$num
        set but $path.handle$num
        frame $sep -bd 1 -highlightthickness 0 \
            -bg $bg -width $sashw -height $sashw -relief $sashr
        frame $but -bd 1 -relief raised -highlightthickness 0 \
            -bg $bg -width $handlew -height $handlew

        lappend data(sashes)     $sep
        lappend data(handles)    $but
        lappend data(allwidgets) $sep $but

        set cursor [Widget::getoption $path -sashcursor]
        if {[string equal $cursor ""]} {
            if {$data(horizontal)} {
                set cursor sb_h_double_arrow 
            } else {
                set cursor sb_v_double_arrow 
            }
        }

        ## If they only want to move with the handle, don't bind the sash.
        if {![Widget::getoption $path -handlemove]} {
            $sep configure -cursor $cursor 
            bind $sep <B1-Motion>       [list $path _sash_move %X %Y]
            bind $sep <ButtonRelease-1> [list $path _sash_move_end %X %Y]
            bind $sep <ButtonPress-1>   [list $path _sash_move_begin %W %X %Y]
        }

        ## Bind the handle for movement.
        $but configure -cursor $cursor 
        bind $but <B1-Motion>       [list $path _sash_move %X %Y]
        bind $but <ButtonRelease-1> [list $path _sash_move_end %X %Y]
        bind $but <ButtonPress-1>   [list $path _sash_move_begin %W %X %Y]
    }

    frame $pane -bd 0 -relief flat -highlightthickness 0 -bg $bg \
        -width  [Widget::getoption $pane -width] \
        -height [Widget::getoption $pane -height]
    lappend data(allwidgets) $pane

    if {$create} {
        frame $user -bd 0 -relief flat -highlightthickness 0 -bg $bg
        lappend data(allwidgets) $user
    }
    place $user -in $pane -x 0 -y 0 -relwidth 1 -relheight 1
    raise $user

    incr data(npanes)

    _redraw $path
    _resize $path

    return $user
}


# ----------------------------------------------------------------------------
#  Command PanedWindow::getframe
# ----------------------------------------------------------------------------
proc PanedWindow::getframe { path index } {
    Widget::getVariable $path data
    return [lindex $data(panes) $index]
}


proc PanedWindow::index { path pane } {
    Widget::getVariable $path data

    set n   [expr {[llength $data(panes)] - 1}]
    set idx $pane
    if {[string is integer -strict $pane]} {
        if {$pane < 0}  { set idx 0  }
        if {$pane > $n} { set idx $n }
    } elseif {[string equal $pane "end"]} {
        set idx $n
    } else {
        set idx [lsearch -exact $data(panes) $pane]
    }

    return $idx
}


proc PanedWindow::panes { path {first ""} {last ""} } {
    Widget::getVariable $path data
    if {![string length $first]} { return $data(panes) }
    if {![string length $last]}  { return [lindex $data(panes) $first] }
    return [lrange $data(panes) $first $last]
}


proc PanedWindow::delete { path args } {
    Widget::getVariable $path data

    foreach pane $args {
        set idx [lsearch -exact $data(panes) $pane]
        if {$idx < 0} { continue }
        set frame  [lindex $data(frames)  $idx]

        if {$idx == [expr {[llength $data(panes)] - 1}]} {
            set sash   [lindex $data(sashes)  end]
            set handle [lindex $data(handles) end]
        } else {
            set sash   [lindex $data(sashes)  $idx]
            set handle [lindex $data(handles) $idx]
        }

        set created [expr [lsearch -exact $data(allwidgets) $pane] > -1]

        set data(panes)   [lreplace $data(panes)  $idx $idx]
        set data(frames)  [lreplace $data(frames) $idx $idx]

        set data(sashes)     [BWidget::lremove $data(sashes)  $sash]
        set data(handles)    [BWidget::lremove $data(handles) $handle]
        set data(allwidgets) [BWidget::lremove $data(allwidgets) \
                                $frame $sash $pane $handle]

        destroy $frame $sash $handle

        ## If we created this frame, we need to destroy it.
        ## Otherwise, the user created it, and we don't want to mess with it.
        if {$created} { destroy $pane }
    }

    _redraw $path
    _resize $path
}


## Compatibility proc for Tcl 8.4's panedwindow.
proc PanedWindow::forget { path pane } {
    return [PanedWindow::delete $path $pane]
}


proc PanedWindow::identify { path x y } {
    Widget::getVariable $path data

    set idx    -1
    set widget [winfo containing $x $y]

    if {[Widget::getoption $path -showhandle]} {
        set idx  [lsearch -exact $data(handles) $widget]
        set word handle
    }

    if {$idx < 0} {
        set idx  [lsearch -exact $data(sashes) $widget]
        set word sash
    }

    if {$idx > -1} { return [list $idx $word] }
}


proc PanedWindow::_sash_temp_name { path } {
    set top [winfo toplevel $path]
    if {[string equal $top "."]} {
        return .#BWidget#sash
    } else {
        return $top.#BWidget#sash
    }
}
    

# ----------------------------------------------------------------------------
#  Command PanedWindow::_sash_move_begin
# ----------------------------------------------------------------------------
proc PanedWindow::_sash_move_begin { path w x y } {
    Widget::getVariable $path data

    set data(x)      $x
    set data(y)      $y
    set data(startX) $x
    set data(startY) $y
    set data(endX)   $x
    set data(endY)   $y
    set data(sash)   [lsearch -exact $data(curwidgets) $w]

    if {![Widget::getoption $path -opaqueresize]} {
        ## If we're not doing an opaque resize, we need to draw
        ## a temporary sash that we can move around.
        set bg   [Widget::cget $path -background]
        set sash [lindex $data(curwidgets) $data(sash)]
        set geom [split [winfo geometry $sash] x+-]
        foreach [list w h x y] $geom { break }

        set sashw [Widget::getoption $path -sashwidth]
        set sashr [Widget::getoption $path -sashrelief]

        set sep [_sash_temp_name $path]
        frame $sep -bd 1 -highlightthickness 0 \
            -bg $bg -width $sashw -height $sashw -relief $sashr

        place $sep -in $path -x $x -y $y -width $w -height $h
    }
}


# ----------------------------------------------------------------------------
#  Command PanedWindow::_sash_move
# ----------------------------------------------------------------------------
proc PanedWindow::_sash_move { path x y } {
    Widget::getVariable $path data

    set cx $data(x)
    set cy $data(y)

    set data(x) $x
    set data(y) $y

    set column $data(sash)

    if {$data(horizontal)} {
        set change [expr {$x - $cx}]
    } else {
        set change [expr {$y - $cy}]
    }

    if {$change == 0} { return }

    if {$change < 0} {
        set lose [lindex $data(curwidgets) [expr {$column - 1}]]
        set gain [lindex $data(curwidgets) [expr {$column + 1}]]
        incr column -1
        set adjust 5
    } else {
        set lose [lindex $data(curwidgets) [expr {$column + 1}]]
        set gain [lindex $data(curwidgets) [expr {$column - 1}]]
        incr column 1
        set adjust -5
    }

    if {$data(horizontal)} {
        set box [grid bbox $path $column 0]
    } else {
        set box [grid bbox $path 0 $column]
    }

    if {![Widget::getoption $path -opaqueresize]} {
        set sep [_sash_temp_name $path]
        if {$data(horizontal)} {
            set opt -x
            set min [expr {[lindex $box 0] + $adjust}]
            set max [expr {$min + [lindex $box 2] - 5}]
        } else {
            set opt -y
            set min [expr {[lindex $box 1] + $adjust}]
            set max [expr {$min + [lindex $box 3] - 5}]
        }

        set new [expr {[lindex [place configure $sep $opt] end] + $change}]

        if {$change < 0 && $new <= $min} { return }
        if {$change > 0 && $new >= $max} { return }
        place $sep $opt $new
    } else {
        set change [expr {abs($change)}]
        set min [Widget::getoption $lose -minsize]
        if {$data(horizontal)} {
            set opt  -width
            set size [lindex $box 2]
        } else {
            set opt  -height
            set size [lindex $box 3]
        }

        if {$size - $change <= $min} { return }

        set losex [expr {[$lose cget $opt] - $change}]
        set gainx [expr {[$gain cget $opt] + $change}]
        $lose configure $opt $losex
        $gain configure $opt $gainx

        Widget::setoption $lose $opt $losex
        Widget::setoption $gain $opt $gainx
    }

    set data(endX) $x
    set data(endY) $y
}


# ----------------------------------------------------------------------------
#  Command PanedWindow::_sash_move_end
# ----------------------------------------------------------------------------
proc PanedWindow::_sash_move_end { path x y } {
    Widget::getVariable $path data

    if {[Widget::getoption $path -opaqueresize]} { return }

    set sep [_sash_temp_name $path]

    if {$data(horizontal)} {
        set opt    -width
        set change [expr {$data(endX) - $data(startX)}]
    } else {
        set opt    -height
        set change [expr {$data(endY) - $data(startY)}]
    }

    if {$change < 0} {
        set lose [lindex $data(curwidgets) [expr {$data(sash) - 1}]]
        set gain [lindex $data(curwidgets) [expr {$data(sash) + 1}]]
    } else {
        set lose [lindex $data(curwidgets) [expr {$data(sash) + 1}]]
        set gain [lindex $data(curwidgets) [expr {$data(sash) - 1}]]
    }

    if {[set min [Widget::getoption $lose -minsize]] < 1} { set min 1 }

    set losex [expr {[$lose cget $opt] - abs($change)}]
    if {$losex < $min} { set losex $min }
    set gainx [expr {[$gain cget $opt] + ([$lose cget $opt] - $losex)}]

    $lose configure $opt $losex
    $gain configure $opt $gainx

    Widget::setoption $lose $opt $losex
    Widget::setoption $gain $opt $gainx

    destroy $sep
}


proc PanedWindow::_resize { path {w ""} {h ""} } {
    Widget::getVariable $path data

    if {$data(resizing)} { return }

    if {$data(curpanes) < 1} { return }

    set data(resizing) 1

    set npanes $data(curpanes)

    if {[string equal $w ""]} { set w [winfo width  $path] }
    if {[string equal $h ""]} { set h [winfo height $path] }

    if {$data(horizontal)} {
        set opt   -width
	set total $w
    } else {
        set opt   -height
	set total $h
    }

    set sashp [Widget::getoption $path -sashpad]
    set sashw [Widget::getoption $path -sashwidth]
    set sashw [expr {$sashw + (2 * $sashp)}]
    set total [expr {$total - (($npanes - 1) * $sashw)}]
    
    set panes        [list]
    set sizes        [list]
    set panesize     0
    set stretchpanes 0
    foreach frame $data(frames) {
        if {[Widget::getoption $frame -hide]} { continue }
        set stretch   [Widget::getoption $frame -stretch]
        set framesize [Widget::getoption $frame $opt].0

        if {[string equal $stretch "never"]
            || ([string equal $stretch "last"]
                && ![string equal $frame $data(lastpane)])
            || ([string equal $stretch "first"]
                && ![string equal $frame $data(firstpane)])
            || ([string equal $stretch "middle"]
                && ([string equal $frame $data(firstpane)]
                    || [string equal $frame $data(lastpane)]))} {
            set total [expr {$total - $framesize}]
            continue
        }
        lappend panes $frame
        lappend sizes $framesize
        set panesize [expr {$panesize + $framesize}]
        incr stretchpanes
    }

    foreach pane $panes size $sizes {
        if {$panesize > 0} {
            set newsize [expr {($size / $panesize) * $total}]
        } else {
            set newsize [expr {$total / $stretchpanes}]
        }
        $pane configure $opt $newsize
    }

    update idletasks
    set data(resizing) 0
}


proc PanedWindow::_redraw { path } {
    Widget::getVariable $path data

    set data(curpanes)   0
    set data(curwidgets) [list]

    set handle     [Widget::getoption $path -showhandle]
    set sashpad    [Widget::getoption $path -sashpad]
    set handlepad  [Widget::getoption $path -handlepad]

    set sashPadX   0
    set sashPadY   0
    set handlePadX 0
    set handlePadY 0

    set side [Widget::getoption $path -side]
    if {$data(horizontal)} {
        set where        column
        set sashPadX     $sashpad
        set sashSticky   ns
        set handlePadY   $handlepad
        set handleSticky s
        if {[string equal $side "top"]} { set handleSticky n }
        grid rowconfigure $path 0 -weight 1
    } else {
        set where        row
        set sashPadY     $sashpad
        set sashSticky   ew
        set handlePadX   $handlepad
        set handleSticky e
        if {[string equal $side "left"]} { set handleSticky w }
        grid columnconfigure $path 0 -weight 1
    }

    ## Before we redraw the grid, we need to walk through and
    ## make sure all the configuration options are clean.
    set i -1
    foreach widget $data(curwidgets) {
        grid remove $widget
        grid ${where}configure $path [incr i] -weight 0
    }

    set c -1
    foreach pane $data(frames) sash $data(sashes) {
        if {[Widget::getoption $pane -hide]} { continue }

        if {$data(horizontal)} {
            set row 0; set col [incr c]
        } else {
            set row [incr c]; set col 0
        }

        if {!$data(curpanes)} { set data(firstpane) $pane }
        set data(lastpane) $pane
        incr data(curpanes)

        lappend data(curwidgets) $pane

        ## Grid the pane into place.
        set padx   [Widget::getoption $pane -padx]
        set pady   [Widget::getoption $pane -pady]
        set sticky [Widget::getoption $pane -sticky]
        set weight [Widget::getoption $pane -weight]
        grid $pane -in $path -row $row -column $col \
            -sticky $sticky -padx $padx -pady $pady
        grid ${where}configure $path $c -weight $weight

        if {[string length $sash]} {
            if {$data(horizontal)} {
                set row 0; set col [incr c]
            } else {
                set row [incr c]; set col 0
            }

            lappend data(curwidgets) $sash

            ## Grid the sash into place
            grid $sash -in $path -row $row -column $col \
                -sticky $sashSticky -padx $sashPadX -pady $sashPadY

            set x [lsearch -exact $data(sashes) $sash]
            set button [lindex $data(handles) $x]
            if {$handle} {
                grid $button -in $path -row $row -column $col \
                    -sticky $handleSticky -padx $handlePadX -pady $handlePadY
            } else {
                grid remove $button
            }
        }
    }
}


# ----------------------------------------------------------------------------
#  Command PanedWindow::_destroy
# ----------------------------------------------------------------------------
proc PanedWindow::_destroy { path } {
    Widget::getVariable $path data

    for {set i 0} {$i < $data(npanes)} {incr i} {
        Widget::destroy $path.f$i 0
    }

    Widget::destroy $path
}
Added lib/BWidget/panelframe.tcl.
































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# ----------------------------------------------------------------------------
#  panelframe.tcl
#	Create PanelFrame widgets.
#	A PanelFrame is a boxed frame that allows you to place items
#	in the label area (liked combined frame+toolbar).  It uses the
#	highlight colors the default frame color.
#  $Id: panelframe.tcl,v 1.1 2004/09/09 22:17:51 hobbs Exp $
# ----------------------------------------------------------------------------
#  Index of commands:
#     - PanelFrame::create
#     - PanelFrame::configure
#     - PanelFrame::cget
#     - PanelFrame::getframe
#     - PanelFrame::add
#     - PanelFrame::remove
#     - PanelFrame::items
# ----------------------------------------------------------------------------

namespace eval PanelFrame {
    Widget::define PanelFrame panelframe

    Widget::declare PanelFrame {
	{-background	   Color "SystemButtonFace" 0}
	{-borderwidth	   TkResource 1	 0 frame}
	{-relief	   TkResource flat 0 frame}
	{-panelbackground  Color "SystemHighlight" 0}
	{-panelforeground  Color "SystemHighlightText" 0}
	{-width		   Int	      0	 0}
	{-height	   Int	      0	 0}
	{-font		   String     "TkTextFont" 0}
	{-text		   String     "" 0}
	{-textvariable	   String     "" 0}
	{-ipad		   String      1 0}
	{-bg		   Synonym    -background}
	{-bd		   Synonym    -borderwidth}
    }

    Widget::addmap PanelFrame "" :cmd {
	-panelbackground -background
	-width {} -height {} -borderwidth {} -relief {}
    }
    Widget::addmap PanelFrame "" .title	  {
	-panelbackground -background
    }
    Widget::addmap PanelFrame "" .title.text   {
	-panelbackground -background
	-panelforeground -foreground
	-text {} -textvariable {} -font {}
    }
    Widget::addmap PanelFrame "" .frame {
	-background {}
    }

    if {0} {
	# This would be code to have an automated close button
	#{-closebutton	   Boolean    0	 0}
	Widget::addmap PanelFrame "" .title.close   {
	    -panelbackground -background
	    -panelforeground -foreground
	}
	variable HaveMarlett \
	    [expr {[lsearch -exact [font families] "Marlett"] != -1}]

	variable imgdata {
	    #define close_width 16
	    #define close_height 16
	    static char close_bits[] = {
		0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x10, 0x08,
		0x38, 0x1c, 0x70, 0x0e,
		0xe0, 0x07, 0xc0, 0x03,
		0xc0, 0x03, 0xe0, 0x07,
		0x70, 0x0e, 0x38, 0x1c,
		0x10, 0x08, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00};
	}
	# We use the same -foreground as the default -panelbackground
	image create bitmap ::PanelFrame::X -data $imgdata \
	    -foreground [lindex $Widget::PanelFrame::opt(-panelbackground) 1]
    }
}


# ----------------------------------------------------------------------------
#  Command PanelFrame::create
# ----------------------------------------------------------------------------
proc PanelFrame::create { path args } {
    variable HaveMarlett

    Widget::initArgs PanelFrame $args maps

    set lblopts [list -bd 0 -highlightthickness 0 -anchor w]
    set outer [eval [list frame $path -class PanelFrame] $maps(:cmd)]
    set title [eval [list frame $path.title] $maps(.title)]
    set tlbl  [eval [list label $path.title.text] $lblopts $maps(.title.text)]
    set inner [eval [list frame $path.frame] $maps(.frame)]

    Widget::initFromODB PanelFrame $path $maps(PanelFrame)

    foreach {ipadx ipady} [_padval [Widget::cget $path -ipad]] { break }

    if {0} {
	set btnopts [list -padx 0 -pady 0 -relief flat -overrelief raised \
			 -bd 1 -highlightthickness 0]
	set clbl  [eval [list button $path.title.close] $btnopts \
                        $maps(.title.close)]
	set close [Widget::cget $path -closebutton]
	if {$HaveMarlett} {
	    $clbl configure -font "Marlett -14" -text \u0072
	} else {
	    $clbl configure -image ::PanelFrame::X
	}
	if {$close} {
	    pack $path.title.close -side right -padx $ipadx -pady $ipady
	}
    }

    grid $path.title -row 0 -column 0 -sticky ew
    grid $path.frame -row 1 -column 0 -sticky news
    grid columnconfigure $path 0 -weight 1
    grid rowconfigure $path 1 -weight 1

    pack $path.title.text -side left -fill x -anchor w \
	-padx $ipadx -pady $ipady

    return [Widget::create PanelFrame $path]
}


# ----------------------------------------------------------------------------
#  Command PanelFrame::configure
# ----------------------------------------------------------------------------
proc PanelFrame::configure { path args } {
    set res [Widget::configure $path $args]

    if {[Widget::hasChanged $path -ipad ipad]} {
    }

    return $res
}


# ----------------------------------------------------------------------------
#  Command PanelFrame::cget
# ----------------------------------------------------------------------------
proc PanelFrame::cget { path option } {
    return [Widget::cget $path $option]
}

# ----------------------------------------------------------------------------
#  Command PanelFrame::getframe
# ----------------------------------------------------------------------------
proc PanelFrame::getframe { path } {
    return $path.frame
}

# ------------------------------------------------------------------------
#  Command PanelFrame::add
# ------------------------------------------------------------------------
proc PanelFrame::add {path w args} {
    variable _widget

    array set opts [list \
			-side   right \
			-fill   none \
			-expand 0 \
			-pad    [Widget::cget $path -ipad] \
		       ]
    foreach {key val} $args {
	if {[info exists opts($key)]} {
	    set opts($key) $val
	} else {
	    set msg "unknown option \"$key\", must be one of: "
	    append msg [join [lsort [array names opts]] {, }]
	    return -code error $msg
	}
    }
    foreach {ipadx ipady} [_padval $opts(-pad)] { break }

    set f $path.title

    lappend _widget($path,items) $w
    pack $w -in $f -padx $ipadx -pady $ipady -side $opts(-side) \
	-fill $opts(-fill) -expand $opts(-expand)

    return $w
}

# ------------------------------------------------------------------------
#  Command PanelFrame::remove
# ------------------------------------------------------------------------
proc PanelFrame::remove {path args} {
    variable _widget

    set destroy [string equal [lindex $args 0] "-destroy"]
    if {$destroy} {
	set args [lrange $args 1 end]
    }
    foreach w $args {
	set idx [lsearch -exact $_widget($path,items) $w]
	if {$idx == -1} {
	    # ignore unknown
	    continue
	}
	if {$destroy} {
	    destroy $w
	} elseif {[winfo exists $w]} {
	    pack forget $w
	}
	set _widget($path,items) [lreplace $_widget($path,items) $idx $idx]
    }
}

# ------------------------------------------------------------------------
#  Command PanelFrame::delete
# ------------------------------------------------------------------------
proc PanelFrame::delete {path args} {
    return [PanelFrame::remove $path -destroy $args]
}

# ------------------------------------------------------------------------
#  Command PanelFrame::items
# ------------------------------------------------------------------------
proc PanelFrame::items {path} {
    variable _widget
    return $_widget($path,items)
}

proc PanelFrame::_padval {padval} {
    set len [llength $padval]
    foreach {a b} $padval { break }
    if {$len == 0 || $len > 2} {
	return -code error \
	    "invalid pad value \"$padval\", must be 1 or 2 pixel values"
    } elseif {$len == 1} {
	return [list $a $a]
    } elseif {$len == 2} {
	return $padval
    }
}
Added lib/BWidget/passwddlg.tcl.




























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# -----------------------------------------------------------------------------
#  passwddlg.tcl
#  This file is part of Unifix BWidget Toolkit
#   by Stephane Lavirotte (Stephane.Lavirotte@sophia.inria.fr)
#  $Id: passwddlg.tcl,v 1.8 2003/10/20 21:23:52 damonc Exp $
# -----------------------------------------------------------------------------
#  Index of commands:
#     - PasswdDlg::create
#     - PasswdDlg::configure
#     - PasswdDlg::cget
#     - PasswdDlg::_verifonlogin
#     - PasswdDlg::_verifonpasswd
#     - PasswdDlg::_max
#------------------------------------------------------------------------------

namespace eval PasswdDlg {
    Widget::define PasswdDlg passwddlg Dialog LabelEntry

    Widget::bwinclude PasswdDlg Dialog :cmd \
        remove {
            -image -bitmap -side -default -cancel separator
        } initialize {
            -modal local -anchor c
        }

    Widget::bwinclude PasswdDlg LabelEntry .frame.lablog \
        remove {
            -command -justify -name -show -side -state -takefocus
            -width -xscrollcommand -padx -pady -dragenabled -dragendcmd
            -dragevent -draginitcmd -dragtype -dropenabled -dropcmd
            -dropovercmd -droptypes
        } prefix {
            login -editable -helptext -helpvar -label -text
            -textvariable -underline
        } initialize {
            -relief sunken -borderwidth 2 -labelanchor w -width 15
            -label "Login"
        }

    Widget::bwinclude PasswdDlg LabelEntry .frame.labpass \
        remove {
            -command -justify -name -show -side -state -takefocus
            -width -xscrollcommand -padx -pady -dragenabled -dragendcmd
            -dragevent -draginitcmd -dragtype -dropenabled -dropcmd
            -dropovercmd -droptypes
        } prefix {
            passwd -editable -helptext -helpvar -label -text
            -textvariable -underline
        } initialize {
            -relief sunken -borderwidth 2 -labelanchor w -width 15
            -label "Password"
        }

    Widget::declare PasswdDlg {
        {-type        Enum       ok           0 {ok okcancel}}
        {-labelwidth  TkResource -1           0 {label -width}}
        {-command     String     ""           0}

        {-login       String     ""           0}
        {-password    String     ""           0}
    }
}


# -----------------------------------------------------------------------------
#  Command PasswdDlg::create
# -----------------------------------------------------------------------------
proc PasswdDlg::create { path args } {
    Widget::initArgs PasswdDlg $args maps

    set bmp [Bitmap::get passwd]
    eval [list Dialog::create $path] $maps(:cmd) \
         [list -class PasswdDlg -image $bmp -side bottom -spacing 0]

    Widget::initFromODB PasswdDlg "$path#PasswdDlg" $maps(PasswdDlg)

    # Extract the PasswdDlg megawidget options (those that don't map to a
    # subwidget)
    set type      [Widget::cget "$path#PasswdDlg" -type]
    set cmd       [Widget::cget "$path#PasswdDlg" -command]

    set defb -1
    set canb -1
    switch -- $type {
        ok        { set lbut {ok}; set defb 0 }
        okcancel  { set lbut {ok cancel} ; set defb 0; set canb 1 }
    }

    $path configure -default $defb -cancel $canb

    foreach but $lbut {
        if {[string equal $but "ok"] && [string length $cmd]} {
            Dialog::add $path -text $but -name $but -command $cmd -width 12
        } else {
            Dialog::add $path -text $but -name $but -width 12
        }
    }

    set frame [Dialog::getframe $path]
    #bind $path  <Return>  ""
    bind $frame <Destroy> [list Widget::destroy $path\#PasswdDlg]

    set lablog [eval [list LabelEntry::create $frame.lablog] \
		    $maps(.frame.lablog) \
		    [list -name login -dragenabled 0 -dropenabled 0 \
			 -command [list PasswdDlg::_verifonpasswd \
				       $path $frame.labpass]]]

    set labpass [eval [list LabelEntry::create $frame.labpass] \
		     $maps(.frame.labpass) \
		     [list -name password -show "*" \
			  -dragenabled 0 -dropenabled 0 \
			  -command [list PasswdDlg::_verifonlogin \
					$path $frame.lablog]]]

    set labwidth [$lablog cget -labelwidth]
    if {$labwidth == 0} {
        set loglabel  [$lablog cget -label]
        set passlabel [$labpass cget -label]
        set labwidth [_max [string length $loglabel] [string length $passlabel]]
        incr labwidth 1
    }
    $lablog  configure -labelwidth $labwidth
    $labpass configure -labelwidth $labwidth

    Widget::create PasswdDlg $path 0

    pack  $lablog $labpass -fill x -expand 1

    # added by bach@mwgdna.com
    #  give focus to loginlabel unless the state is disabled
    set focus $labpass.e
    if {[$lablog cget -editable]} { set focus $lablog.e }

    set login [Widget::getoption $path#PasswdDlg -login]
    if {[string length $login]} {
        $lablog configure -text $login
        set focus $labpass.e
    }

    set password [Widget::getoption $path#PasswdDlg -password]
    if {[string length $password]} {
        $labpass configure -text $password
        set focus $lablog.e
    }

    focus $focus
    
    set res [Dialog::draw $path]

    if { $res == 0 } {
        set res [list [$lablog.e cget -text] [$labpass.e cget -text]]
    } else {
        set res [list]
    }
    Widget::destroy "$path#PasswdDlg"
    destroy $path

    return $res
}

# -----------------------------------------------------------------------------
#  Command PasswdDlg::configure
# -----------------------------------------------------------------------------

proc PasswdDlg::configure { path args } {
    set res [Widget::configure "$path#PasswdDlg" $args]
}

# -----------------------------------------------------------------------------
#  Command PasswdDlg::cget
# -----------------------------------------------------------------------------

proc PasswdDlg::cget { path option } {
    return [Widget::cget "$path#PasswdDlg" $option]
}


# -----------------------------------------------------------------------------
#  Command PasswdDlg::_verifonlogin
# -----------------------------------------------------------------------------
proc PasswdDlg::_verifonlogin { path labpass } {
    if { [$labpass.e cget -text] == "" } {
        focus $labpass
    } else {
        Dialog::setfocus $path default
    }
}

# -----------------------------------------------------------------------------
#  Command PasswdDlg::_verifonpasswd
# -----------------------------------------------------------------------------
proc PasswdDlg::_verifonpasswd { path lablog } {
    if { [$lablog.e cget -text] == "" } {
        focus $lablog
    } else {
        Dialog::setfocus $path default
    }
}

# -----------------------------------------------------------------------------
#  Command PasswdDlg::_max
# -----------------------------------------------------------------------------
proc PasswdDlg::_max { val1 val2 } { 
    return [expr {($val1 > $val2) ? ($val1) : ($val2)}] 
}
Added lib/BWidget/pkgIndex.tcl.


























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
if {[catch {package require Tcl}]} return
package ifneeded BWidget 2.0 "\
    package require Tk 8.4;\
    [list tclPkgSetup $dir BWidget 2.0 {
{arrow.tcl source {ArrowButton ArrowButton::create ArrowButton::use}}
{bitmap.tcl source {Bitmap::get Bitmap::use}}
{button.tcl source {Button Button::create Button::use}}
{buttonbox.tcl source {ButtonBox ButtonBox::create ButtonBox::use}}
{calendar.tcl source {Calendar Calendar::create Calendar::use}}
{choosedir.tcl source {ChooseDirectory ChooseDirectory::create ChooseDirectory::use}}
{choosefile.tcl source {ChooseFile ChooseFile::create ChooseFile::use}}
{color.tcl source {SelectColor SelectColor::menu SelectColor::dialog SelectColor::setcolor}}
{combobox.tcl source {ComboBox ComboBox::create ComboBox::use}}
{dialog.tcl source {Dialog Dialog::create Dialog::use}}
{dragsite.tcl source {DragSite::register DragSite::include DragSite::use}}
{drawerpanel.tcl source {DrawerPanel DrawerPanel::create DrawerPanel::use}}
{dropsite.tcl source {DropSite::register DropSite::include DropSite::use}}
{dynhelp.tcl source {DynamicHelp::configure DynamicHelp::use DynamicHelp::register DynamicHelp::include DynamicHelp::add DynamicHelp::delete}}
{entry.tcl source {Entry Entry::create Entry::use}}
{font.tcl source {SelectFont SelectFont::create SelectFont::use SelectFont::loadfont}}
{icons.tcl source {IconLibrary IconLibrary::create IconLibrary::use}}
{label.tcl source {Label Label::create Label::use}}
{labelentry.tcl source {LabelEntry LabelEntry::create LabelEntry::use}}
{labelframe.tcl source {LabelFrame LabelFrame::create LabelFrame::use}}
{listbox.tcl source {ListBox ListBox::create ListBox::use}}
{mainframe.tcl source {MainFrame MainFrame::create MainFrame::use}}
{messagedlg.tcl source {MessageDlg MessageDlg::create MessageDlg::use}}
{notebook.tcl source {NoteBook NoteBook::create NoteBook::use}}
{optiontree.tcl source {OptionTree OptionTree::create OptionTree::use}}
{pagesmgr.tcl source {PagesManager PagesManager::create PagesManager::use}}
{panedw.tcl source {PanedWindow PanedWindow::create PanedWindow::use}}
{panelframe.tcl source {PanelFrame PanelFrame::create PanelFrame::use}}
{passwddlg.tcl source {PasswdDlg PasswdDlg::create PasswdDlg::use}}
{preferences.tcl source {Preferences Preferences::create Preferences::use}}
{progressbar.tcl source {ProgressBar ProgressBar::create ProgressBar::use}}
{progressdlg.tcl source {ProgressDlg ProgressDlg::create ProgressDlg::use}}
{properties.tcl source {Properties Properties::create Properties::use}}
{scrollframe.tcl source {ScrollableFrame ScrollableFrame::create ScrollableFrame::use}}
{scrollview.tcl source {ScrollView ScrollView::create ScrollView::use}}
{scrollw.tcl source {ScrolledWindow ScrolledWindow::create ScrolledWindow::use}}
{separator.tcl source {Separator Separator::create Separator::use}}
{spinbox.tcl source {SpinBox SpinBox::create SpinBox::use}}
{splitlist.tcl source {SplitList SplitList::create SplitList::use}}
{statusbar.tcl source {StatusBar StatusBar::create StatusBar::use}}
{stddialog.tcl source {StandardDialog StandardDialog::create StandardDialog::use}}
{tablelist.tcl source {TableList TableList::create TableList::use}}
{text.tcl source {Text Text::create Text::use}}
{titleframe.tcl source {TitleFrame TitleFrame::create TitleFrame::use}}
{tree.tcl source {Tree Tree::create Tree::use}}
{ttkbutton.tcl source {TTKButton TTKButton::create TTKButton::use}}
{wizard.tcl source {Wizard Wizard::create Wizard::use SimpleWizard ClassicWizard}}
{xpm2image.tcl source {xpm-to-image}}

}]; \
	[list namespace eval ::BWIDGET {}]; \
	[list set ::BWIDGET::LIBRARY $dir]; \
    [list source [file join $dir widget.tcl]]; \
    [list source [file join $dir init.tcl]]; \
    [list source [file join $dir utils.tcl]]; \
    BWidget::use
"
Added lib/BWidget/preferences.tcl.






















































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
# -----------------------------------------------------------------------------
#  preferences.tcl
#
#       Implement a preferences window with a Tree on the left side to
#       show layered preference groups and a PagesManager on the right
#       to display a different frame for each group.
#
#  $Id$
# -----------------------------------------------------------------------------
#  Index of commands:
#     - Preferences::create
#     - Preferences::configure
#     - Preferences::cget
#     - Preferences::getframe
#     - Preferences::insert
#     - Preferences::delete
#     - Preferences::nodes
#     - Preferences::raise
#     - Preferences::open
#     - Preferences::close
#     - Preferences::toggle
# -----------------------------------------------------------------------------

namespace eval Preferences {
    if {[info tclversion] < 8.4} {
        Widget::define Preferences preferences PanedWindow Tree ScrolledWindow
    } else {
        Widget::define Preferences preferences Tree ScrolledWindow
    }

    Widget::declare Preferences::Node {
        {-pagewindow      String    ""    1}
        {-haspage         Boolean   1     1}
        {-created         Boolean   0     1}
        {-createpage      Boolean   0     1}
        {-raisecommand    String    ""    0}
        {-createcommand   String    ""    0}
    }

    Widget::tkinclude Preferences frame :cmd \
        include { -relief -borderwidth -bd -width -height }

    Widget::bwinclude Preferences Tree .panes.treeframe.t \
        prefix { tree -background -cursor -borderwidth
                 -highlightbackground -highlightcolor -highlightthickness
                 -relief -selectbackground -selectforeground -padx } \
        remove { -bd -bg } \
	initialize { -highlightthickness 0 }

    Widget::declare Preferences {
        {-background   String     ""         0}
	{-padx         Padding    "0"        0}
	{-resizable    Boolean    "1"        1}

        {-treewidth    Int        "200"      0}
        {-treestretch  Enum       "never"    0 {always first last middle never}}

        {-pagewidth    Int        "200"      0 "%d > 0"}
        {-pagestretch  Enum       "always"   0 {always first last middle never}}

        {-bg           Synonym    -background}
    }
}


# -----------------------------------------------------------------------------
#  Command Preferences::create
# -----------------------------------------------------------------------------
proc Preferences::create { path args } {
    Widget::initArgs Preferences $args maps

    eval frame $path $maps(:cmd) -class Preferences

    Widget::initFromODB Preferences $path $maps(Preferences)

    Widget::getVariable $path data
    Widget::getVariable $path pane1
    Widget::getVariable $path pane2

    set data(select) ""

    set resizable [Widget::cget $path -resizable]

    if {$resizable} {
        PanedWindow $path.panes -sashpad 2 -sashwidth 2 -sashrelief ridge
    } else {
        frame $path.panes
    }

    pack $path.panes -expand 1 -fill both

    set pane1 [frame $path.panes.treeframe]
    set pane2 [frame $path.panes.mainframe]

    if {$resizable} {
        $path.panes add $pane1 \
            -width   [Widget::getoption $path -treewidth] \
            -stretch [Widget::getoption $path -treestretch]
        $path.panes add $pane2 -stretch last \
            -width   [Widget::getoption $path -pagewidth] \
            -stretch [Widget::getoption $path -pagestretch]
    } else {
        pack $pane1 -side left -fill y
        pack $pane2 -side left -fill both -expand 1
    }

    ScrolledWindow $pane1.sw
    pack $pane1.sw -expand 1 -fill both

    eval Tree $pane1.t -linesfill #CACACA -padx 2 $maps(.panes.treeframe.t)
    $pane1.sw setwidget $pane1.t
    $pane1.t bindText  <1> [list $path raise]
    $pane1.t bindImage <1> [list $path raise]
    $pane1.t bindText  <Double-1> [list $path toggle]
    $pane1.t bindImage <Double-1> [list $path toggle]

    frame $pane2.f
    grid rowconfigure    $pane2.f 0 -weight 1
    grid columnconfigure $pane2.f 0 -weight 1

    set padx [Widget::getoption $path -padx]
    pack $pane2.f -side left -expand 1 -fill both -padx $padx

    return [Widget::create Preferences $path]
}


# -----------------------------------------------------------------------------
#  Command Preferences::configure
# -----------------------------------------------------------------------------
proc Preferences::configure { path args } {
    Widget::getVariable $path pane1
    Widget::getVariable $path pane2

    set res [Widget::configure $path $args]

    if {[Widget::hasChanged $path -background bg]} {
        $path configure -background $bg
        $path.panes configure -background $bg
        $pane2.f configure -background $bg
    }

    if {[Widget::hasChanged $path -treewidth width]} {
        $path.panes paneconfigure $pane1 -width $width
    }

    if {[Widget::hasChanged $path -treestretch stretch]} {
        $path.panes paneconfigure $pane1 -stretch $stretch
    }

    if {[Widget::hasChanged $path -pagewidth width]} {
        $path.panes paneconfigure $pane2 -width $width
    }

    if {[Widget::hasChanged $path -pagestretch stretch]} {
        $path.panes paneconfigure $pane2 -stretch $stretch
    }

    if {[Widget::hasChanged $path -padx padx]} {
        pack configure $pane2.f -padx $padx
    }

    return $res
}


proc Preferences::cget { path option } {
    switch -- $option {
        "-treewidth" {
            Widget::getVariable $path pane1
            return [$path.panes panecget $pane1 -width]

        }

        "-treestretch" {
            Widget::getVariable $path pane1
            return [$path.panes panecget $pane1 -stretch]
        }

        "-pagewidth" {
            Widget::getVariable $path pane2
            return [$path.panes panecget $pane2 -width]
        }

        "-pagestretch" {
            Widget::getVariable $path pane2
            return [$path.panes panecget $pane2 -stretch]
        }

        default {
            return [Widget::cget $path $option]
        }
    }
}


proc Preferences::itemconfigure { path node args } {
    Widget::getVariable $path pane1

    if {![llength $args]} {
        set res [eval $pane1.t itemconfigure $node $args]
        eval lappend res [Widget::configure $path.$node $args]
        return [lsort $res]
    }

    if {[llength $args] == 1} {
        if {[Widget::optionExists Tree::Node $args]} {
            return [Tree::itemconfigure $pane1.t $node $args]
        } else {
            return [Widget::configure $path.$node $args]
        }
    }

    array set maps [Widget::splitArgs $args Preferences::Node Tree::Node]

    if {[info exists maps(Tree::Node)]} {
        eval [list Tree::itemconfigure $pane1.t $node] $maps(Tree::Node)
    }

    if {[info exists maps(Preferences::Node)]} {
        Widget::configure $path.$node $maps(Preferences::Node)
    }
}


proc Preferences::itemcget { path node option } {
    Widget::getVariable $path pane1
    if {[Widget::optionExists Preferences::Node $option]} {
        return [Widget::cget $path.$node $option]
    } else {
        return [$pane1.t itemcget $node $option]
    }
}


proc Preferences::getframe { path {node ""} } {
    Widget::getVariable $path pane2

    if {[string length $node] && ![exists $path $node]} {
        return -code error "node \"$node\" does not exist"
    }

    if {![string length $node]} { return $pane2.f }

    if {![Widget::getoption $path.$node -haspage]} { return }

    set window [Widget::getoption $path.$node -pagewindow]
    if {![winfo exists $window]} { _create_node $path $node }
    return $window
}


proc Preferences::gettree { path } {
    Widget::getVariable $path pane1
    return $pane1.t
}


proc Preferences::insert { path idx parent node args } {
    Widget::getVariable $path data
    Widget::getVariable $path pane1
    Widget::getVariable $path pane2

    array set maps [list Preferences::Node {} Tree::Node {}]
    array set maps [Widget::splitArgs $args Preferences::Node Tree::Node]

    set node [Widget::nextIndex $path $node]

    ## Add a node in the tree.
    set n [eval [list $pane1.t insert $idx $parent $node] $maps(Tree::Node)]

    Widget::init Preferences::Node $path.$n $maps(Preferences::Node)

    set window [Widget::getoption $path.$node -pagewindow]
    if {![string length $window]} {
        Widget::setoption $path.$node -pagewindow $pane2.f.f$node
    }

    if {[Widget::getoption $path.$node -haspage]
        && [Widget::getoption $path.$n -createpage]} { _create_node $path $n }

    return $n
}


proc Preferences::delete { path args } {
    Widget::getVariable $path data
    Widget::getVariable $path pane1
    Widget::getVariable $path pane2

    foreach node $args {
        destroy $pane2.f.f$node
        $pane1.t delete $node
        Widget::destroy $path.$node 0
        if {[info exists data($node,realized)]} { unset data($node,realized) }
    }
    
    if {![exists $path $data(select)]} { set data(select) "" }
}


proc Preferences::nodes { path node {first ""} {last ""} } {
    Widget::getVariable $path pane1
    return [$pane1.t nodes $node $first $last]
}


proc Preferences::parent { path node } {
    Widget::getVariable $path pane1
    return [$pane1.t parent $node]
}


proc Preferences::exists { path node } {
    Widget::getVariable $path pane1
    return [Tree::exists $pane1.t $node]
}


proc Preferences::reset { path } {
    Widget::getVariable $path data
    if {[string length $data(select)]} {
        grid remove [Widget::getoption $path.$data(select) -pagewindow]
        set data(select) ""
        Preferences::selection $path clear
    }
}


proc Preferences::raise { path {node ""} } {
    Widget::getVariable $path data
    Widget::getVariable $path pane1
    Widget::getVariable $path pane2

    if {![string length $node]} { return $data(select) }

    Tree::selection $pane1.t set $node

    if {![Widget::getoption $path.$node -haspage]} { return }

    if {[string equal $data(select) $node]} { return }

    set old $data(select)

    set data(select) $node

    set window [Widget::getoption $path.$node -pagewindow]

    if {![winfo exists $window]} { _create_node $path $node }

    if {![info exists data($node,realized)]} {
        set data($node,realized) 1
        set cmd [Widget::getoption $path.$node -createcommand]
        if {[string length $cmd]} { uplevel #0 $cmd }
    }

    set cmd [Widget::getoption $path.$node -raisecommand]
    if {[string length $cmd]} { uplevel #0 $cmd }
    
    if {![string equal $data(select) $old]} {
        set oldwindow ""
        if {[string length $old]} {
            set oldwindow [Widget::getoption $path.$old -pagewindow]

            if {![string equal $window $oldwindow]} {
                grid remove [Widget::getoption $path.$old -pagewindow]
            }
        }
        if {![string equal $window $oldwindow]} {
            grid $window -in $pane2.f -sticky news
        }
    }
}


proc Preferences::open { path node {recurse 0} } {
    Widget::getVariable $path pane1
    $pane1.t opentree $node $recurse
}


proc Preferences::close { path node {recurse 0} } {
    Widget::getVariable $path pane1
    $pane1.t closetree $node $recurse
}


proc Preferences::toggle { path node } {
    Widget::getVariable $path pane1
    $pane1.t toggle $node
}


proc Preferences::selection { path args } {
    Widget::getVariable $path pane1
    return [eval $pane1.t selection $args]
}


proc Preferences::index { path node } {
    Widget::getVariable $path pane1
    return [eval $pane1.t index $node]
}


proc Preferences::edit { path args } {
    Widget::getVariable $path pane1
    return [eval $pane1.t edit $args]
}


proc Preferences::see { path node } {
    Widget::getVariable $path pane1
    return [$pane1.t see $node]
}


proc Preferences::_create_node { path node } {
    Widget::getVariable $path pane2
    set frame  $pane2.f.f$node
    set window [Widget::getoption $path.$node -pagewindow]
    if {![string equal $frame $window] || [winfo exists $frame]} { return }

    Widget::setoption $path.$node -created 1

    frame $frame
}
Added lib/BWidget/progressbar.tcl.


































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# ----------------------------------------------------------------------------
#  progressbar.tcl
#  This file is part of Unifix BWidget Toolkit
# ----------------------------------------------------------------------------
#  Index of commands:
#     - ProgressBar::create
#     - ProgressBar::configure
#     - ProgressBar::cget
#     - ProgressBar::_destroy
#     - ProgressBar::_modify
# ----------------------------------------------------------------------------

namespace eval ProgressBar {
    Widget::define ProgressBar progressbar

    Widget::declare ProgressBar {
        {-type        Enum       normal     0
                      {normal incremental infinite nonincremental_infinite}}
        {-maximum     Int        100        0 "%d >= 0"}
        {-background  Color      "SystemButtonFace" 0}
        {-foreground  Color      "blue"     0 label}
        {-troughcolor Color      "SystemScrollbar"  0}
        {-borderwidth TkResource 2          0 frame}
        {-relief      TkResource sunken     0 label}
        {-orient      Enum       horizontal 1 {horizontal vertical}}
        {-variable    String     ""         0}
        {-idle        Boolean    0          0}
        {-width       TkResource 100        0 frame}
        {-height      TkResource 4m         0 frame}
        {-bg          Synonym    -background}
        {-fg          Synonym    -foreground}
        {-bd          Synonym    -borderwidth}
    }

    Widget::addmap ProgressBar "" :cmd {-background {} -width {} -height {}}
    Widget::addmap ProgressBar "" .bar {
	-troughcolor -background -borderwidth {} -relief {}
    }

    variable _widget
}


# ----------------------------------------------------------------------------
#  Command ProgressBar::create
# ----------------------------------------------------------------------------
proc ProgressBar::create { path args } {
    variable _widget

    Widget::initArgs ProgressBar $args maps

    eval frame $path $maps(:cmd) -class ProgressBar -bd 0 \
	    -highlightthickness 0 -relief flat

    Widget::initFromODB ProgressBar $path $maps(ProgressBar)

    set c  [eval [list canvas $path.bar] $maps(.bar) -highlightthickness 0]
    set fg [Widget::cget $path -foreground]
    if { [string equal [Widget::cget $path -orient] "horizontal"] } {
        $path.bar create rectangle -1 0 0 0 -fill $fg -outline $fg -tags rect
    } else {
        $path.bar create rectangle 0 1 0 0 -fill $fg -outline $fg -tags rect
    }

    set _widget($path,val) 0
    set _widget($path,dir) 1
    set _widget($path,var) [Widget::cget $path -variable]
    if {$_widget($path,var) != ""} {
        BWidget::traceglobal variable $_widget($path,var) w \
		[list ProgressBar::_modify $path]
        set _widget($path,afterid) \
	    [after idle [list ProgressBar::_modify $path]]
    }

    bind $path.bar <Destroy>   [list ProgressBar::_destroy $path]
    bind $path.bar <Configure> [list ProgressBar::_modify $path]

    return [Widget::create ProgressBar $path]
}


# ----------------------------------------------------------------------------
#  Command ProgressBar::configure
# ----------------------------------------------------------------------------
proc ProgressBar::configure { path args } {
    variable _widget

    set res [Widget::configure $path $args]

    if { [Widget::hasChangedX $path -variable] } {
	set newv [Widget::cget $path -variable]
        if { $_widget($path,var) != "" } {
            BWidget::traceglobal vdelete $_widget($path,var) w \
		    [list ProgressBar::_modify $path]
        }
        if { $newv != "" } {
            set _widget($path,var) $newv
            BWidget::traceglobal variable $newv w \
		    [list ProgressBar::_modify $path]
	    if {![info exists _widget($path,afterid)]} {
		set _widget($path,afterid) \
		    [after idle [list ProgressBar::_modify $path]]
	    }
        } else {
            set _widget($path,var) ""
        }
    }

    foreach {cbd cor cma} [Widget::hasChangedX $path -borderwidth \
	    -orient -maximum] break

    if { $cbd || $cor || $cma } {
	if {![info exists _widget($path,afterid)]} {
	    set _widget($path,afterid) \
		[after idle [list ProgressBar::_modify $path]]
	}
    }
    if { [Widget::hasChangedX $path -foreground] } {
	set fg [Widget::cget $path -foreground]
        $path.bar itemconfigure rect -fill $fg -outline $fg
    }
    return $res
}


# ----------------------------------------------------------------------------
#  Command ProgressBar::cget
# ----------------------------------------------------------------------------
proc ProgressBar::cget { path option } {
    return [Widget::cget $path $option]
}


# ----------------------------------------------------------------------------
#  Command ProgressBar::_modify
# ----------------------------------------------------------------------------
proc ProgressBar::_modify { path args } {
    variable _widget

    catch {unset _widget($path,afterid)}
    if { ![BWidget::globalexists $_widget($path,var)] ||
	 [set val [BWidget::getglobal $_widget($path,var)]] < 0 } {
        catch {place forget $path.bar}
    } else {
	place $path.bar -relx 0 -rely 0 -relwidth 1 -relheight 1
	set type [Widget::getoption $path -type]
	if { $val != 0 && $type != "normal" && \
		$type != "nonincremental_infinite"} {
	    set val [expr {$val+$_widget($path,val)}]
	}
	set _widget($path,val) $val
	set max [Widget::getoption $path -maximum]
	set bd  [expr {2*[$path.bar cget -bd]}]
	set w   [winfo width  $path.bar]
	set h   [winfo height $path.bar]
	if {$type == "infinite" || $type == "nonincremental_infinite"} {
	    # JDC: New infinite behaviour
	    set tval [expr {$val % $max}]
	    if { $tval < ($max / 2.0) } {
		set x0 [expr {double($tval) / double($max) * 1.5}]
	    } else {
		set x0 [expr {(1.0-(double($tval) / double($max))) * 1.5}]
	    }
	    set x1 [expr {$x0 + 0.25}]
	    # convert coords to ints to prevent triggering canvas refresh
	    # bug related to fractional coords
	    if {[Widget::getoption $path -orient] == "horizontal"} {
		$path.bar coords rect [expr {int($x0*$w)}] 0 \
		    [expr {int($x1*$w)}] $h
	    } else {
		$path.bar coords rect 0 [expr {int($h-$x0*$h)}] $w \
		    [expr {int($x1*$h)}]
	    }
	} else {
	    if { $val > $max } {set val $max}
	    if {[Widget::getoption $path -orient] == "horizontal"} {
		$path.bar coords rect -1 0 [expr {int($val*$w/$max)}] $h
	    } else {
		$path.bar coords rect 0 [expr {$h+1}] $w \
		    [expr {int($h*(1.0 - double($val)/$max))}]
	    }
	}
    }
    if {![Widget::cget $path -idle]} {
	update idletasks
    }
}


# ----------------------------------------------------------------------------
#  Command ProgressBar::_destroy
# ----------------------------------------------------------------------------
proc ProgressBar::_destroy { path } {
    variable _widget

    if {[info exists _widget($path,afterid)]} {
	after cancel $_widget($path,afterid)
	unset _widget($path,afterid)
    }
    if {[info exists _widget($path,var)]} {
	if {$_widget($path,var) != ""} {
	    BWidget::traceglobal vdelete $_widget($path,var) w \
		[list ProgressBar::_modify $path]
	}
	unset _widget($path,var)
    }
    unset _widget($path,dir)
    Widget::destroy $path
}
Added lib/BWidget/progressdlg.tcl.
















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# ----------------------------------------------------------------------------
#  progressdlg.tcl
#  This file is part of Unifix BWidget Toolkit
# ----------------------------------------------------------------------------
#  Index of commands:
#     - ProgressDlg::create
# ----------------------------------------------------------------------------

namespace eval ProgressDlg {
    Widget::define ProgressDlg progressdlg Dialog ProgressBar

    Widget::bwinclude ProgressDlg Dialog :cmd \
        remove {
            -modal -image -bitmap -side -anchor -cancel -default
            -homogeneous -padx -pady -spacing
        }

    Widget::bwinclude ProgressDlg ProgressBar .frame.pb \
        remove {-orient -width -height}

    Widget::declare ProgressDlg {
        {-width        TkResource 25 0 label}
        {-height       TkResource 2  0 label}
        {-textvariable String     "" 0}
        {-font         String     "TkTextFont" 0}
        {-stop         String "" 0}
        {-command      String "" 0}
    }

    Widget::addmap ProgressDlg :cmd .frame.msg \
        {-width {} -height {} -textvariable {} -font {} -background {}}
}


# ----------------------------------------------------------------------------
#  Command ProgressDlg::create
# ----------------------------------------------------------------------------
proc ProgressDlg::create { path args } {
    Widget::initArgs ProgressDlg $args maps

    eval [list Dialog::create $path] $maps(:cmd) \
	 [list -image [Bitmap::get hourglass]] \
         -modal none -side bottom -anchor c -class ProgressDlg -spacing 0

    Widget::initFromODB ProgressDlg "$path#ProgressDlg" $maps(ProgressDlg)

    wm protocol $path WM_DELETE_WINDOW {;}

    set frame [Dialog::getframe $path]
    bind $frame <Destroy> [list Widget::destroy $path\#ProgressDlg]
    $frame configure -cursor watch

    eval [list label $frame.msg] $maps(.frame.msg) \
	-relief flat -borderwidth 0 \
	    -highlightthickness 0 -anchor w -justify left
    pack $frame.msg -side top -pady 3m -anchor nw -fill x -expand yes

    eval [list ProgressBar::create] $frame.pb $maps(.frame.pb) -width 100
    pack $frame.pb -side bottom -anchor w -fill x -expand yes

    set stop [Widget::cget "$path#ProgressDlg" -stop]
    set cmd  [Widget::cget "$path#ProgressDlg" -command]
    if { $stop != "" && $cmd != "" } {
        set width [string length $stop]
        if {$width < 12} { set width 12 }
        Dialog::add $path -text $stop -name $stop -command $cmd -width $width
    }
    Dialog::draw $path
    BWidget::grab local $path

    return [Widget::create ProgressDlg $path 0]
}


# ----------------------------------------------------------------------------
#  Command ProgressDlg::configure
# ----------------------------------------------------------------------------
proc ProgressDlg::configure { path args } {
    return [Widget::configure "$path#ProgressDlg" $args]
}


# ----------------------------------------------------------------------------
#  Command ProgressDlg::cget
# ----------------------------------------------------------------------------
proc ProgressDlg::cget { path option } {
    return [Widget::cget "$path#ProgressDlg" $option]
}
Added lib/BWidget/properties.tcl.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
# -----------------------------------------------------------------------------
#  $Id$
# -----------------------------------------------------------------------------
#  Index of commands:
#
#   Public Commands:
#     - Properties::create
#     - Properties::configure
#     - Properties::cget
#     - Properties::getframe
#     - Properties::insert
#     - Properties::delete
#     - Properties::nodes
#     - Properties::raise
#     - Properties::open
#     - Properties::close
#     - Properties::toggle
#
#   Private Commands:
#     - Properties::_resize
#     - Properties::_destroy
# -----------------------------------------------------------------------------

package require Tk 8.4
package require Tktable

namespace eval Properties {
    Widget::define Properties properties ComboBox Button

    Widget::declare Properties::Node {
	{-data               String  ""        0}
	{-open               Boolean "0"       0}
	{-text               String  ""        0}
	{-font               String  ""        0} 
	{-state              Enum    "normal"  0 {normal disabled hidden}}
	{-width              Int     "0"       0}
	{-height             Int     "0"       0}
	{-window             String  ""        0}
        {-multiline          Boolean "0"       0}

	{-padx               Padding ""        0 "%d >= 0"}
	{-pady               Padding "0 8"     0 "%d >= 0"}
	{-ipadx              Int     ""        0 "%d >= 0"}
	{-ipady              Int     ""        0 "%d >= 0"}
        {-cellpadx           Int     ""        0 "%d >= 0"}
        {-cellpady           Int     ""        0 "%d >= 0"}
        {-selectable         Boolean 1         0}

        {-browseargs         String      ""        0}

	{-opencommand        String  ""        0}
	{-closecommand       String  ""        0}
	{-editstartcommand   String  ""        0}
	{-editfinishcommand  String  ""        0}
	{-editcancelcommand  String  ""        0}
    }

    DynamicHelp::include Properties::Node balloon

    Widget::declare Properties::Property {
	{-data               String      ""        0}
	{-text               String      ""        0}
	{-font               String      ""        0} 
	{-state              Enum        "normal"  0 {normal disabled hidden}}
	{-value              String      ""        0}
	{-window             String      ""        0}
	{-variable           String      ""        0}
	{-editable           Boolean     "1"       0}
	{-editwindow         String      ""        0}

	{-values             String      ""        0}
        {-valuescommand      String      ""        0}
        
        {-browseargs         String      ""        0}
	{-browsebutton       Boolean     "0"       0}
        {-browsecommand      String      ""        0}

        {-postcommand        String      ""        0}
	{-modifycommand      String      ""        0}

	{-editstartcommand   String      ""        0}
	{-editfinishcommand  String      ""        0}
	{-editcancelcommand  String      ""        0}
    }

    DynamicHelp::include Properties::Property balloon

    Widget::tkinclude Properties canvas .c \
	remove {
	    -insertwidth -insertbackground -insertborderwidth -insertofftime
	    -insertontime -selectborderwidth -closeenough -confine -scrollregion
            -state
	} initialize {
	    -relief flat -borderwidth 2 -takefocus 1
	    -highlightthickness 0 -width 400
	}

    Widget::declare Properties {
	{-font               String      "TkTextFont" 0}
	{-state              Enum        "normal"  0 {normal disabled}}
	{-expand             Boolean     "0"       0}
	{-redraw             Boolean     "1"       0}
	{-drawmode           Enum        "normal"  0 {normal slow fast}}
        {-multiline          Boolean     "0"       0}

	{-padx               Padding     "0"       0 "%d >= 0"}
	{-pady               Padding     "4"       0 "%d >= 0"}
	{-ipadx              Int         "4"       0 "%d >= 0"}
	{-ipady              Int         "4"       0 "%d >= 0"}
        {-cellpadx           Int         "2"       0 "%d >= 0"}
        {-cellpady           Int         "1"       0 "%d >= 0"}

        {-browseargs         String      ""        0}
        {-helpcolumn         Enum        "label"   1 {both label value}}

	{-opencommand        String      ""        0}
	{-closecommand       String      ""        0}
	{-editstartcommand   String      ""        0}
	{-editfinishcommand  String      ""        0}
	{-editcancelcommand  String      ""        0}
    }

    bind Properties <Map>       [list Properties::_realize %W]
    bind Properties <Destroy>   [list Properties::_destroy %W]
    bind Properties <Configure> [list Properties::_resize %W]

    bind PropertiesTable <1>        [list Properties::_button_1 %W %x %y]
    bind PropertiesTable <Double-1> [list Properties::_double_button_1 %W %x %y]

    bind Properties <FocusIn>   [list after idle {BWidget::refocus %W %W.c}]
    bind PropertiesCanvas <1>   [list Properties::_focus_canvas %W]

    BWidget::bindMouseWheel PropertiesCanvas
}


# -----------------------------------------------------------------------------
#  Command Properties::create
# -----------------------------------------------------------------------------
proc Properties::create { path args } {
    Widget::initArgs Properties $args maps

    frame $path -class Properties -bd 0 -highlightthickness 0 \
    	-relief flat -takefocus 0

    Widget::initFromODB Properties $path $maps(Properties)

    eval [list canvas $path.c] -width 400 $maps(.c)
    bindtags $path.c [concat PropertiesCanvas [bindtags $path.c]]
    pack $path.c -expand 1 -fill both

    $path.c bind c: <1>        [list Properties::_toggle_cross $path]
    $path.c bind l: <1>        [list Properties::_select_node  $path]
    $path.c bind l: <Double-1> [list Properties::_toggle_cross $path]

    Widget::getVariable $path data

    set data(selected)    ""
    set data(realized)    0
    set data(redrawlevel) 0

    set data(nodes,root)  [list]

    return [Widget::create Properties $path]
}


# -----------------------------------------------------------------------------
#  Command Properties::configure
# -----------------------------------------------------------------------------
proc Properties::configure { path args } {
    set res [Widget::configure $path $args]

    set redraw [Widget::anyChangedX $path -padx -pady -ipadx -ipady -expand]

    if {[Widget::hasChanged $path -font font]} {
        _configure_tables $path -font $font
        set redraw 1
    }

    if {[Widget::hasChanged $path -state state]} {
        _configure_tables $path -state $state
    }

    if {$redraw && [Widget::getoption $path -redraw]} {
        _redraw_idle $path
    }

    return $res
}


# -----------------------------------------------------------------------------
#  Command Properties::cget
# -----------------------------------------------------------------------------
proc Properties::cget { path option } {
    return [Widget::cget $path $option]
}


proc Properties::itemcget { path node option } {
    if {![Properties::exists $path $node]} {
        return -code error "node \"$node\" does not exist"
    }
    return [Widget::cget $path.$node $option]
}


proc Properties::itemconfigure { path node args } {
    Widget::getVariable $path data

    if {![info exists data($node)]} {
        return -code error "node \"$node\" does not exist"
    }

    set lastState [Widget::getoption $path.$node -state]

    if {![string equal $data($node) "root"]} {
        set lastVar [Widget::getoption $path.$node -variable]
    }

    set res [Widget::configure $path.$node $args]

    if {[string equal $data($node) "root"]} {
	set redraw 0

	## We always redraw when a node is opened or closed, regardless
	## of the -redraw option for the widget.
	if {[Widget::hasChanged $path.$node -open open]} {
            set redraw 1

            if {$open} {
                set command [_option $path root $node -opencommand]
                _eval_command $path root $node $command
            } else {
                set command [_option $path root $node -closecommand]
                _eval_command $path root $node $command
            }
        }

	if {[Widget::hasChanged $path.$node -state state]} {
	    ## If we're changing to or from a hidden state, we need
	    ## to redraw all the tables.  Otherwise, we're just
	    ## changing from normal or disabled and no redraw is
	    ## necessary.
	    if {[string equal $state "hidden"]
	    	|| [string equal $lastState "hidden"]} {
		## Only redraw if the user wants us to.
		if {[Widget::getoption $path -redraw]} { set redraw 1 }
	    }
	}

	if {$redraw} { _redraw_idle $path 2 }
    } else {
	if {[Widget::hasChanged $path.$node -state state]} {
	    ## If we're changing to or from a hidden state, we need
	    ## to redraw all the tables.  Otherwise, we're just
	    ## changing from normal or disabled and no redraw is
	    ## necessary.
	    if {[string equal $state "hidden"]
	    	|| [string equal $lastState "hidden"]} {
		## Only redraw if the user wants us to.
		if {[Widget::getoption $path -redraw]} { _redraw_idle $path }
	    }
	}

        if {[Widget::hasChanged $path.$node -value value]} {
            set varName [Widget::getoption $path.$node -variable]
            if {[string length $varName]} {
                upvar #0 $varName var
                set var $value
            } else {
                _redraw_properties $path $data($node)
            }
        }

        if {[Widget::hasChanged $path.$node -variable variable]} {
            _trace_variable $path $node
        }

        if {[Widget::anyChangedX $path.$node -helpvar -helptype -helptext]} {
            _configure_help $path $node 1
        }
    }

    return $res
}


proc Properties::tagcget { path node which option } {
    Widget::getVariable $path data

    if {![info exists data($node)]} {
        return -code error "node \"$node\" does not exists"
    }

    set parent $data($node)
    if {$parent eq "root"} {
        set table $path.t$node
    } else {
        set table $path.t$parent
    }

    if {[$table tag exists $node-$which]} {
        return [$table tag cget $node-$which $option]
    }

    if {[$table tag exists $parent-$which]} {
        return [$table tag cget $parent-$which $option]
    }

    return [$table cget $option]
}


proc Properties::tagconfigure { path node which args } {
    Widget::getVariable $path data

    if {![info exists data($node)]} {
        return -code error "node \"$node\" does not exists"
    }

    switch -- $which {
        "label" {
            set col 0
        }

        "value" {
            set col 1
        }

        default {
            return [BWidget::badOptionString value $which [list label value]]
        }
    }

    set tag $node-$which

    set parent $data($node)
    if {$parent eq "root"} {
        set table  $path.t$node
        set parent $node
    } else {
        set table $path.t$parent
    }

    if {![winfo exists $table]} {
        _create_root_node $path root $parent
    }

    return [eval [list $table tag configure $tag] $args]
}


# -----------------------------------------------------------------------------
#  Command Properties::insert
# -----------------------------------------------------------------------------
proc Properties::insert { path idx parent node args } {
    Widget::getVariable $path data

    if {![info exists data(nodes,$parent)]} {
        return -code error "node \"$parent\" does not exist"
    }

    set node [Widget::nextIndex $path $node]

    if {[info exists data($node)]} {
        return -code error "node \"$node\" already exists"
    }

    set drawmode [Widget::getoption $path -drawmode]

    if {[string equal $parent "root"]} {
	Widget::init Properties::Node $path.$node $args

        set data($node) $parent
	set data(nodes,$node) [list]

        if {$idx eq "end"} {
            lappend data(nodes,root) $node
        } else {
            set data(nodes,root) [linsert $data(nodes,root) $idx $node]
        }

        if {[string equal $drawmode "fast"]} {
            _create_root_node $path $parent $node
        }
    } else {
	Widget::init Properties::Property $path.$node $args

        set data($node) $parent
        set varName [Widget::getoption $path.$node -variable]
        if {![string equal $varName ""] && ![string match "::*" $varName]} {
            Widget::setoption $path.$node -variable ::$varName
        }

        if {$idx eq "end"} {
            lappend data(nodes,$parent) $node
        } else {
            set data(nodes,$parent) [linsert $data(nodes,$parent) $idx $node]
        }

        if {[string length $varName]} { _trace_variable $path $node }
    }

    if {[Widget::getoption $path -redraw]} { _redraw_idle $path }

    return $node
}


# -----------------------------------------------------------------------------
#  Command Properties::delete
# -----------------------------------------------------------------------------
proc Properties::delete { path args } {
    Widget::getVariable $path data

    foreach node $args {
        if {[info exists data(editing)] && $node eq $data(editing)} {
            Properties::edit $path cancel
        }

	set pnode $data($node)
	Widget::destroy $path.$node 0
	if {[string equal $pnode "root"]} {
	    destroy $path.t$node

            foreach prop $data(nodes,$node) {
                Widget::destroy $path.$node 0
                Properties::_untrace_variable $path $node
            }

	    unset data(nodes,$node)
	}

        if {[info exists data(nodes,$pnode)]} {
            set data(nodes,$pnode) [BWidget::lremove $data(nodes,$pnode) $node]
        }
    }

    if {[Widget::getoption $path -redraw]} { _redraw_idle $path }
}


# -----------------------------------------------------------------------------
#  Command Properties::nodes
# -----------------------------------------------------------------------------
proc Properties::nodes { path node {first ""} {last ""} } {
    Widget::getVariable $path data

    if {![info exists data(nodes,$node)]} {
        return -code error "node \"$node\" does not exist"
    }

    if {![string length $first]} { return $data(nodes,$node) }
    if {![string length $last]}  { return [lindex $data(nodes,$node) $first] }
    return [lrange $data(nodes,$node) $first $last]
}


# -----------------------------------------------------------------------------
#  Command Properties::open
# -----------------------------------------------------------------------------
proc Properties::open { path node {recurse 0} } {
    $path itemconfigure $node -open 1
}


# -----------------------------------------------------------------------------
#  Command Properties::close
# -----------------------------------------------------------------------------
proc Properties::close { path node {recurse 0} } {
    Widget::getVariable $path data

    $path itemconfigure $node -open 0

    ## If we're editing a property in the table we're closing,
    ## finish the edit.
    if {[info exists data(editing)]
        && [lsearch -exact $data(nodes,$node) $data(editing)] > -1} {
        $path edit finish
    }
}


# -----------------------------------------------------------------------------
#  Command Properties::toggle
# -----------------------------------------------------------------------------
proc Properties::toggle { path node } {
    if {[Widget::getoption $path.$node -open]} {
        Properties::close $path $node
    } else {
        Properties::open $path $node
    }
}


proc Properties::edit { path command {node ""} {focus ""} } {
    Widget::getVariable $path data
    Widget::getVariable $path nodes

    if {[info exists data(editing)] && ![info exists data($data(editing))]} {
        unset data(editing)
    }

    switch -- $command {
	"start" {
            if {![info exists data($node)]} {
                return -code error "node \"$node\" does not exist"
            }

	    _start_edit $path $path.t$data($node) $node $focus
	}

	"finish" - "cancel" {
	    if {![info exists data(editing)]} { return }

	    set node   $data(editing)
	    set parent $data($node)
            set table  $path.t$parent

	    set cmd [_option $path $parent $node -edit${command}command]
            if {![_eval_command $path $parent $node $cmd]} { return }

            ## If this is a cancel, reset the original value.
            if {[string equal $command "cancel"]} {
                $path itemconfigure $node -value $data(value)
                event generate $path <<PropertiesEditCancel>>
            } else {
                event generate $path <<PropertiesEditFinish>>
            }

	    destroy $path.edit

            Widget::getVariable $path.$parent tableData
            set row $nodes($parent,$node)
            set tableData($row,1) [_get_value $path $node]
            $table selection clear all

            set vars [list editing editpath entrypath browsepath valuespath]
            foreach var $vars {
                if {[info exists data($var)]} { unset data($var) }
            }
	}

        "reread" {
	    if {[info exists data(editing)]} {
                upvar #0 [Properties::variable $path $data(editing)] var
                set var $data(value)
            }
        }

	"active" - "current" {
	    if {[info exists data(editing)]} { return $data(editing) }
	}

        "value"      -
        "values"     -
        "editable"   -
        "editpath"   -
        "entrypath"  -
        "editwindow" -
        "browsepath" -
        "valuespath" {
	    if {[info exists data(editing)]} { return $data($command) }
        }

        default {
            return -code error "invalid edit property \"$command\""
        }
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::xview
# ----------------------------------------------------------------------------
proc Properties::xview { path args } {
    return [eval [list $path.c xview] $args]
}


# ----------------------------------------------------------------------------
#  Command Tree::yview
# ----------------------------------------------------------------------------
proc Properties::yview { path args } {
    return [eval [list $path.c yview] $args]
}


proc Properties::exists { path node } {
    return [Widget::exists $path.$node]
}


proc Properties::reorder { path node neworder } {
    Widget::getVariable $path data

    if {![info exists data(nodes,$node)]} {
        return -code error "node \"$node\" does not exist"
    }

    set data(nodes,$node) $neworder
    _redraw_idle $path
}


proc Properties::redraw { path } {
    Widget::getVariable $path data

    _redraw_nodes  $path
    _resize        $path

    set data(redrawlevel) 0
}


proc Properties::parent { path node } {
    Widget::getVariable $path data
    if {![info exists data($node)]} {
        return -code error "node \"$node\" does not exist"
    }
    return $data($node)
}


proc Properties::bindLabel { path args } {
    Widget::getVariable $path data
    Widget::getVariable $path events
    Widget::getVariable $path labelEvents

    if {![llength $args]} {
        set list [list]
        foreach event [lsort [array names labelEvents]] {
            lappend list $event $labelEvents($event)
        }
        return $list
    } elseif {[llength $args] == 1} {
        set event [lindex $args 0]
        if {![info exists labelEvents($event)]} { return }
        return $labelEvents($event)
    } elseif {[llength $args] != 2} {
        set err [BWidget::wrongNumArgsString "$path bindLabel ?event? ?script?"]
        return -code error $err
    }

    BWidget::lassign $args event script
    if {![string length $script]} {
        if {[info exists events($event)]} { unset events($event) }
        if {[info exists labelEvents($event)]} { unset labelEvents($event) }
    } else {
        set events($event) 1
        set labelEvents($event) $script
    }
}

proc Properties::bindValue { path args } {
    Widget::getVariable $path data
    Widget::getVariable $path events
    Widget::getVariable $path valueEvents

    if {![llength $args]} {
        set list [list]
        foreach event [lsort [array names valueEvents]] {
            lappend list $event $valueEvents($event)
        }
        return $list
    } elseif {[llength $args] == 1} {
        set event [lindex $args 0]
        if {![info exists valueEvents($event)]} { return }
        return $valueEvents($event)
    } elseif {[llength $args] != 2} {
        set err [BWidget::wrongNumArgsString "$path bindValue ?event? ?script?"]
        return -code error $err
    }

    BWidget::lassign $args event script
    if {![string length $script]} {
        if {[info exists events($event)]} { unset events($event) }
        if {[info exists valueEvents($event)]} { unset valueEvents($event) }
    } else {
        set events($event) 1
        set valueEvents($event) $script
    }
}


proc Properties::variable { path node } {
    Widget::getVariable $path data
    if {![info exists data($node)]} {
        return -code error "node \"$node\" does not exist"
    }

    set varName [Widget::getoption $path.$node -variable]
    if {![string length $varName]} {
        set varName [Widget::varForOption $path.$node -value]
    }
    return $varName
}

proc Properties::_handle_event { table coords event map } {
    set path [winfo parent $table]

    Widget::getVariable $path data
    Widget::getVariable $path nodes

    set row [$table index @$coords row]
    set col [$table index @$coords col]

    if {$col == 0} {
        Widget::getVariable $path labelEvents events
    } elseif {$col == 1} {
        Widget::getVariable $path valueEvents events
    }

    if {![info exists events($event)]} { return }

    set node   $nodes($table,$row)
    set parent $data($node)
    lappend map %p $parent %n $node

    uplevel #0 [string map $map $events($event)]
}


proc Properties::_create_root_node { path parent node } {
    Widget::getVariable $path data

    set table $path.t$node
    if {[winfo exists $table]} { return }

    set bg    [Widget::cget $path -background]
    set font  [Widget::cget $path -font]
    set padx  [_option $path root $node -cellpadx]
    set pady  [_option $path root $node -cellpady]
    set width [Widget::cget $path -width]
    set multi [_option $path root $node -multiline]

    table $table -cols 2 -rows 0 -colstretchmode last \
        -state disabled -anchor w -justify left -highlightthickness 0 \
        -background $bg -font $font -resizeborder col \
        -bordercursor sb_h_double_arrow -cursor "" -multiline $multi \
        -maxheight 10000 -maxheight 10000 -padx $padx -pady $pady \
        -variable [Widget::widgetVar $path.$node tableData]

    $table tag configure sel    -relief sunken -background $bg \
        -foreground #000000
    $table tag configure active -relief sunken -background $bg \
        -foreground #000000

    $table tag col $node-label 0
    $table tag col $node-value 1

    DynamicHelp::add $table -col 1 \
        -command [list Properties::_display_text_balloon $path %W %r]

    set top [winfo toplevel $table]
    bindtags $table [list $table PropertiesTable Table $top all]

    set width -[expr {$width / 2}]
    $table width 0 $width 1 $width
}


proc Properties::_start_edit { path table node {focus ""} } {
    Widget::getVariable $path data
    Widget::getVariable $path nodes

    set parent $data($node)
    set state  [_option $path $parent $node -state normal]

    if {[string equal $state "disabled"]} { return }

    if {[info exists data(editing)]} {
        Properties::edit $path finish

        if {[info exists data(editing)]} {
            ## We couldn't finish editing because of a validation check failure.
            return
        }
    }

    foreach var [list editpath entrypath browsepath valuespath] {
        set data($var) ""
    }

    set var [Properties::variable $path $node]

    set font     [_option $path $parent $node -font]
    set window   [Widget::getoption $path.$node -editwindow]
    set values   [Widget::getoption $path.$node -values]
    set valcmd   [Widget::getoption $path.$node -valuescommand]
    set editable [Widget::getoption $path.$node -editable]

    set combobox 0
    if {[string length $values] || [string length $valcmd]} { set combobox 1 }

    frame $path.edit

    if {![string length $window]} {
	if {![Widget::getoption $path.$node -browsebutton]} {
            if {!$combobox} {
		set widget $path.edit.e
                set entry  $widget
		Entry $entry -bd 1 -font $font -textvariable $var \
                    -editable $editable
	    } else {
                set widget  $path.edit.cb
		set entry   $widget.e
                set modcmd  [Widget::getoption $path.$node -modifycommand]
                set postcmd [Widget::getoption $path.$node -postcommand]

                if {[string length $valcmd]} {
                    _eval_command $path $parent $node $valcmd values
                }

		ComboBox $widget -borderwidth 1 -font $font \
                    -exportselection 0 -hottrack 1 -textvariable $var \
                    -values $values -editable $editable \
                    -postcommand   [_map_command $path $parent $node $postcmd] \
                    -modifycommand [_map_command $path $parent $node $modcmd]

                set data(valuespath) $widget
	    }
	} else {
            if {!$combobox} {
                set widget $path.edit.e
                set entry  $widget
                Entry $entry -bd 1 -font $font -textvariable $var -width 1 \
                    -editable $editable
            } else {
                set widget  $path.edit.combo
		set entry   $widget.e
                set modcmd  [Widget::getoption $path.$node -modifycommand]
                set postcmd [Widget::getoption $path.$node -postcommand]

                if {[string length $valcmd]} {
                    _eval_command $path $parent $node $valcmd values
                }

		ComboBox $widget -borderwidth 1 -font $font \
                    -exportselection 0 -hottrack 1 -textvariable $var \
                    -values $values -editable $editable \
                    -modifycommand $modcmd -postcommand $postcmd

                set data(valuespath) $widget
            }

            set data(browsepath) $path.edit.b

            set args    [_option $path $parent $node -browseargs]
            set command [Widget::getoption $path.$node -browsecommand]
            lappend args -command [_map_command $path $parent $node $command]
            set args [linsert $args 0 -text ...]

            if {[BWidget::using ttk]} {
                eval [list ttk::button $path.edit.b] $args
            } else {
                set args [linsert $args 0 -relief link]
                eval [list Button $path.edit.b] $args

                if {[string length [$path.edit.b cget -image]]} {
                    $path.edit.b configure \
                        -height [expr {[winfo reqheight $entry] - 4}]
                }
            }
            pack $path.edit.b -side right
	}

        pack $widget -side left -expand 1 -fill x
        bind $entry <Escape> "$path edit cancel; break"
        bind $entry <Return> "$path edit finish; break"
    } else {
	## The user has given us a window to use for editing.  Walk
	## through the immediate children and see if we can find an
	## entry widget to focus on.

        place $window -in $path.edit -x 0 -y 0 -relwidth 1.0 -relheight 1.0

        set widget $window
	set entry  $window
	foreach child [winfo children $window] {
	    if {[string equal [winfo class $child] "Entry"]} {
                set entry $child
                break
            }
	}
    }

    upvar #0 $var value
    set data(value)      $value
    set data(values)     $values
    set data(editing)    $node
    set data(editable)   $editable
    set data(editpath)   $path.edit
    set data(entrypath)  $entry
    set data(editwindow) $window

    set cell $nodes($parent,$node),1
    $table window configure $cell -window $data(editpath) -sticky news -padx 2

    if {[string equal [winfo class $entry] "Entry"] && $editable} {
	after idle [list Properties::_select_entry_contents $path $entry]
    }

    update idletasks

    if {$focus eq ""} { set focus $entry }
    focus -force $focus

    set cmd [_option $path $parent $node -editstartcommand]
    if {![_eval_command $path $parent $node $cmd]} { edit $path cancel; return }

    event generate $path <<PropertiesEditStart>>

    ## If we're displaying a combobox with non-editable values,
    ## go ahead and post the combobox.
    if {$combobox && !$editable} { $widget post }
}


proc Properties::_select_node { path {item ""} } {
    Widget::getVariable $path data

    if {![string length $item]} {
    	set item [lindex [$path.c gettags current] 0]
    }

    set state [Widget::cgetOption -state normal $path.$item $path]
    if {[string equal $state "disabled"]
        || ![Widget::getoption $path.$item -selectable]} { return }

    set bg [Widget::cget $path -selectbackground]
    set fg [Widget::cget $path -selectforeground]

    if {[string length $data(selected)]} {
        $path.c itemconfigure l:$data(selected) -fill #000000
    }
    $path.c delete sel

    set i [$path.c find withtag l:$item]
    if {![string length $i]} { return }

    set data(selected) $item

    $path.c create rect [$path.c bbox $i] -fill $bg -width 0 \
    	-tags [list sel $item]
    $path.c itemconfigure l:$item -fill $fg
    $path.c raise l:$item
}


proc Properties::_toggle_cross { path } {
    set item  [lindex [$path.c gettags current] 0]
    set state [Widget::cgetOption -state normal $path.$item $path]

    if {[string equal $state "disabled"]
        || ![Widget::getoption $path.$item -selectable]} { return }

    _select_node $path $item
    $path toggle $item
}


## level 1 = full redraw
## level 2 = redraw tables only
proc Properties::_redraw_idle { path {level 1} } {
    Widget::getVariable $path data

    if {$data(redrawlevel) > 0} { return }

    set data(redrawlevel) $level
    after idle [list Properties::redraw $path]
}


proc Properties::_redraw_nodes { path } {
    Widget::getVariable $path data
    Widget::getVariable $path events

    set map [_bind_map $path]
    set cmd [list Properties::_handle_event %W %x,%y $map]

    if {[info exists data(editing)]} { Properties::edit $path finish }

    $path.c delete all

    set y 0
    foreach node $data(nodes,root) {
        set item $path.$node

        set open  [Widget::getoption $item -open]
        set state [Widget::getoption $item -state]

        if {[string equal $state "hidden"]} { continue }

        set ipadx [Properties::_get_padding $path $item -ipadx 0]
        set ipady [Properties::_get_padding $path $item -ipady 0]

        ## Give everything a 2 padding to the right so that things
        ## don't get clipped of the screen to the left.
        set x  [expr {2 + [Properties::_get_padding $path $item -padx 0]}]
        incr y [Properties::_get_padding $path $item -pady 0]

        set image [BWidget::Icon tree-plus]
        if {$open} { set image [BWidget::Icon tree-minus] }

        ## Add the cross to open and close this table.
        $path.c create image $x $y -image $image -anchor nw \
            -tags [list $node c:$node c:]
        
        ## Create the label to the right of the cross.
	set bbox [$path.c bbox c:$node]
        set tx   [expr {[lindex $bbox 2] + $ipadx}]
        set ty   [expr {$y - 2}]
        set text [Widget::getoption $item -text]
        set font [Widget::cgetOption -font "" $item $path]
        $path.c create text $tx $ty -text $text -font $font -anchor nw \
            -tags [list $node l:$node l:]

        set help [Widget::getoption $item -helptext]
        if {$help ne ""} {
            DynamicHelp::add $path.c -item l:$node -text $help
        }

	set y [expr {[lindex [$path.c bbox l:$node c:$node] end] + $ipady}]

	if {[Widget::getoption $item -open]} {
            set window [Widget::getoption $item -window]
            if {[string length $window] || [llength $data(nodes,$node)]} {
                if {[string length $window]} {
                    set height [winfo reqheight $window]
                } else {
                    set window $path.t$node

                    if {![winfo exists $window]} {
                        _create_root_node $path root $node
                    }

                    foreach event [array names events] {
                        bind $window $event [linsert $cmd end-1 $event]
                    }

                    _redraw_properties $path $node

                    set height [Widget::getoption $item -height]
                }

                $path.c create window $x $y -window $window \
                    -anchor nw -tags [list $node t:$node node]

                if {[Widget::getoption $path -expand]} {
                    set padx  [Properties::_get_padding $path $item -padx 1]
                    set width [winfo width $path.c]
                    $path.c itemconfigure t:$node -width [expr {$width - $padx}]
                }
                incr y $height
            }
	}
	incr y [Properties::_get_padding $path $item -pady 1]
    }

    if {[string length $data(selected)]} { _select_node $path $data(selected) }
}


proc Properties::_redraw_properties { path {nodelist {}} } {
    Widget::getVariable $path data
    Widget::getVariable $path nodes

    if {![llength $nodelist]} { set nodelist $data(nodes,root) }

    foreach parent $nodelist {
        set t $path.t$parent
        Widget::getVariable $path.$parent tableData

        set open  [Widget::getoption $path.$parent -open]
        set state [Widget::getoption $path.$parent -state]

        if {!$open || [string equal $state "hidden"]
            || ![llength $data(nodes,$parent)]} { continue }

        if {![winfo exists $t]} { _create_root_node $path root $parent }

        set data(realized,$parent) 1

        set row 0
	foreach node $data(nodes,$parent) {
            set state [Widget::getoption $path.$node -state]
	    if {[string equal $state "hidden"]} { continue }
            set text  [Widget::getoption $path.$node -text]
            set value [_get_value $path $node]
            set tableData($row,0) $text
            set tableData($row,1) $value
            set nodes($t,$row) $node
            set nodes($parent,$node) $row

            $t tag cell $node-label $row,0
            $t tag cell $node-value $row,1

            incr row

            _configure_help $path $node
	}

        $t configure -rows $row
        Widget::setoption $path.$parent -height [winfo reqheight $t]
    }
}


proc Properties::_option { path parent node option {default ""} } {
    if {[string equal $parent "root"]} {
        set widgets [list $path.$node $path]
    } else {
        set widgets [list $path.$node $path.$parent $path]
    }

    return [eval [list Widget::cgetOption $option $default] $widgets]
}


proc Properties::_focus_canvas { canvas } {
    set path [winfo parent $canvas]
    Widget::getVariable $path data
    edit $path finish
    focus $canvas
}


proc Properties::_resize { path } {
    Widget::getVariable $path data

    if {[Widget::getoption $path -expand]} {
	update idletasks
	set width [winfo width $path.c]
	foreach item [$path.c find withtag node] {
            set node [lindex [$path.c itemcget $item -tags] 0]
            set padx [Properties::_get_padding $path $path.$node -padx 1]
	    $path.c itemconfigure $item -width [expr {$width - $padx}]
	}
	update idletasks
    }

    $path.c configure -scrollregion [$path.c bbox all]
}


proc Properties::_configure_tables { path args } {
    Widget::getVariable $path data

    foreach parent $data(nodes,root) {
        set table $path.t$parent
        eval [list $table configure] $args
    }
}


proc Properties::_button_1 { table x y } {
    if {[string length [$table border mark $x $y]]} { return }
    set path [winfo parent $table]

    Widget::getVariable $path nodes

    set col [$table index @$x,$y col]
    set row [$table index @$x,$y row]

    if {$col == 0} {
        edit $path finish
    }

    if {$col == 1} {
        edit $path start $nodes($table,$row)
    }

    return -code break
}


proc Properties::_double_button_1 { table x y } {

    set col [lindex [$table border mark $x $y col] 0]
    if {![string length $col]} { return }

    set font [$table cget -font]

    set max 0
    foreach string [$table get 0,0 [$table cget -rows],0] {
        set size [font measure $font $string]
        if {$size > $max} { set max $size }
    }
    incr max 5

    $table width 0 -$max
}


proc Properties::_bind_map { path } {
    return [list %%h %h %%w %w %%x %x %%y %y %%X %X %%Y %Y %%T %W %%W $path]
}


proc Properties::_map_command { path parent node command } {
    set var [Properties::variable $path $node]
    set map [list %W $path %p $parent %n $node %v $var]
    return [string map $map $command]
}


proc Properties::_eval_command { path parent node command {resultVarName ""} } {
    if {![string length $command]} { return 1 }
    if {[string length $resultVarName]} { upvar 1 $resultVarName result }
    set command [_map_command $path $parent $node $command]
    set result [uplevel #0 $command]
    if {![string is boolean -strict $result]} { return 1 }
    return $result
}


proc Properties::_get_value { path node } {
    set value   [Widget::getoption $path.$node -value]
    set varName [Widget::getoption $path.$node -variable]
    if {[string length $varName]} {
        upvar #0 $varName var
        if {![info exists var]} { set var "" }
        set value $var
    }
    return $value
}


proc Properties::_untrace_variable { path node } {
    Widget::getVariable $path vars

    if {[info exists vars($path.$node)]} {
        trace remove variable $vars($path.$node) [list write unset] \
            [list Properties::_handle_variable $path $node]
        unset vars($path.$node)
    }
}


proc Properties::_trace_variable { path node } {
    Widget::getVariable $path data
    Widget::getVariable $path vars

    _untrace_variable $path $node

    set varName [Widget::getoption $path.$node -variable]
    if {![string length $varName]} { return }

    if {[info exists $varName]} {
        Widget::setoption $path.$node -value [set $varName]
    }

    trace add variable $varName [list write unset] \
        [list Properties::_handle_variable $path $node]

    set vars($path.$node) $varName
}


proc Properties::_handle_variable { path node name1 name2 op } {
    Widget::getVariable $path data
    Widget::getVariable $path nodes

    set parent  $data($node)
    set varName [Widget::getoption $path.$node -variable]

    switch -- $op {
        "write" {
            Widget::setoption $path.$node -value [set $varName]

            if {![info exists data(editing)] || $data(editing) != $node} {
                if {[info exists nodes($parent,$node)]} {
                    Widget::getVariable $path.$parent tableData

                    set row $nodes($parent,$node)
                    set tableData($row,1) [set $varName]
                }
            }
        }

        "unset" {
            set $varName [Widget::getoption $path.$node -value]
            _trace_variable $path $node
        }
    }
}


proc Properties::_get_padding { path frame option index } {
    set value [Widget::getOption $option "" $frame $path]
    return [Widget::_get_padding $value $index]
}


proc Properties::_configure_help { path node {force 0} } {
    Widget::getVariable $path help

    if {[info exists help($node)] && !$force} { return }

    set help($node) 1

    Widget::getVariable $path nodes

    set parent  [parent $path $node]
    set table   $path.t$parent
    set row     $nodes($parent,$node)
    set text    [Widget::getoption $path.$node -helptext]
    set column  [Widget::getoption $path -helpcolumn]
    set command [Widget::getoption $path.$node -helpcommand]

    set opt  -cell
    set cell $row,0
    if {$column eq "both"} { set opt -row; set cell $row }
    if {$column eq "value"} { set cell $row,1 }

    switch -- [Widget::getoption $path.$node -helptype] {
        "balloon" {
            DynamicHelp::add $table $opt $cell -text $text -command $command
        }

        "variable" {
            DynamicHelp::add $table $opt $cell -text $text -type variable \
                -command $command \
                -variable [Widget::getoption $path.$node -helpvariable]
        }
    }
}


proc Properties::_display_text_balloon { path table row } {
    Widget::getVariable $path nodes

    set node  $nodes($table,$row)
    set value [_get_value $path $node]

    set font    [$table cget -font]
    set measure [font measure $font $value]

    set width [lindex [$table bbox $row,1] 2]
    if {$measure > $width} { return $value }
}


proc Properties::_select_entry_contents { path entry } {
    if {[winfo exists $entry]} {
        $entry selection range 0 end
    }
}


proc Properties::_realize { path } {
    Widget::getVariable $path data

    if {!$data(realized)} {
        set data(realized) 1
        Properties::redraw $path
    }

    if {[string length $data(selected)]} { _select_node $path $data(selected) }
}


# -----------------------------------------------------------------------------
#  Command Properties::_destroy
# -----------------------------------------------------------------------------
proc Properties::_destroy { path } {
    if {[Widget::exists $path]} {
        Widget::getVariable $path data

        foreach node [array names data] {
            Widget::destroy $path.$node 0
            Properties::_untrace_variable $path $node
        }

        Widget::destroy $path
    }
}
Added lib/BWidget/readme.txt.






























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
BWidget ToolKit 1.7.0				December 2003
Copyright (c) 1998-1999 UNIFIX.
Copyright (c) 2001-2002 ActiveState Corp. 

See the file LICENSE.txt for license info (uses Tcl's BSD-style license).

--------------------------------------------------------------------------

WHAT IS BWIDGET ?

The BWidget Toolkit is a high-level Widget Set for Tcl/Tk built using
native Tcl/Tk 8.x namespaces.

The BWidgets have a professional look&feel as in other well known
Toolkits (Tix or Incr Widgets), but the concept is radically different
because everything is pure Tcl/Tk.  No platform dependencies, and no
compiling required.  The code is 100% Pure Tcl/Tk.

The BWidget library was originally developed by UNIFIX Online, and
released under both the GNU Public License and the Tcl license.
BWidget is now maintained as a community project, hosted by
Sourceforge.  Scores of fixes and enhancements have been added by
community developers.  See the ChangeLog file for details.

--------------------------------------------------------------------------

WIDGET LIST (1.7)

Simple Widgets 
      Label           Extended Label widget
      Entry           Extended Entry widget
      Button          Extended Button widget
      ArrowButton     Button widget with an arrow shape.
      ProgressBar     Progress indicator widget
      ScrollView      Display the visible area of a scrolled window
      Separator       3D separator widget

Manager Widgets 
      MainFrame       Manage toplevel with menu, toolbar and statusbar 
      LabelFrame      Frame with a Label
      TitleFrame      Frame with a title
      ScrolledWindow  Generic scrolled widget
      ScrollableFrame Scrollable frame containing widget
      PanedWindow     Tiled layout manager widget
      ButtonBox       Set of buttons with horizontal or vertical layout
      PagesManager    Pages manager widget
      NoteBook        Notebook manager widget
      Dialog          Dialog abstraction with custom buttons

Composite Widgets 
      LabelEntry      LabelFrame containing an Entry widget. 
      ComboBox        ComboBox widget
      SpinBox         SpinBox widget
      Tree            Tree widget
      ListBox         ListBox widget
      MessageDlg      Message dialog box
      ProgressDlg     Progress indicator dialog box
      PasswdDlg       Login/Password dialog box (contributed by Stephane Lavirotte)
      SelectFont      Font selection widget
      SelectColor     Color selection widget

Commands Classes 
      Widget          The Widget base class
      DynamicHelp     Provide help to Tk widget or BWidget
      DragSite        Commands set for Drag facilities
      DropSite        Commands set for Drop facilities
      BWidget         Utilities

--------------------------------------------------------------------------
INSTALLATION AND USE

- On Unix Platform:
  Uncompress the file BWidget-<version>.tar.Z|gz

  To use the BWidget:
  - If you have uncompressed the archive file under the Tcl Library Path
    directory, you only need to do:
      % package require BWidget
  - If not, you have to specify the BWidget installation path in auto_path
    global variable:
      % lappend auto_path <install_path>
      % package require BWidget

  To launch the demo, you need to cd into the demo subdirectory:
      $ cd <install_path>/demo
      $ wish demo.tcl

- On Windows and others Platforms:
  Uncompress the file BWidget-<version>.zip

  To use the BWidget:
  - If you uncompressed the archive file under the Tcl Library Path
    directory, you only need to do:
      % package require BWidget
  - If not, you have to specify the BWidget installation path in auto_path
    global variable:
      % lappend auto_path your_path
      % package require BWidget

  To launch the demo :
      Double click on demo.tcl in the demo subdirectory


Distribution contains these directories:

BWidget-<version>   Root directory and BWidget Tcl sources
   BWman        HTML manual pages
   images       images used by BWidget
   lang         Resources for language customization
   demo         Demo sources
   tests        BWidgets test suite         


--------------------------------------------------------------------------

DOCUMENTATION

HTML manual pages are available in the BWman subdirectory.  Point to
index.html for frame version with tree navigation, or to contents.html
for no frame version.

--------------------------------------------------------------------------

CONTACTS

The BWidget toolkit is maintained on Sourceforge, at
http://www.sourceforge.net/projects/tcllib/
Added lib/BWidget/scrollframe.tcl.










































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# ----------------------------------------------------------------------------
#  scrollframe.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: scrollframe.tcl,v 1.6 2003/10/20 21:23:52 damonc Exp $
# ----------------------------------------------------------------------------
#  Index of commands:
#     - ScrollableFrame::create
#     - ScrollableFrame::configure
#     - ScrollableFrame::cget
#     - ScrollableFrame::getframe
#     - ScrollableFrame::see
#     - ScrollableFrame::xview
#     - ScrollableFrame::yview
#     - ScrollableFrame::_resize
# ----------------------------------------------------------------------------

namespace eval ScrollableFrame {
    Widget::define ScrollableFrame scrollframe

    Widget::declare ScrollableFrame {
        {-background        Color      "SystemButtonFace" 0}
        {-width             Int        0  0 {}}
        {-height            Int        0  0 {}}
        {-areawidth         Int        0  0 {}}
        {-areaheight        Int        0  0 {}}
        {-constrainedwidth  Boolean    0 0}
        {-constrainedheight Boolean    0 0}
        {-xscrollcommand    TkResource "" 0 canvas}
        {-yscrollcommand    TkResource "" 0 canvas}
        {-xscrollincrement  TkResource "" 0 canvas}
        {-yscrollincrement  TkResource "" 0 canvas}
        {-bg                Synonym    -background}
    }

    Widget::addmap ScrollableFrame "" :cmd {
        -background {} -width {} -height {} 
        -xscrollcommand {} -yscrollcommand {}
        -xscrollincrement {} -yscrollincrement {}
    }
    Widget::addmap ScrollableFrame "" .frame {-background {}}

    variable _widget

    bind BwScrollableFrame <Configure> [list ScrollableFrame::_resize %W]
    bind BwScrollableFrame <Destroy>   [list Widget::destroy %W]
}


# ----------------------------------------------------------------------------
#  Command ScrollableFrame::create
# ----------------------------------------------------------------------------
proc ScrollableFrame::create { path args } {
    Widget::initArgs ScrollableFrame $args maps

    set canvas $path
    set frame  $path.frame

    eval [list canvas $canvas] $maps(:cmd) \
        -highlightthickness 0 -borderwidth 0 -relief flat

    Widget::initFromODB ScrollableFrame $path $maps(ScrollableFrame)

    if {[BWidget::using ttk]} {
        ttk::frame $frame
    } else {
        eval [list frame $frame] $maps(.frame) \
            -highlightthickness 0 -borderwidth 0 -relief flat
    }

    $canvas create window 0 0 -anchor nw -window $frame -tags win \
        -width  [Widget::cget $path -areawidth] \
        -height [Widget::cget $path -areaheight]

    bind $frame <Configure> \
	    [list ScrollableFrame::_frameConfigure $canvas $frame %w %h]
    bindtags $path [list $path BwScrollableFrame [winfo toplevel $path] all]

    return [Widget::create ScrollableFrame $path]
}


# ----------------------------------------------------------------------------
#  Command ScrollableFrame::configure
# ----------------------------------------------------------------------------
proc ScrollableFrame::configure { path args } {
    set res [Widget::configure $path $args]
    set upd 0

    set modcw [Widget::hasChanged $path -constrainedwidth cw]
    set modw  [Widget::hasChanged $path -areawidth w]
    if { $modcw || (!$cw && $modw) } {
        if { $cw } {
            set w [winfo width $path]
        }
        set upd 1
    }

    set modch [Widget::hasChanged $path -constrainedheight ch]
    set modh  [Widget::hasChanged $path -areaheight h]
    if { $modch || (!$ch && $modh) } {
        if { $ch } {
            set h [winfo height $path]
        }
        set upd 1
    }

    if { $upd } {
        $path:cmd itemconfigure win -width $w -height $h
    }
    return $res
}


# ----------------------------------------------------------------------------
#  Command ScrollableFrame::cget
# ----------------------------------------------------------------------------
proc ScrollableFrame::cget { path option } {
    return [Widget::cget $path $option]
}


# ----------------------------------------------------------------------------
#  Command ScrollableFrame::getframe
# ----------------------------------------------------------------------------
proc ScrollableFrame::getframe { path } {
    return $path.frame
}

# ----------------------------------------------------------------------------
#  Command ScrollableFrame::see
# ----------------------------------------------------------------------------
proc ScrollableFrame::see { path widget {vert top} {horz left} {xOffset 0} {yOffset 0}} {
    set x0  [winfo x $widget]
    set y0  [winfo y $widget]
    set x1  [expr {$x0+[winfo width  $widget]}]
    set y1  [expr {$y0+[winfo height $widget]}]
    set xb0 [$path:cmd canvasx 0]
    set yb0 [$path:cmd canvasy 0]
    set xb1 [$path:cmd canvasx [winfo width  $path]]
    set yb1 [$path:cmd canvasy [winfo height $path]]
    set dx  0
    set dy  0
    
    if { [string equal $horz "left"] } {
	if { $x1 > $xb1 } {
	    set dx [expr {$x1-$xb1}]
	}
	if { $x0 < $xb0+$dx } {
	    set dx [expr {$x0-$xb0}]
	}
    } elseif { [string equal $horz "right"] } {
	if { $x0 < $xb0 } {
	    set dx [expr {$x0-$xb0}]
	}
	if { $x1 > $xb1+$dx } {
	    set dx [expr {$x1-$xb1}]
	}
    }

    if { [string equal $vert "top"] } {
	if { $y1 > $yb1 } {
	    set dy [expr {$y1-$yb1}]
	}
	if { $y0 < $yb0+$dy } {
	    set dy [expr {$y0-$yb0}]
	}
    } elseif { [string equal $vert "bottom"] } {
	if { $y0 < $yb0 } {
	    set dy [expr {$y0-$yb0}]
	}
	if { $y1 > $yb1+$dy } {
	    set dy [expr {$y1-$yb1}]
	}
    }

    if {($dx + $xOffset) != 0} {
	set x [expr {($xb0+$dx+$xOffset)/[winfo width $path.frame]}]
	$path:cmd xview moveto $x
    }
    if {($dy + $yOffset) != 0} {
	set y [expr {($yb0+$dy+$yOffset)/[winfo height $path.frame]}]
	$path:cmd yview moveto $y
    }
}


# ----------------------------------------------------------------------------
#  Command ScrollableFrame::xview
# ----------------------------------------------------------------------------
proc ScrollableFrame::xview { path args } {
    return [eval [list $path:cmd xview] $args]
}


# ----------------------------------------------------------------------------
#  Command ScrollableFrame::yview
# ----------------------------------------------------------------------------
proc ScrollableFrame::yview { path args } {
    return [eval [list $path:cmd yview] $args]
}


# ----------------------------------------------------------------------------
#  Command ScrollableFrame::_resize
# ----------------------------------------------------------------------------
proc ScrollableFrame::_resize { path } {
    if { [Widget::getoption $path -constrainedwidth] } {
        $path:cmd itemconfigure win -width [winfo width $path]
    }
    if { [Widget::getoption $path -constrainedheight] } {
        $path:cmd itemconfigure win -height [winfo height $path]
    }
}


# ----------------------------------------------------------------------------
#  Command ScrollableFrame::_frameConfigure
# ----------------------------------------------------------------------------
proc ScrollableFrame::_frameConfigure {canvas frame width height} {
    # This ensures that we don't get funny scrollability in the frame
    # when it is smaller than the canvas space
    if {[winfo height $frame] < [winfo height $canvas]} {
	set height [winfo height $canvas]
    }
    if {[winfo width $frame] < [winfo width $canvas]} {
	set width [winfo width $canvas]
    }
    $canvas:cmd configure -scrollregion [list 0 0 $width $height]
}
Added lib/BWidget/scrollview.tcl.


































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# ------------------------------------------------------------------------------
#  scrollview.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: scrollview.tcl,v 1.7 2003/11/05 18:04:29 hobbs Exp $
# ------------------------------------------------------------------------------
#  Index of commands:
#     - ScrolledWindow::create
#     - ScrolledWindow::configure
#     - ScrolledWindow::cget
#     - ScrolledWindow::_set_hscroll
#     - ScrolledWindow::_set_vscroll
#     - ScrolledWindow::_update_scroll
#     - ScrolledWindow::_set_view
#     - ScrolledWindow::_resize
# ------------------------------------------------------------------------------

namespace eval ScrollView {
    Widget::define ScrollView scrollview

    Widget::tkinclude ScrollView canvas :cmd \
	    include {-relief -borderwidth -background -width -height -cursor} \
	    initialize {-relief flat -borderwidth 0 -width 30 -height 30 \
		-cursor crosshair}

    Widget::declare ScrollView {
        {-width       TkResource 30        0 canvas}
        {-height      TkResource 30        0 canvas}
        {-background  Color      "SystemButtonFace" 0}
        {-foreground  Color      "SystemButtonText" 0}
        {-fill        Color      ""        0}
        {-relief      TkResource flat      0 canvas}
        {-borderwidth TkResource 0         0 canvas}
        {-cursor      TkResource crosshair 0 canvas}
        {-window      String     ""        0}
        {-fg          Synonym    -foreground}
        {-bg          Synonym    -background}
        {-bd          Synonym    -borderwidth}
    }

    bind BwScrollView <B1-Motion>   [list ScrollView::_set_view %W motion %x %y]
    bind BwScrollView <ButtonPress-1> [list ScrollView::_set_view %W set %x %y]
    bind BwScrollView <Configure>     [list ScrollView::_resize %W]
    bind BwScrollView <Destroy>       [list ScrollView::_destroy %W]
}


# ------------------------------------------------------------------------------
#  Command ScrollView::create
# ------------------------------------------------------------------------------
proc ScrollView::create { path args } {
    Widget::initArgs ScrollView $args maps

    eval [list canvas $path] $maps(:cmd) -highlightthickness 0

    Widget::initFromODB ScrollView $path $maps(ScrollView)

    Widget::create ScrollView $path

    Widget::getVariable $path _widget

    set w               [Widget::cget $path -window]
    set _widget(bd)     [Widget::cget $path -borderwidth]
    set _widget(width)  [Widget::cget $path -width]
    set _widget(height) [Widget::cget $path -height]

    if {[winfo exists $w]} {
        set _widget(oldxscroll) [$w cget -xscrollcommand]
        set _widget(oldyscroll) [$w cget -yscrollcommand]
        $w configure \
            -xscrollcommand [list ScrollView::_set_hscroll $path] \
            -yscrollcommand [list ScrollView::_set_vscroll $path]
    }
    $path:cmd create rectangle -2 -2 -2 -2 \
        -fill    [Widget::cget $path -fill]       \
        -outline [Widget::cget $path -foreground] \
        -tags    view

    bindtags $path [list $path BwScrollView [winfo toplevel $path] all]

    return $path
}


# ------------------------------------------------------------------------------
#  Command ScrollView::configure
# ------------------------------------------------------------------------------
proc ScrollView::configure { path args } {
    Widget::getVariable $path _widget

    set oldw [Widget::getoption $path -window] 
    set res  [Widget::configure $path $args]

    if { [Widget::hasChanged $path -window w] } {
        if { [winfo exists $oldw] } {
            $oldw configure \
                -xscrollcommand $_widget(oldxscroll) \
                -yscrollcommand $_widget(oldyscroll)
        }
        if { [winfo exists $w] } {
            set _widget(oldxscroll) [$w cget -xscrollcommand]
            set _widget(oldyscroll) [$w cget -yscrollcommand]
            $w configure \
                -xscrollcommand [list ScrollView::_set_hscroll $path] \
                -yscrollcommand [list ScrollView::_set_vscroll $path]
        } else {
            $path:cmd coords view -2 -2 -2 -2
            set _widget(oldxscroll) {}
            set _widget(oldyscroll) {}
        }
    }

    if { [Widget::hasChanged $path -fill fill] |
         [Widget::hasChanged $path -foreground fg] } {
        $path:cmd itemconfigure view \
            -fill    $fill \
            -outline $fg
    }

    return $res
}


# ------------------------------------------------------------------------------
#  Command ScrollView::cget
# ------------------------------------------------------------------------------
proc ScrollView::cget { path option } {
    return [Widget::cget $path $option]
}


# ------------------------------------------------------------------------------
#  Command ScrollView::_set_hscroll
# ------------------------------------------------------------------------------
proc ScrollView::_set_hscroll { path vmin vmax } {
    Widget::getVariable $path _widget

    set c  [$path:cmd coords view]
    set x0 [expr {$vmin*$_widget(width)+$_widget(bd)}]
    set x1 [expr {$vmax*$_widget(width)+$_widget(bd)-1}]
    $path:cmd coords view $x0 [lindex $c 1] $x1 [lindex $c 3]
    if { $_widget(oldxscroll) != "" } {
        uplevel \#0 $_widget(oldxscroll) $vmin $vmax
    }
}


# ------------------------------------------------------------------------------
#  Command ScrollView::_set_vscroll
# ------------------------------------------------------------------------------
proc ScrollView::_set_vscroll { path vmin vmax } {
    Widget::getVariable $path _widget

    set c  [$path:cmd coords view]
    set y0 [expr {$vmin*$_widget(height)+$_widget(bd)}]
    set y1 [expr {$vmax*$_widget(height)+$_widget(bd)-1}]
    $path:cmd coords view [lindex $c 0] $y0 [lindex $c 2] $y1
    if { $_widget(oldyscroll) != "" } {
        uplevel \#0 $_widget(oldyscroll) $vmin $vmax
    }
}


# ------------------------------------------------------------------------------
#  Command ScrollView::_update_scroll
# ------------------------------------------------------------------------------
proc ScrollView::_update_scroll { path callscroll hminmax vminmax } {
    Widget::getVariable $path _widget

    set c    [$path:cmd coords view]
    set hmin [lindex $hminmax 0]
    set hmax [lindex $hminmax 1]
    set vmin [lindex $vminmax 0]
    set vmax [lindex $vminmax 1]
    set x0   [expr {$hmin*$_widget(width)+$_widget(bd)}]
    set x1   [expr {$hmax*$_widget(width)+$_widget(bd)-1}]
    set y0   [expr {$vmin*$_widget(height)+$_widget(bd)}]
    set y1   [expr {$vmax*$_widget(height)+$_widget(bd)-1}]
    $path:cmd coords view $x0 $y0 $x1 $y1
    if { $callscroll } {
        if { $_widget(oldxscroll) != "" } {
            uplevel \#0 $_widget(oldxscroll) $hmin $hmax
        }
        if { $_widget(oldyscroll) != "" } {
            uplevel \#0 $_widget(oldyscroll) $vmin $vmax
        }
    }
}


# ------------------------------------------------------------------------------
#  Command ScrollView::_set_view
# ------------------------------------------------------------------------------
proc ScrollView::_set_view { path cmd x y } {
    Widget::getVariable $path _widget

    set w [Widget::getoption $path -window]
    if {[winfo exists $w]} {
        if {[string equal $cmd "set"]} {
            set c  [$path:cmd coords view]
            set x0 [lindex $c 0]
            set y0 [lindex $c 1]
            set x1 [lindex $c 2]
            set y1 [lindex $c 3]
            if {$x >= $x0 && $x <= $x1 &&
                $y >= $y0 && $y <= $y1} {
                set _widget(dx) [expr {$x-$x0}]
                set _widget(dy) [expr {$y-$y0}]
                return
            } else {
                set x0 [expr {$x-($x1-$x0)/2}]
                set y0 [expr {$y-($y1-$y0)/2}]
                set _widget(dx) [expr {$x-$x0}]
                set _widget(dy) [expr {$y-$y0}]
                set vh [expr {double($x0-$_widget(bd))/$_widget(width)}]
                set vv [expr {double($y0-$_widget(bd))/$_widget(height)}]
            }
        } elseif {[string equal $cmd "motion"]} {
            set vh [expr {double($x-$_widget(dx)-$_widget(bd))/$_widget(width)}]
            set vv [expr {double($y-$_widget(dy)-$_widget(bd))/$_widget(height)}]
        }
        $w xview moveto $vh
        $w yview moveto $vv
        _update_scroll $path 1 [$w xview] [$w yview]
    }
}


# ------------------------------------------------------------------------------
#  Command ScrollView::_resize
# ------------------------------------------------------------------------------
proc ScrollView::_resize { path } {
    Widget::getVariable $path _widget

    set _widget(bd)     [Widget::cget $path -borderwidth]
    set _widget(width)  [expr {[winfo width  $path]-2*$_widget(bd)}]
    set _widget(height) [expr {[winfo height $path]-2*$_widget(bd)}]
    set w [Widget::getoption $path -window]
    if { [winfo exists $w] } {
        _update_scroll $path 0 [$w xview] [$w yview]
    }
}


# ------------------------------------------------------------------------------
#  Command ScrollView::_destroy
# ------------------------------------------------------------------------------
proc ScrollView::_destroy { path } {
    Widget::getVariable $path _widget

    set w [Widget::getoption $path -window] 
    if { [winfo exists $w] } {
        $w configure \
            -xscrollcommand $_widget(oldxscroll) \
            -yscrollcommand $_widget(oldyscroll)
    }
    Widget::destroy $path
}
Added lib/BWidget/scrollw.tcl.




































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# -----------------------------------------------------------------------------
#  scrollw.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: scrollw.tcl,v 1.11 2004/02/04 00:11:29 hobbs Exp $
# -----------------------------------------------------------------------------
#  Index of commands:
#
#   Public Commands:
#     - ScrolledWindow::cget
#     - ScrolledWindow::configure
#     - ScrolledWindow::create
#     - ScrolledWindow::getframe
#     - ScrolledWindow::setwidget
#
#   Private Commands:
#     - ScrolledWindow::_realize
#     - ScrolledWindow::_set_hscroll
#     - ScrolledWindow::_set_vscroll
#     - ScrolledWindow::_setData
# -----------------------------------------------------------------------------

namespace eval ScrolledWindow {
    Widget::define ScrolledWindow scrollw

    Widget::tkinclude ScrolledWindow frame :cmd \
        remove { -class -colormap -visual }

    Widget::declare ScrolledWindow {
        {-class       String     "ScrolledWindow" 1}
	{-scrollbar   Enum	 both 0 {none both vertical horizontal}}
	{-auto	      Enum	 both 0 {none both vertical horizontal}}
	{-sides	      Enum	 se   0 {ne en nw wn se es sw ws}}
	{-size	      Int	 0    1 "%d >= 0"}
	{-ipad	      Int	 1    1 "%d >= 0"}
	{-managed     Boolean	 1    1}
    }

    bind ScrolledWindow <Map>     [list ScrolledWindow::_realize %W]
    bind ScrolledWindow <Destroy> [list ScrolledWindow::_destroy %W]
}


# -----------------------------------------------------------------------------
#  Command ScrolledWindow::create
# -----------------------------------------------------------------------------
proc ScrolledWindow::create { path args } {
    Widget::initArgs ScrolledWindow $args maps

    ## Do a special check for the -class option.
    array set _args $args
    set class ScrolledWindow
    if {[info exists _args(-class)]} { set class $_args(-class) }

    eval [list frame $path -class $class] $maps(:cmd)

    Widget::initFromODB ScrolledWindow $path $args

    Widget::getVariable $path data

    ## If they specified a class other than ScrolledWindow, make
    ## sure the bindtags include ScrolledWindow so that our
    ## bindings will be enabled.
    if {![string equal $class "ScrolledWindow"]} {
        set top [winfo toplevel $path]
        bindtags $path [list $path $class ScrolledWindow $top all]
    }

    set bg [$path cget -background]

    set useTtk 0
    if {[BWidget::using ttk] && ![BWidget::using aqua]} {
        set useTtk 1
        ttk::scrollbar $path.vscroll
        ttk::scrollbar $path.hscroll -orient horizontal
    } else {
        scrollbar $path.hscroll \
                -highlightthickness 0 -takefocus 0 \
                -orient	 horiz	\
                -relief	 sunken	\
                -bg	 $bg
        scrollbar $path.vscroll \
                -highlightthickness 0 -takefocus 0 \
                -orient	 vert	\
                -relief	 sunken	\
                -bg	 $bg
    }

    set data(vmin)     -1
    set data(vmax)     -1
    set data(hmin)     -1
    set data(hmax)     -1

    set data(afterId)  ""
    set data(realized) 0

    _setData $path \
	    [Widget::cget $path -scrollbar] \
	    [Widget::cget $path -auto] \
	    [Widget::cget $path -sides]

    if {[Widget::cget $path -managed]} {
	set data(hsb,packed) $data(hsb,present)
	set data(vsb,packed) $data(vsb,present)
    } else {
	set data(hsb,packed) 0
	set data(vsb,packed) 0
    }

    if {!$useTtk} {
        set sbsize [Widget::cget $path -size]

        if {$sbsize} {
            $path.vscroll configure -width $sbsize
            $path.hscroll configure -width $sbsize
        }
    }

    set data(ipad) [Widget::cget $path -ipad]

    if {$data(hsb,packed)} {
	grid $path.hscroll -column 1 -row $data(hsb,row) \
		-sticky ew -ipady $data(ipad)
    }
    if {$data(vsb,packed)} {
	grid $path.vscroll -column $data(vsb,column) -row 1 \
		-sticky ns -ipadx $data(ipad)
    }

    grid columnconfigure $path 1 -weight 1
    grid rowconfigure	 $path 1 -weight 1

    return [Widget::create ScrolledWindow $path]
}


# -----------------------------------------------------------------------------
#  Command ScrolledWindow::getframe
# -----------------------------------------------------------------------------
proc ScrolledWindow::getframe { path } {
    return $path
}


# -----------------------------------------------------------------------------
#  Command ScrolledWindow::setwidget
# -----------------------------------------------------------------------------
proc ScrolledWindow::setwidget { path widget } {
    Widget::getVariable $path data

    if {[info exists data(widget)] && [winfo exists $data(widget)]
	&& ![string equal $data(widget) $widget]} {
	grid remove $data(widget)
	$data(widget) configure -xscrollcommand "" -yscrollcommand ""
    }

    set data(widget) $widget
    grid $widget -in $path -row 1 -column 1 -sticky news

    $path.hscroll configure -command [list $widget xview]
    $path.vscroll configure -command [list $widget yview]
    $widget configure \
        -xscrollcommand [list ScrolledWindow::_set_hscroll $path] \
        -yscrollcommand [list ScrolledWindow::_set_vscroll $path]
}


# -----------------------------------------------------------------------------
#  Command ScrolledWindow::getwidget
# -----------------------------------------------------------------------------
proc ScrolledWindow::getwidget { path } {
    Widget::getVariable $path data
    if {[info exists data(widget)]} { return $data(widget) }
}


# -----------------------------------------------------------------------------
#  Command ScrolledWindow::configure
# -----------------------------------------------------------------------------
proc ScrolledWindow::configure { path args } {
    Widget::getVariable $path data

    set res [Widget::configure $path $args]

    if {[Widget::hasChanged $path -background bg]} {
	catch { $path.hscroll configure -background $bg }
	catch { $path.vscroll configure -background $bg }
    }

    if {[Widget::hasChanged $path -scrollbar scrollbar]
        || [Widget::hasChanged $path -auto  auto]
        || [Widget::hasChanged $path -sides sides]} {
	_setData $path $scrollbar $auto $sides

        BWidget::lassign [$path.hscroll get] vmin vmax
	set data(hsb,packed) [expr {$data(hsb,present) && \
		(!$data(hsb,auto) || ($vmin != 0 || $vmax != 1))}]

        BWidget::lassign [$path.vscroll get] vmin vmax
	set data(vsb,packed) [expr {$data(vsb,present) && \
		(!$data(vsb,auto) || ($vmin != 0 || $vmax != 1))}]

	set data(ipad) [Widget::cget $path -ipad]

	if {$data(hsb,packed)} {
	    grid $path.hscroll -column 1 -row $data(hsb,row) \
                -sticky ew -ipady $data(ipad)
	}
	if {$data(vsb,packed)} {
	    grid $path.vscroll -column $data(vsb,column) -row 1 \
                -sticky ns -ipadx $data(ipad)
	}
    }
    return $res
}


# -----------------------------------------------------------------------------
#  Command ScrolledWindow::cget
# -----------------------------------------------------------------------------
proc ScrolledWindow::cget { path option } {
    return [Widget::cget $path $option]
}


# -----------------------------------------------------------------------------
#  Command ScrolledWindow::_set_hscroll
# -----------------------------------------------------------------------------
proc ScrolledWindow::_set_hscroll { path vmin vmax } {
    Widget::getVariable $path data

    $path.hscroll set $vmin $vmax

    set data(hmin) $vmin
    set data(hmax) $vmax

    _redraw_after $path
}


# -----------------------------------------------------------------------------
#  Command ScrolledWindow::_set_vscroll
# -----------------------------------------------------------------------------
proc ScrolledWindow::_set_vscroll { path vmin vmax } {
    Widget::getVariable $path data

    $path.vscroll set $vmin $vmax

    set data(vmin) $vmin
    set data(vmax) $vmax

    _redraw_after $path
}


proc ScrolledWindow::_setData {path scrollbar auto sides} {
    Widget::getVariable $path data

    set sb    [lsearch -exact {none horizontal vertical both} $scrollbar]
    set auto  [lsearch -exact {none horizontal vertical both} $auto]

    set data(hsb,present)  [expr {($sb & 1) != 0}]
    set data(hsb,auto)	   [expr {($auto & 1) != 0}]
    set data(hsb,row)	   [expr {[string match *n* $sides] ? 0 : 2}]

    set data(vsb,present)  [expr {($sb & 2) != 0}]
    set data(vsb,auto)	   [expr {($auto & 2) != 0}]
    set data(vsb,column)   [expr {[string match *w* $sides] ? 0 : 2}]
}


proc ScrolledWindow::_redraw_after { path } {
    Widget::getVariable $path data
    after cancel $data(afterId)
    set data(afterId) [after 5 [list ScrolledWindow::_redraw $path]]
}


proc ScrolledWindow::_redraw { path } {
    if {![Widget::exists $path]} { return }

    Widget::getVariable $path data

    if {!$data(realized)} { return }

    if {$data(hsb,present) && $data(hsb,auto)} {
        if {$data(hsb,packed) && $data(hmin) == 0 && $data(hmax) == 1} {
            set data(hsb,packed) 0
            grid remove $path.hscroll
        } elseif {!$data(hsb,packed) && ($data(hmin)!=0 || $data(hmax)!=1)} {
            set data(hsb,packed) 1
            grid $path.hscroll -column 1 -row $data(hsb,row) \
                    -sticky ew -ipady $data(ipad)
        }
    }

    if {$data(vsb,present) && $data(vsb,auto)} {
        if {$data(vsb,packed) && $data(vmin) == 0 && $data(vmax) == 1} {
            set data(vsb,packed) 0
            grid remove $path.vscroll
        } elseif {!$data(vsb,packed) && ($data(vmin)!=0 || $data(vmax)!=1) } {
            set data(vsb,packed) 1
            grid $path.vscroll -column $data(vsb,column) -row 1 \
                    -sticky ns -ipadx $data(ipad)
        }
    }
}


# -----------------------------------------------------------------------------
#  Command ScrolledWindow::_realize
# -----------------------------------------------------------------------------
proc ScrolledWindow::_realize { path } {
    Widget::getVariable $path data
    set data(realized) 1
}


proc ScrolledWindow::_destroy { path } {
    Widget::getVariable $path data
    after cancel $data(afterId)
    Widget::destroy $path
}
Added lib/BWidget/separator.tcl.
























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# ------------------------------------------------------------------------------
#  separator.tcl
#  This file is part of Unifix BWidget Toolkit
# ------------------------------------------------------------------------------
#  Index of commands:
#     - Separator::create
#     - Separator::configure
#     - Separator::cget
# ------------------------------------------------------------------------------

namespace eval Separator {
    Widget::define Separator separator

    Widget::declare Separator {
        {-background Color      "SystemButtonFace" 0}
        {-cursor     String     ""         0}
        {-relief     Enum       groove     0 {ridge groove}}
        {-orient     Enum       horizontal 1 {horizontal vertical}}
        {-bg         Synonym    -background}
    }
    Widget::addmap Separator "" :cmd { -background {} -cursor {} }

    bind Separator <Destroy> [list Widget::destroy %W]
}


# ------------------------------------------------------------------------------
#  Command Separator::create
# ------------------------------------------------------------------------------
proc Separator::create { path args } {
    Widget::initArgs Separator $args maps

    eval [list frame $path -class Separator] $maps(:cmd)

    Widget::initFromODB Separator $path $maps(Separator)

    if {[string equal [Widget::cget $path -orient] "horizontal"]} {
	$path configure -borderwidth 1 -height 2
    } else {
	$path configure -borderwidth 1 -width 2
    }

    if {[string equal [Widget::cget $path -relief] "groove"]} {
	$path configure -relief sunken
    } else {
	$path configure -relief raised
    }

    return [Widget::create Separator $path]
}


# ------------------------------------------------------------------------------
#  Command Separator::configure
# ------------------------------------------------------------------------------
proc Separator::configure { path args } {
    set res [Widget::configure $path $args]

    if { [Widget::hasChanged $path -relief relief] } {
        if { $relief == "groove" } {
            $path:cmd configure -relief sunken
        } else {
            $path:cmd configure -relief raised
        }
    }

    return $res
}


# ------------------------------------------------------------------------------
#  Command Separator::cget
# ------------------------------------------------------------------------------
proc Separator::cget { path option } {
    return [Widget::cget $path $option]
}
Added lib/BWidget/spinbox.tcl.
























































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# spinbox.tcl --
#
#	BWidget SpinBox implementation.
#
# Copyright (c) 1999 by Unifix
# Copyright (c) 2000 by Ajuba Solutions
# All rights reserved.
# 
# RCS: @(#) $Id: spinbox.tcl,v 1.12 2003/10/20 21:23:52 damonc Exp $
# -----------------------------------------------------------------------------
#  Index of commands:
#     - SpinBox::create
#     - SpinBox::configure
#     - SpinBox::cget
#     - SpinBox::setvalue
#     - SpinBox::_destroy
#     - SpinBox::_modify_value
#     - SpinBox::_test_options
# -----------------------------------------------------------------------------

namespace eval SpinBox {
    Widget::define SpinBox spinbox Entry ArrowButton

    Widget::tkinclude SpinBox frame :cmd \
	    include {-background -borderwidth -bg -bd -relief} \
	    initialize {-relief sunken -borderwidth 2}

    Widget::bwinclude SpinBox Entry .e \
        remove {-relief -bd -borderwidth -fg -bg} \
        rename {-foreground -entryfg -background -entrybg}

    Widget::declare SpinBox {
        {-range          String ""  0}
        {-values         String ""  0}
        {-modifycmd      String ""  0}
        {-repeatdelay    Int    400 0 {%d >= 0}}
        {-repeatinterval Int    100 0 {%d >= 0}}
	{-foreground     Color  "SystemButtonText" 0}
    }

    Widget::addmap SpinBox "" :cmd {-background {}}
    Widget::addmap SpinBox ArrowButton .arrup {
        -foreground {} -background {} -disabledforeground {} -state {} \
		-repeatinterval {} -repeatdelay {}
    }
    Widget::addmap SpinBox ArrowButton .arrdn {
        -foreground {} -background {} -disabledforeground {} -state {} \
		-repeatinterval {} -repeatdelay {}
    }

    ::bind SpinBox <FocusIn> [list after idle {BWidget::refocus %W %W.e}]
    ::bind SpinBox <Destroy> [list SpinBox::_destroy %W]

    variable _widget
}


# -----------------------------------------------------------------------------
#  Command SpinBox::create
# -----------------------------------------------------------------------------
proc SpinBox::create { path args } {
    Widget::initArgs SpinBox $args maps

    eval [list frame $path -class SpinBox] $maps(:cmd) \
	 -highlightthickness 0 -takefocus 0

    Widget::initFromODB SpinBox $path $maps(SpinBox)

    set entry [eval [list Entry::create $path.e] $maps(.e) -relief flat -bd 0]
    bindtags $path.e [linsert [bindtags $path.e] 1 SpinBoxEntry]

    set farr   [frame $path.farr -relief flat -bd 0 -highlightthickness 0]
    set height [expr {[winfo reqheight $path.e]/2-2}]
    set width  11
    set arrup  [eval [list ArrowButton::create $path.arrup -dir top] \
	    $maps(.arrup) \
		    [list -highlightthickness 0 -borderwidth 1 -takefocus 0 \
			 -type button -width $width -height $height \
			 -armcommand    [list SpinBox::_modify_value $path next arm] \
			 -disarmcommand [list SpinBox::_modify_value $path next disarm]]]
    set arrdn  [eval [list ArrowButton::create $path.arrdn -dir bottom] \
	    $maps(.arrdn) \
		    [list -highlightthickness 0 -borderwidth 1 -takefocus 0 \
			 -type button -width $width -height $height \
			 -armcommand    [list SpinBox::_modify_value $path previous arm] \
			 -disarmcommand [list SpinBox::_modify_value $path previous disarm]]]

    # --- update SpinBox value ---
    _test_options $path
    set val [Entry::cget $path.e -text]
    if { [string equal $val ""] } {
	Entry::configure $path.e -text $::SpinBox::_widget($path,curval)
    } else {
	set ::SpinBox::_widget($path,curval) $val
    }

    grid $arrup -in $farr -column 0 -row 0 -sticky nsew
    grid $arrdn -in $farr -column 0 -row 2 -sticky nsew
    grid rowconfigure $farr 0 -weight 1
    grid rowconfigure $farr 2 -weight 1

    pack $farr  -side right -fill y
    pack $entry -side left  -fill both -expand yes

    ::bind $entry <Key-Up>    [list SpinBox::_modify_value $path next activate]
    ::bind $entry <Key-Down>  [list SpinBox::_modify_value $path previous activate]
    ::bind $entry <Key-Prior> [list SpinBox::_modify_value $path last activate]
    ::bind $entry <Key-Next>  [list SpinBox::_modify_value $path first activate]

    ::bind $farr <Configure> {grid rowconfigure %W 1 -minsize [expr {%h%%2}]}

    return [Widget::create SpinBox $path]
}

# -----------------------------------------------------------------------------
#  Command SpinBox::configure
# -----------------------------------------------------------------------------
proc SpinBox::configure { path args } {
    set res [Widget::configure $path $args]
    if { [Widget::hasChangedX $path -values] ||
         [Widget::hasChangedX $path -range] } {
        _test_options $path
    }
    return $res
}


# -----------------------------------------------------------------------------
#  Command SpinBox::cget
# -----------------------------------------------------------------------------
proc SpinBox::cget { path option } {
    return [Widget::cget $path $option]
}


# -----------------------------------------------------------------------------
#  Command SpinBox::setvalue
# -----------------------------------------------------------------------------
proc SpinBox::setvalue { path index } {
    variable _widget

    set values [Widget::getoption $path -values]
    set value  [Entry::cget $path.e -text]
    
    if { [llength $values] } {
        # --- -values SpinBox ---
        switch -- $index {
            next {
                if { [set idx [lsearch $values $value]] != -1 } {
                    incr idx
                } elseif { [set idx [lsearch $values "$value*"]] == -1 } {
                    set idx [lsearch $values $_widget($path,curval)]
                }
            }
            previous {
                if { [set idx [lsearch $values $value]] != -1 } {
                    incr idx -1
                } elseif { [set idx [lsearch $values "$value*"]] == -1 } {
                    set idx [lsearch $values $_widget($path,curval)]
                }
            }
            first {
                set idx 0
            }
            last {
                set idx [expr {[llength $values]-1}]
            }
            default {
                if { [string index $index 0] == "@" } {
                    set idx [string range $index 1 end]
                    if { [catch {string compare [expr {int($idx)}] $idx} res] || $res != 0 } {
                        return -code error "bad index \"$index\""
                    }
                } else {
                    return -code error "bad index \"$index\""
                }
            }
        }
        if { $idx >= 0 && $idx < [llength $values] } {
            set newval [lindex $values $idx]
        } else {
            return 0
        }
    } else {
        # --- -range SpinBox ---
	foreach {vmin vmax incr} [Widget::getoption $path -range] {
	    break
	}
	# Allow zero padding on the value; strip it out for calculation by
	# scanning the value into a floating point number.
	scan $value %f value
        switch -- $index {
            next {
                if { [catch {expr {double($value-$vmin)/$incr}} idx] } {
                    set newval $_widget($path,curval)
                } else {
                    set newval [expr {$vmin+(round($idx)+1)*$incr}]
                    if { $newval < $vmin } {
                        set newval $vmin
                    } elseif { $newval > $vmax } {
                        set newval $vmax
                    }
                }
            }
            previous {
                if { [catch {expr {double($value-$vmin)/$incr}} idx] } {
                    set newval $_widget($path,curval)
                } else {
                    set newval [expr {$vmin+(round($idx)-1)*$incr}]
                    if { $newval < $vmin } {
                        set newval $vmin
                    } elseif { $newval > $vmax } {
                        set newval $vmax
                    }
                }
            }
            first {
                set newval $vmin
            }
            last {
                set newval $vmax
            }
            default {
                if { [string index $index 0] == "@" } {
                    set idx [string range $index 1 end]
                    if { [catch {string compare [expr {int($idx)}] $idx} res] || $res != 0 } {
                        return -code error "bad index \"$index\""
                    }
                    set newval [expr {$vmin+int($idx)*$incr}]
                    if { $newval < $vmin || $newval > $vmax } {
                        return 0
                    }
                } else {
                    return -code error "bad index \"$index\""
                }
            }
        }
    }
    set _widget($path,curval) $newval
    Entry::configure $path.e -text $newval
    return 1
}


# -----------------------------------------------------------------------------
#  Command SpinBox::getvalue
# -----------------------------------------------------------------------------
proc SpinBox::getvalue { path } {
    variable _widget

    set values [Widget::getoption $path -values]
    set value  [Entry::cget $path.e -text]

    if { [llength $values] } {
        # --- -values SpinBox ---
        return  [lsearch $values $value]
    } else {
	foreach {vmin vmax incr} [Widget::getoption $path -range] {
	    break
	}
        if { ![catch {expr {double($value-$vmin)/$incr}} idx] &&
             $idx == int($idx) } {
            return [expr {int($idx)}]
        }
        return -1
    }
}


# -----------------------------------------------------------------------------
#  Command SpinBox::bind
# -----------------------------------------------------------------------------
proc SpinBox::bind { path args } {
    return [eval [list ::bind $path.e] $args]
}


# -----------------------------------------------------------------------------
#  Command SpinBox::_modify_value
# -----------------------------------------------------------------------------
proc SpinBox::_modify_value { path direction reason } {
    if { $reason == "arm" || $reason == "activate" } {
        SpinBox::setvalue $path $direction
    }
    if { ($reason == "disarm" || $reason == "activate") &&
         [set cmd [Widget::getoption $path -modifycmd]] != "" } {
        uplevel \#0 $cmd
    }
}

# -----------------------------------------------------------------------------
#  Command SpinBox::_test_options
# -----------------------------------------------------------------------------
proc SpinBox::_test_options { path } {
    set values [Widget::getoption $path -values]
    if { [llength $values] } {
        set ::SpinBox::_widget($path,curval) [lindex $values 0]
    } else {
	foreach {vmin vmax incr} [Widget::getoption $path -range] {
	    break
	}
	set update 0
        if { [catch {expr {int($vmin)}}] } {
            set vmin 0
	    set update 1
        }
        if { [catch {expr {$vmax<$vmin}} res] || $res } {
            set vmax $vmin
	    set update 1
        }
        if { [catch {expr {$incr<0}} res] || $res } {
            set incr 1
	    set update 1
        }
	# Only do the set back (which is expensive) if we changed a value
	if { $update } {
	    Widget::setoption $path -range [list $vmin $vmax $incr]
	}
        set ::SpinBox::_widget($path,curval) $vmin
    }
}


# -----------------------------------------------------------------------------
#  Command SpinBox::_destroy
# -----------------------------------------------------------------------------
proc SpinBox::_destroy { path } {
    variable _widget

    unset _widget($path,curval)
    Widget::destroy $path
}
Added lib/BWidget/splitlist.tcl.










































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# -----------------------------------------------------------------------------
#  splitlist.tcl
#
#  $Id$
# -----------------------------------------------------------------------------
#  Index of commands:
#     - SplitList::create
#     - SplitList::configure
#     - SplitList::cget
# -----------------------------------------------------------------------------

package require Tk 8.4

namespace eval SplitList {
    Widget::define SplitList splitlist ListBox

    Widget::bwinclude SplitList ListBox .left \
        prefix { left remove -bg -fg -bd }

    Widget::bwinclude SplitList ListBox .right \
        prefix { right remove -bg -fg -bd }

    Widget::tkinclude SplitList frame :cmd \
        include { -background -bg -relief -borderwidth -bd -width -height }
}


proc SplitList::create { path args } {
    Widget::initArgs SplitList $args maps

    eval frame $path $maps(:cmd) -class SplitList

    Widget::initFromODB SplitList $path $maps(SplitList)

    grid rowconfigure    $path 0     -weight 1
    grid columnconfigure $path {0 2} -weight 1

    eval [list ListBox $path.left -dragenabled 1 -dropenabled 1 \
        -dropcmd SplitList::_drag_and_drop -selectmode multiple -selectfill 1] \
        $maps(.left)

    grid $path.left -row 0 -column 0 -sticky news

    ButtonBox $path.buttons -orient vertical
    grid $path.buttons -row 0 -column 1 -padx 5

    $path.buttons add -text ">" -width 5 \
        -command [list SplitList::_shift_items $path right]
    $path.buttons add -text "<" \
        -command [list SplitList::_shift_items $path left]
    $path.buttons add -text ">>" \
        -command [list SplitList::_shift_items $path right 1]
    $path.buttons add -text "<<" \
        -command [list SplitList::_shift_items $path left 1]

    eval [list ListBox $path.right -dragenabled 1 -dropenabled 1 \
        -dropcmd SplitList::_drag_and_drop -selectmode multiple] \
        $maps(.right)
    grid $path.right -row 0 -column 2 -sticky news

    return [Widget::create SplitList $path]
}


proc SplitList::configure { path args } {
    set res [Widget::configure $path $args]
    return $res
}


proc SplitList::cget { path option } {
    return [Widget::cget $path $option]
}


proc SplitList::copy { path item leftOrRight newItem index } {
    Widget::getVariable $path items

    if {![info exists items($item)]} {
        return -code error "item \"$item\" does not exist"
    }

    set newItem [Widget::nextIndex $path $newItem]

    if {[info exists items($newItem)]} {
        return -code error "item \"$newItem\" does not exist"
    }

    set to   [SplitList::getlistbox $path $leftOrRight]
    set from $path.$items($item)

    set options [Widget::options $from.$item]
    set item [eval [linsert $options 0 $to insert $index $newItem]]
    set items($item) $leftOrRight
}


proc SplitList::getlistbox { path leftOrRight } {
    if {$leftOrRight eq "left"} {
        return $path.left
    } elseif {$leftOrRight eq "right"} {
        return $path.right
    } else {
        return -code error \
            [BWidget::badOptionString listbox $leftOrRight [list left right]]
    }
}


proc SplitList::insert { path leftOrRight index item args } {
    Widget::getVariable $path items

    set item [Widget::nextIndex $path $item]

    if {[info exists items($item)]} {
        return -code error "item \"$item\" already exists"
    }

    set items($item) $leftOrRight

    eval [list $path.$leftOrRight insert $index $item] $args
}


proc SplitList::itemcget { path item option } {
    Widget::getVariable $path items

    if {![info exists items($item)]} {
        return -code error "item \"$item\" does not exist"
    }

    return [$path.$items($item) itemcget $item $option]
}


proc SplitList::itemconfigure { path item args } {
    Widget::getVariable $path items

    if {![info exists items($item)]} {
        return -code error "item \"$item\" does not exist"
    }

    return [eval [list $path.$items($item) itemconfigure $item] $args]
}


proc SplitList::move { path item leftOrRight index } {
    Widget::getVariable $path items

    if {![info exists items($item)]} {
        return -code error "item \"$item\" does not exist"
    }

    set to   [SplitList::getlistbox $path $leftOrRight]
    set from $path.$items($item)

    if {$to eq $from} {
        $to move $item $index
    } else {
        set options [Widget::options $from.$item]
        set item [eval [linsert $options 0 $to insert $index $item]]
        set items($item) $leftOrRight
        $from delete $item
    }
}


proc SplitList::_shift_items { path dir {all 0} } {
    set opp [expr {$dir eq "left" ? "right" : "left"}]

    if {$all} {
        set items [$path.$opp items]
    } else {
        set items [$path.$opp selection get]
    }

    foreach item $items {
        SplitList::move $path $item $dir end
    }
}


proc SplitList::_drag_and_drop { path from endItem operation type startItem } {
    set tolist   $path
    set fromlist [winfo parent $from]
    set path     [winfo parent $path]

    if {[winfo parent $tolist] ne [winfo parent $fromlist]} { return }

    set place [lindex $endItem 0]
    set i     [lindex $endItem 1]

    switch -- $place {
        "position" {
            set idx $i
        } 

        "item" {
            set idx [$tolist index $i]
        }

        default {
            set idx end
        }
    }

    if {[string equal $operation "copy"]} {
        set newItem [Widget::nextIndex $path COPY$startItem-#auto]
        SplitList::copy $path $startItem [winfo name $tolist] $newItem $idx
    } else {
        SplitList::move $path $startItem [winfo name $tolist] $idx
    }
}
Added lib/BWidget/statusbar.tcl.




















































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
# ------------------------------------------------------------------------
#  statusbar.tcl
#	Create a status bar Tk widget
#
#  Provides a status bar to be placed at the bottom of a toplevel.
#  Currently does not support being placed in a toplevel that has
#  gridding applied (via widget -setgrid or wm grid).
#
#  Ensure that the widget is placed at the very bottom of the toplevel,
#  otherwise the resize behavior may behave oddly.
# ------------------------------------------------------------------------

package require Tk 8.3

if {0} {
    proc sample {} {
    # sample usage
    eval destroy [winfo children .]
    pack [text .t -width 0 -height 0] -fill both -expand 1

    set sbar .s
    StatusBar $sbar
    pack $sbar -side bottom -fill x
    set f [$sbar getframe]

    # Specify -width 1 for the label widget so it truncates nicely
    # instead of requesting large sizes for long messages
    set w [label $f.status -width 1 -anchor w -textvariable ::STATUS]
    set ::STATUS "This is a status message"
    # give the entry weight, as we want it to be the one that expands
    $sbar add $w -weight 1

    # BWidget's progressbar
    set w [ProgressBar $f.bpbar -orient horizontal \
	       -variable ::PROGRESS -bd 1 -relief sunken]
    set ::PROGRESS 50
    $sbar add $w
    }
}

namespace eval StatusBar {
    Widget::define StatusBar statusbar

    Widget::declare StatusBar {
	{-background  Color      "SystemButtonFace"	0}
	{-borderwidth TkResource 0	0 frame}
	{-relief      TkResource flat	0 frame}
	{-showseparator Boolean	 1	0}
	{-showresizesep Boolean	 0	0}
	{-showresize  Boolean	 1	0}
	{-width	      TkResource 100	0 frame}
	{-height      TkResource 18	0 frame}
	{-ipad	      String	 1	0}
	{-pad	      String	 0	0}
	{-bg	      Synonym	 -background}
	{-bd	      Synonym	 -borderwidth}
    }

    # -background, -borderwidth and -relief apply to outer frame, but relief
    # should be left flat for proper look
    Widget::addmap StatusBar "" :cmd {
	-background {} -width {} -height {} -borderwidth {} -relief {}
    }
    Widget::addmap StatusBar "" .sbar {
	-background {}
    }
    Widget::addmap StatusBar "" .resize {
	-background {}
    }
    Widget::addmap StatusBar "" .hsep {
	-background {}
    }

    # -pad provides general padding around the status bar
    # -ipad provides padding around each status bar item
    # Padding can be a list of {padx pady}

    variable HaveMarlett \
	[expr {[lsearch -exact [font families] "Marlett"] != -1}]

    bind StatusResize <1> \
	[namespace code [list begin_resize %W %X %Y]]
    bind StatusResize <B1-Motion> \
	[namespace code [list continue_resize %W %X %Y]]
    bind StatusResize <ButtonRelease-1> \
	[namespace code [list end_resize %W %X %Y]]

    bind StatusBar <Destroy> [list StatusBar::_destroy %W]

    # PNG version has partial alpha transparency for better look
    variable pngdata {
	iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAFM0aXcAAAABGdBTUEAAYagM
	eiWXwAAAGJJREFUGJW9kVEOgCAMQzs8GEezN69fkKlbUAz2r3l5NGTA+pCU+Q
	IA5sv39wGgZKClZGBhJMVTklRr3VNwMz04mVfQzQiEm79EkrYZycxIkq8kkv2
	v6RFGku9TUrj8RGr9AGy6mhv2ymLwAAAAAElFTkSuQmCC
    }
    variable gifdata {
	R0lGODlhDwAPAJEAANnZ2f///4CAgD8/PyH5BAEAAAAALAAAAAAPAA8AAAJEh
	I+py+1IQvh4IZlG0Qg+QshkAokGQfAvZCBIhG8hA0Ea4UPIQJBG+BAyEKQhCH
	bIQAgNEQCAIA0hAyE0AEIGgjSEDBQAOw==
    }

    BWidget::CreateImage $gifdata $pngdata ::StatusBar::resizer
}


# ------------------------------------------------------------------------
#  Command StatusBar::create
# ------------------------------------------------------------------------
proc StatusBar::create { path args } {
    variable _widget
    variable HaveMarlett

    Widget::initArgs StatusBar $args maps

    eval [list frame $path -class StatusBar] $maps(:cmd)

    Widget::initFromODB StatusBar $path $maps(StatusBar)

    foreach {padx pady} [_padval [Widget::cget $path -pad]] \
	{ipadx ipady} [_padval [Widget::cget $path -ipad]] { break }

    if {[BWidget::using ttk]} {
	set sbar   [ttk::frame $path.sbar -padding [list $padx $pady]]
    } else {
	set sbar   [eval [list frame $path.sbar -padx $padx -pady $pady] \
			$maps(.sbar)]
    }
    if {[string equal $::tcl_platform(platform) "windows"]} {
	set cursor size_nw_se
    } else {
	set cursor sizing; # bottom_right_corner ??
    }
    set resize [eval [list label $path.resize] $maps(.resize) \
		    [list -borderwidth 0 -relief flat -anchor se \
			 -cursor $cursor -anchor se -padx 0 -pady 0]]
    if {$HaveMarlett} {
	$resize configure -font "Marlett -16" -text \u006f
    } else {
	$resize configure -image ::StatusBar::resizer
    }
    bindtags $resize [list all [winfo toplevel $path] StatusResize $resize]

    if {[BWidget::using ttk]} {
	set fsep [ttk::separator $path.hsep -orient horizontal]
    } else {
	set fsep [eval [list frame $path.hsep -bd 1 -height 2 -relief sunken] \
		      $maps(.hsep)]
    }
    set sep  [_sep $path sepresize {}]

    grid $fsep   -row 0 -column 0 -columnspan 3 -sticky ew
    grid $sbar   -row 1 -column 0 -sticky news
    grid $sep    -row 1 -column 1 -sticky ns -padx $ipadx -pady $ipady
    grid $resize -row 1 -column 2 -sticky news
    grid columnconfigure $path 0 -weight 1
    if {![Widget::cget $path -showseparator]} {
	grid remove $fsep
    }
    if {![Widget::cget $path -showresize]} {
	grid remove $sep $resize
    } elseif {![Widget::cget $path -showresizesep]} {
	grid remove $sep
    }
    set _widget($path,items) {}

    return [Widget::create StatusBar $path]
}


# ------------------------------------------------------------------------
#  Command StatusBar::configure
# ------------------------------------------------------------------------
proc StatusBar::configure { path args } {
    variable _widget

    set res [Widget::configure $path $args]

    foreach {chshow chshowrsep chshowsep chipad chpad} \
	[Widget::hasChangedX $path -showresize -showresizesep -showseparator \
	     -ipad -pad] { break }

    if {$chshow || $chshowrsep} {
	set show [Widget::cget $path -showresize]
	set showrsep [Widget::cget $path -showresizesep]
        if {$show} {
	    if {$showrsep} {
		grid $path.sepresize
	    } else {
                grid remove $path.sepresize
            }
	    grid $path.resize
        } else {
	    grid remove $path.sepresize $path.resize
	}
    }
    if {$chshowsep} {
        if {$show} {
	    grid $path.hsep
        } else {
	    grid remove $path.hsep
	}
    }
    if {$chipad} {
	foreach {ipadx ipady} [_padval [Widget::cget $path -ipad]] { break }
	foreach w [grid slaves $path.sbar] {
	    grid configure $w -padx $ipadx -pady $ipady
	}
    }
    if {$chpad} {
	foreach {padx pady} [_padval [Widget::cget $path -pad]] { break }
	if {[string equal [winfo class $path.sbar] "TFrame"]} {
	    $path.sbar configure -padding [list $padx $pady]
	} else {
	    $path.sbar configure -padx $padx -pady $pady
	}
    }
    return $res
}


# ------------------------------------------------------------------------
#  Command StatusBar::cget
# ------------------------------------------------------------------------
proc StatusBar::cget { path option } {
    return [Widget::cget $path $option]
}

# ------------------------------------------------------------------------
#  Command StatusBar::getframe
# ------------------------------------------------------------------------
proc StatusBar::getframe {path} {
    # This is the frame that users should place their statusbar widgets in
    return $path.sbar
}

# ------------------------------------------------------------------------
#  Command StatusBar::add
# ------------------------------------------------------------------------
proc StatusBar::add {path w args} {
    variable _widget

    array set opts [list \
			-weight    0 \
			-separator 1 \
			-sticky    news \
			-pad       [Widget::cget $path -ipad] \
			]
    foreach {key val} $args {
	if {[info exists opts($key)]} {
	    set opts($key) $val
	} else {
	    set msg "unknown option \"$key\", must be one of: "
	    append msg [join [lsort [array names opts]] {, }]
	    return -code error $msg
	}
    }
    foreach {ipadx ipady} [_padval $opts(-pad)] { break }

    set sbar $path.sbar
    foreach {cols rows} [grid size $sbar] break
    # Add separator if requested, and we aren't the first element
    if {$opts(-separator) && $cols != 0} {
	set sep [_sep $path sep[winfo name $w]]
	# only append name, to distinguish us from them
	lappend _widget($path,items) [winfo name $sep]
	grid $sep -in $sbar -row 0 -column $cols \
	    -sticky ns -padx $ipadx -pady $ipady
	incr cols
    }

    lappend _widget($path,items) $w
    grid $w -in $sbar -row 0 -column $cols -sticky $opts(-sticky) \
	-padx $ipadx -pady $ipady
    grid columnconfigure $sbar $cols -weight $opts(-weight)

    return $w
}

# ------------------------------------------------------------------------
#  Command StatusBar::delete
# ------------------------------------------------------------------------
proc StatusBar::remove {path args} {
    variable _widget

    set destroy [string equal [lindex $args 0] "-destroy"]
    if {$destroy} {
	set args [lrange $args 1 end]
    }
    foreach w $args {
	set idx [lsearch -exact $_widget($path,items) $w]
	if {$idx == -1 || ![winfo exists $w]} {
	    # ignore unknown or non-widget items (like our separators)
	    continue
	}
	# separator is always previous item
	set sidx [expr {$idx - 1}]
	set sep  [lindex $_widget($path,items) $sidx]
	if {[string match .* $sep]} {
	    # not one of our separators
	    incr sidx
	} else {
	    # destroy separator too
	    set sep $path.sbar.$sep
	    grid forget $sep
	    destroy $sep
	}
	if {$destroy} {
	    destroy $w
	} else {
	    grid forget $w
	}
	set _widget($path,items) [lreplace $_widget($path,items) $sidx $idx]
    }
}

# ------------------------------------------------------------------------
#  Command StatusBar::delete
# ------------------------------------------------------------------------
proc StatusBar::delete {path args} {
    return [StatusBar::remove $path -destroy $args]
}

# ------------------------------------------------------------------------
#  Command StatusBar::items
# ------------------------------------------------------------------------
proc StatusBar::items {path} {
    variable _widget
    return $_widget($path,items)
}

proc StatusBar::_sep {path name {sub .sbar}} {
    if {[BWidget::using ttk]} {
	return [ttk::separator $path$sub.$name -orient vertical]
    } else {
	return [frame $path$sub.$name -bd 1 -width 2 -relief sunken]
    }
}

proc StatusBar::_padval {padval} {
    set len [llength $padval]
    foreach {a b} $padval { break }
    if {$len == 0 || $len > 2} {
	return -code error \
	    "invalid pad value \"$padval\", must be 1 or 2 pixel values"
    } elseif {$len == 1} {
	return [list $a $a]
    } elseif {$len == 2} {
	return $padval
    }
}

# ------------------------------------------------------------------------
#  Command StatusBar::_destroy
# ------------------------------------------------------------------------
proc StatusBar::_destroy { path } {
    variable _widget
    variable resize
    array unset widget $path,*
    array unset resize $path.resize,*
    Widget::destroy $path
}

# The following proc handles the mouse click on the resize control. It stores
# the original size of the window and the initial coords of the mouse relative
# to the root.

proc StatusBar::begin_resize {w rootx rooty} {
    variable resize
    set t    [winfo toplevel $w]
    set relx [expr {$rootx - [winfo rootx $t]}]
    set rely [expr {$rooty - [winfo rooty $t]}]
    set resize($w,x) $relx
    set resize($w,y) $rely
    set resize($w,w) [winfo width $t]
    set resize($w,h) [winfo height $t]
    set resize($w,winc) 1
    set resize($w,hinc) 1
    set resize($w,grid) [wm grid $t]
}

# The following proc handles mouse motion on the resize control by asking the
# wm to adjust the size of the window.

proc StatusBar::continue_resize {w rootx rooty} {
    variable resize
    if {[llength $resize($w,grid)]} {
	# at this time, we don't know how to handle gridded resizing
	return
    }
    set t      [winfo toplevel $w]
    set relx   [expr {$rootx - [winfo rootx $t]}]
    set rely   [expr {$rooty - [winfo rooty $t]}]
    set width  [expr {$relx - $resize($w,x) + $resize($w,w)}]
    set height [expr {$rely - $resize($w,y) + $resize($w,h)}]
    if {$width  < 0} { set width 0 }
    if {$height < 0} { set height 0 }
    wm geometry $t ${width}x${height}

    if {[string equal $::tcl_platform(platform) "windows"]} { update idletasks }
}

# The following proc cleans up when the user releases the mouse button.

proc StatusBar::end_resize {w rootx rooty} {
    variable resize
    #continue_resize $w $rootx $rooty
    #wm grid $t $resize($w,grid)
    array unset resize $w,*
}
Added lib/BWidget/stddialog.tcl.














































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# ----------------------------------------------------------------------------
#  stddialog.tcl
#  $Id$
# ----------------------------------------------------------------------------
#  Index of commands:
#     - StandardDialog::create
# ----------------------------------------------------------------------------

namespace eval StandardDialog {
    Widget::define StandardDialog stddialog Dialog

    Widget::bwinclude StandardDialog Dialog :cmd

    Widget::declare StandardDialog {
        {-buttonwidth           Int     12              1}
        {-applybutton           Boolean 1               1}
        {-cancelbutton          Boolean 1               1}
    }
}


proc StandardDialog::create { path args } {
    array set maps [Widget::splitArgs $args Dialog StandardDialog]

    array set _args {
        -buttonwidth    12
        -applybutton    1
        -cancelbutton   1
    }
    array set _args $maps(StandardDialog)

    set width   $_args(-buttonwidth)
    set apply   $_args(-applybutton)
    set cancel  $_args(-cancelbutton)
    set buttons [list OK]

    switch -- [tk windowingsystem] {
        "aqua" {
            ## Apply Cancel OK

            set cancelidx  0
            set defaultidx 2

            if {$cancel} { set buttons [linsert $buttons 0 Cancel] }
            if {$apply}  { set buttons [linsert $buttons 0 Apply]  }
        }

        default {
            ## OK Cancel Apply

            set cancelidx  1
            set defaultidx 0

            if {$cancel} { lappend buttons Cancel }
            if {$apply}  { lappend buttons Apply  }
        }
    }

    if {!$cancel} { set cancelidx $defaultidx }

    eval [list Dialog::create $path -class StandardDialog -anchor e \
        -homogeneous 1 -default $defaultidx -cancel $cancelidx -modal local] \
        $maps(:cmd) $maps(Dialog)

    foreach text $buttons {
        set val [string tolower $text]
        $path add -text $text -width $width -name $val -value $val
    }

    return $path
}
Added lib/BWidget/tablelist.tcl.






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
# ---------------------------------------------------------------------------
#  tablelist.tcl
#
#  $Id$
# ---------------------------------------------------------------------------
#  Index of commands:
#
#   Public Commands:
#     - TableList::create
#     - TableList::configure
#     - TableList::cget
#
#   Private Commands:
#     - TableList::_resize
# ---------------------------------------------------------------------------

package require Tk 8.4
package require Tktable

namespace eval TableList {
    Widget::define TableList tablelist Button

    Widget::declare TableList::Column {
        {-name              String      ""         0}
        {-state             Enum        "normal"   0 {disabled normal}}
        {-title             String      ""         0}
        {-width             Int         "0"        0}
        {-column            Int         "-1"       0}
        {-showarrow         Boolean2     ""        0}
        {-formatcommand     String      ""         0}

        {-sortable          Boolean     1          0}
        {-sortargs          String      ""         0}

        {-editstartcommand  String      ""         0}
        {-editfinishcommand String      ""         0}
        {-editcancelcommand String      ""         0}

        {-values            String      ""         0}
        {-editable          Boolean     "1"        0}
        {-editwindow        String      ""         0}
        {-postcommand       String      ""         0}
        {-modifycommand     String      ""         0}
        {-valuescommand     String      ""         0}

        {-browseargs        String      ""         0}
        {-browsebutton      Boolean     "0"        0}
	{-browsecommand     String      ""         0}
    }

    Widget::declare TableList::Item {
        {-row               Int         "-1"       0}
        {-open              Boolean     "0"        0}
        {-data              String      ""         0}
        {-state             Enum        "normal"   0 {disabled normal readonly}}
        {-values            String      {}         0}
    }

    Widget::declare TableList {
        {-rows              Int         "0"        0}
        {-state             Enum        "normal"   0 {disabled normal}}
        {-upimage           String      "::TableList::uparrow"   0}
        {-downimage         String      "::TableList::downarrow" 0}
        {-showarrow         Boolean     1          0}
        {-showtitles        Boolean     1          1}

        {-keycolumn         String      ""         0}
        {-treecolumn        String      "0"        1}

        {-sortargs          String      ""         0}
        {-sortinsert        Boolean     0          0}

        {-browseargs        String      ""         0}
	{-browsecommand     String      ""         0}

        {-editstartcommand  String      ""         0}
        {-editfinishcommand String      ""         0}
        {-editcancelcommand String      ""         0}
    }

    image create photo ::TableList::uparrow \
        -file [file join $::BWIDGET::LIBRARY images uparrow.gif]

    image create photo ::TableList::downarrow \
        -file [file join $::BWIDGET::LIBRARY images downarrow.gif]

    Widget::tkinclude TableList table .t \
        remove {
            -variable -roworigin -cache -state -rows
            -browsecommand -browsecmd -selectioncommand -selcmd
            -command -usecommand -validate -validatecommand -vcmd
        } initialize {
            -background #FFFFFF -sparsearray 0 -rows 1 -relief flat
            -cursor "" -colstretchmode last -anchor w
            -multiline 0 -ellipsis ... -selecttype row -selectmode single
            -bordercursor sb_h_double_arrow -exportselection 0
            -highlightthickness 0 -padx 2 -pady 1
        }

    BWidget::bindMouseWheel TableListTable

    bind TableList <FocusIn> [list after idle [list BWidget::refocus %W %W.t]]
    bind TableList <Destroy> [list TableList::_destroy %W]

    bind TableListTable <1> "TableList::_table_button_1 %W %x %y; break"
    bind TableListTable <Key> [list TableList::_handle_key_press %W %K]
    bind TableListTable <Double-1> [list TableList::_title_double_1 %W %x %y]
    bind TableListTable <Shift-Button-1>   "TableList::_select_row %W %x %y 1"
    bind TableListTable <Control-Button-1> "TableList::_select_row %W %x %y 2"
    bind TableListTable <ButtonRelease-1> [list TableList::selection %W update]

    bind TableListLabel <1> [list TableList::_title_button_1 %W %X %x %y]
    bind TableListLabel <Motion> [list TableList::_title_motion %W %x %y]
    bind TableListLabel <B1-Motion> [list TableList::_title_motion_1 %W %X]
    bind TableListLabel <ButtonRelease-1> [list TableList::_title_release_1 %W]
    bind TableListLabel <Double-1> [list TableList::_title_double_1 %W %x %y]
    bind TableListLabel <Configure> [list TableList::_configure_col %W %w]

    ## Define the X pixel threshold for resize borders.
    variable _threshold 5
}


proc TableList::create { path args } {
    Widget::initArgs TableList $args maps

    frame $path -class TableList \
        -borderwidth 0 -highlightthickness 0 -relief flat -takefocus 0

    Widget::initFromODB TableList $path $maps(TableList)

    Widget::getVariable $path data

    array set data {
        sort            0
        items           {}
        resize          0
        labels          {}
        setting         0
        rowCount        0
        selected        {}
        sortColumn      -1
        sortDirection   -1
        selectionAnchor 0
    }

    set data(keyColumn) [Widget::getoption $path -keycolumn]

    Widget::getVariable $path items
    set items(root)   ""
    set items(root,c) [list]

    set opts [list -state disabled -bordercursor sb_h_double_arrow]
    lappend opts -command [list TableList::_get_set_value $path %r %c %i %s]

    if {[Widget::getoption $path -showtitles]} {
        lappend opts -roworigin -1 -resizeborders none -titlerows 1
    } else {
        lappend opts -roworigin 0 -resizeborders col -titlerows 0
    }

    set table $path.t
    eval [list table $table] $opts $maps(.t)
    set top [winfo toplevel $path.t]
    bindtags $path.t [list $path.t TableListTable Table $top all]

    pack $path.t -expand 1 -fill both

    $table tag configure sel -relief flat

    set data(font)    [$table cget -font]
    set data(colvars) [list path size largest invalidSize titleElided]

    redraw $path

    Widget::create TableList $path

    proc ::$path { cmd args } \
        "return \[TableList::_path_command [list $path] \$cmd \$args\]"

    return $path
}


proc TableList::configure { path args } {
    set res [Widget::configure $path $args]

    set table [gettable $path]

    Widget::getVariable $path data

    set redrawCols 0
    set redrawRows 0

    if {[Widget::hasChanged $path -cols cols]} {
        set redrawCols 1
    }

    if {[Widget::hasChanged $path -rows rows]} {
        set data(rowCount) $rows
        set redrawRows 1
    }

    if {[Widget::hasChanged $path -font font]} {
        set data(font) $font
        set redrawCols 1
        set redrawRows 1
    }

    if {[Widget::hasChanged $path -keycolumn keycol]} {
        set data(keyColumn) [_get_col_index $path $keycol]
    }

    if {[Widget::hasChanged $path -showarrow arrow]} {
        set redrawCols 1
    }

    if {[Widget::hasChanged $path -state state]} {
        TableList::edit $path finish
    }

    if {$redrawRows} { _redraw_rows_idle $path }
    if {$redrawCols} { _redraw_cols_idle $path }

    return $res
}


proc TableList::cget { path option } {
    return [Widget::cget $path $option]
}


proc TableList::itemconfigure { path item args } {
    if {![TableList::exists $path $item]} {
        return -code error "item \"$item\" does not exist"
    }

    set i $path#item#$item
    set res [Widget::configure $i $args]
    set refresh 0

    if {[Widget::hasChanged $i -open open]} {
        TableList::_redraw_rows_idle $path
    }

    if {[Widget::hasChanged $i -row row]} {
        TableList::move $path $item [expr {$row + 1}]
    }

    if {[Widget::hasChanged $i -state state]} {
        if {[TableList::edit $path current] eq $item} {
            TableList::edit $path finish
        }
    }

    if {[Widget::hasChanged $i -values values]} {
        set refresh 1
    }

    if {$refresh} {
        [gettable $path] configure -drawmode [$table cget -drawmode]
    }

    return $res
}


proc TableList::itemcget { path item option } {
    if {![TableList::exists $path $item]} {
        return -code error "item \"$item\" does not exist"
    }
    return [Widget::cget $path#item#$item $option]
}


proc TableList::clear { path } {
    eval [list TableList::delete $path] [TableList::items $path root]
}


proc TableList::column { path command args } {
    Widget::getVariable $path data

    switch -- $command {
        "cget" {
            set idx [_get_col_index $path [lindex $args 0]]
            set col $path#column#$idx
            return [Widget::getoption $col [lindex $args 1]]
        }

        "configure" {
            set idx [_get_col_index $path [lindex $args 0]]
            _columnconfigure $path $idx [lrange $args 1 end]
        }

        "delete" {

        }

        "index" {
            return [_get_col_index $path [lindex $args 0]]
        }

        "insert" {

        }

        "label" {
            return $data([_get_col_index $path [lindex $args 0]],path)
        }

        "move" {
            set col     [lindex $args 0]
            set idx     [_get_col_index $path $col]
            set index   [lindex $args 1]
            set column  $path#column#$idx
            set name    [Widget::getoption $column -name]
            set columns [linsert $data(columns) $index $name]

            if {$index < $idx} { incr idx }
            set columns [lreplace $columns $idx $idx]

            _reorder_cols_idle $path $columns
        }

        "order" {
            if {![llength $args]} { return $data(columns) }
            set neworder [lindex $args 0]
            _reorder_cols_idle $path $neworder
        }
    }
}



proc TableList::curselection { path } {
    return [TableList::selection $path get]
}


proc TableList::delete { path args } {
    Widget::getVariable $path items

    TableList::edit $path finish

    foreach item $args {
        if {![info exists items($item)]} { continue }

        Widget::destroy $path#item#$item 0

        set parent $items($item)
        set index  [TableList::index $path $item]

        set items($parent,c) [lreplace $items($parent,c) $index $index]
    }

    _redraw_rows_idle $path
}


proc TableList::edit { path command args } {
    Widget::getVariable $path data

    if {[info exists data(editing)]
        && ![Widget::exists $path#item#$data(editing)]} { unset data(editing) }

    switch -- $command {
	"start" {
	    eval [list _start_edit $path] $args
	}

	"finish" - "cancel" {
	    if {![info exists data(editing)]} { return }

            set row   $data(editrow)
            set col   $data(editcol)
	    set item  $data(editing)
            set table [TableList::gettable $path]

	    set cmd [_option $path $col -edit${command}command]
            if {![_eval_command $path $item $col $cmd]} { return }

	    destroy $path.edit

            ## The -edit(cancel|finish)command might have cancelled
            ## or finished this operation already.  If they did,
            ## we skip the rest of this.
	    if {![info exists data(editing)]} { return }

            if {[string equal $command "finish"]} {
                set val $data(editvalue)

                set values [Widget::getoption $path#item#$item -values]
                set values [lreplace $values $col $col $val]
                Widget::setoption $path#item#$item -values $values

                ## If this item is the largest in the column, we
                ## invalidate the size of the column.
                if {[string equal $data($col,largest) $item]} {
                    set data($col,invalidSize) 1
                }
            }

            set window $path.label$row,$col
            if {[winfo exists $window]} {
                ## This cell has a tree label and cross.  We need
                ## to update the label and put the label back in.
                $window.l configure -text "[_get_set_value $path $row $col]"
                $table window configure $row,$col -sticky news \
                    -window $window -padx 1 -pady 1
            }

            set vars [list editing editpath entrypath browsepath valuespath]
            foreach var $vars {
                if {[info exists data($var)]} { unset data($var) }
            }

            focus $table
	}

        "reread" {
            if {[info exists data(editing)]} {
            set data(editvalue) $data(value)
        }
        }

	"active" - "current" {
	    if {[info exists data(editing)]} { return $data(editing) }
	}

        "activecell" - "currentcell" {
	    if {[info exists data(editing)]} {
                return $data(editrow),$data(editcol)
            }
        }

        "editvalue" {
	    if {[info exists data(editing)]} {
                if {[llength $args]} {
                    set data(editvalue) [lindex $args 0]
                }
                return $data($command)
            }
        }

        "value"      -
        "values"     -
        "editable"   -
        "editpath"   -
        "entrypath"  -
        "browsepath" -
        "valuespath" {
	    if {[info exists data(editing)]} { return $data($command) }
        }
    }
}


proc TableList::exists { path item } {
    return [expr {$item eq "root" || [Widget::exists $path#item#$item]}]
}


proc TableList::get { path args } {
    set table [gettable $path]

    BWidget::ParseArgs _args $args \
        -switches [list -formatted -selected -visible]

    set switches $_args(SWITCHES)
    switch -- [lindex $_args(_ARGS_) 0] {
        "col" - "column" {
            BWidget::ParseArgs _args $_args(_ARGS_) -options [list -parent]
            set col [_get_col_index $path [lindex $_args(_ARGS_) 1]]

            if {$_args(selected)} {
                Widget::getVariable $path data

                set list [list]
                foreach item $data(selected) {
                    set values [Widget::getoption $path#item#$item -values]
                    if {$_args(formatted)} {
                        set row [Widget::getoption $path#item#$item -row]
                        lappend list [$table get $row,$col]
                    } else {
                        lappend list [lindex $values $col]
                    }
                }
                return $list
            }

            return [$table get 0,$col [$table cget -rows],$col]
        }

        "item" {
            set item [lindex $_args(_ARGS_) 1]
            set row  [Widget::getoption $path#item#$item -row]
            return [eval [list TableList::get $path] $switches row $row]
        }

        "items" {
            set rows [list]
            foreach item [lrange $_args(_ARGS_) 1 end] {
                lappend rows [Widget::getoption $path#item#$item -row]
            }
            return [eval [list TableList::get $path] $switches rows $rows]
        }

        "row" {
            Widget::getVariable $path data

            set list [list]
            set last [$table cget -cols]
            set row  [lindex $_args(_ARGS_) 1]
            set item [lindex $data(items) $row]

            if {$_args(formatted)} {
                return [$table get $row,0 $row,$last]
            } else {
                return [Widget::getoption $path#item#$item -values]
            }
        }

        "rows" {
            Widget::getVariable $path data

            set list [list]
            set last [$table cget -cols]
            foreach row [lrange $_args(_ARGS_) 1 end] {
                set item [lindex $data(items) $row]

                if {$_args(formatted)} {
                    lappend list [$table get $row,0 $row,$last]
                } else {
                    lappend list [Widget::getoption $path#item#$item -values]
                }
            }

            return $list
        }

        "selected" {
            set sel [TableList::selection $path get]
            return [eval [list TableList::get $path] $switches item $sel]
        }

        "value" {
            set item [lindex $_args(_ARGS_) 1]
            set col  [lindex $_args(_ARGS_) 2]

            set val [eval [list TableList::get $path] $switches item $item]
            return  [lindex $val $col]
        }

        default {
            return [eval [list $table get] $_args(_ARGS_)]
        }
    }
}


proc TableList::gettable { path } {
    return $path.t
}


proc TableList::index { path item } {
    Widget::getVariable $path items

    if {![info exists items($item)]} {
        return -code error "item \"$item\" does not exist"
    }

    return [lsearch -exact $items($items($item),c) $item]
}


proc TableList::insert { path index parent item args } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    set item [Widget::nextIndex $path $item]

    if {[info exists items($item)]} {
        return -code error "item \"$item\" already exists"
    }

    if {![info exists items($parent)]} {
        return -code error "item \"$item\" does not exist"
    }

    set items($item) $parent

    Widget::init TableList::Item $path#item#$item $args

    if {$index eq "end"} {
        lappend items($parent,c) $item
    } else {
        set items($parent,c) [linsert $items($parent,c) $index $item]
    }

    if {$data(sortColumn) > -1 && [Widget::getoption $path -sortinsert]} {
        _sort_rows_idle   $path
    } else {
        _redraw_rows_idle $path
    }

    _invalidate_cols_idle $path

    return $item
}


proc TableList::items { path parent {first ""} {last ""} } {
    Widget::getVariable $path items

    if {![info exists items($parent)]} {
        return -code error "item \"$parent\" does not exist"
    }

    if {![info exists items($parent,c)]} { return }

    if {![string length $first]} { return $items($parent,c) }
    if {![string length $last]}  { return [lindex $items($parent,c) $first] }
    return [lrange $items($parent,c) $first $last]
}


proc TableList::move { path parent item index } {
    Widget::getVariable $path data

    if {![TableList::exists $path $item]} {
        return -code error "item \"$item\" does not exist"
    }

    set oldindex [Widget::getoption $path#item#$item -row]

    if {$oldindex == 0 && $index == $oldindex} { return }
    if {$oldindex != 0 && $index == [expr {$oldindex + 1}]} { return }

    set data(items) [linsert $data(items) $index $item]

    if {$index < $oldindex} { incr oldindex }
    set data(items) [lreplace $data(items) $oldindex $oldindex]

    _redraw_rows_idle $path
}


proc TableList::parent { path item } {
    Widget::getVariable $path items
    if {![info exists items($item)]} {
        return -code error "item \"$item\" does not exist"
    }
    return $items($item)
}


proc TableList::redraw { path } {
    _redraw_rows $path
    _redraw_cols $path
}


proc TableList::reorder { path parent neworder } {
    Widget::getVariable $path items

    if {![info exists items($parent)]} {
        return -code error "item \"$parent\" does not exist"
    }

    set items($parent,c) $neworder

    _redraw_rows_idle $path
}


proc TableList::see { path args } {
    set table [gettable $path]

    update idletasks

    switch -- [lindex $args 0] {
        "cell" {
            $table see [lindex $args 1]
        }

        "item" {
            set item [lindex $args 1]
            set col  [lindex $args 2]
            if {![string length $col]} { set col 0 }

            if {![TableList::exists $path $item]} {
                return -code error "item \"$item\" does not exist"
            }

            set row [Widget::getoption $path#item#$item -row]
            $table see $row,$col
        }

        default {
            eval [list $table see] $args
        }
    }

    return
}


proc TableList::selection { path command args } {
    if {[Widget::exists $path]} { Widget::getVariable $path data }

    set table [TableList::gettable $path]

    switch -- $command {
        "add" {
            foreach item $args {
                if {![TableList::exists $path $item]} {
                    return -code error "item \"$item\" does not exist"
                }
                set row [Widget::getoption $path#item#$item -row]
                $table selection set $row,0
                lappend data(selected) $item
            }

            event generate $path <<TableListSelect>>

            return $data(selected)
        }

        "clear" {
            if {![llength $args]} { set args all }
            eval [list $table selection clear] $args
            TableList::selection $path update
        }

        "get" {
            return $data(selected)
        }

        "includes" {
            set item [lindex $args 0]
            return [expr {[lsearch -exact $data(selected) $item] > -1}]
        }

        "range" {
            set item1 [lindex $args 0]
            if {![TableList::exists $path $item1]} {
                return -code error "item \"$item1\" does not exist"
            }

            set item2 [lindex $args 1]
            if {![TableList::exists $path $item2]} {
                return -code error "item \"$item2\" does not exist"
            }

            set first [Widget::getoption $path#item#$item1 -row]
            set last  [Widget::getoption $path#item#$item2 -row]

            $table selection clear all
            $table selection set $first,0 $last,0

            TableList::selection $path update
        }

        "remove" {
            foreach item $args {
                if {![TableList::exists $path $item]} {
                    return -code error "item \"$item\" does not exist"
                }
                set row [Widget::getoption $path#item#$item -row]
                $table selection clear $row,0
            }

            TableList::selection $path update
        }

        "set" {
            $table selection clear all
            foreach item $args {
                if {![TableList::exists $path $item]} {
                    return -code error "item \"$item\" does not exist"
                }
                set row [Widget::getoption $path#item#$item -row]
                $table selection set $row,0
            }

            event generate $path <<TableListSelect>>

            set data(selected) $args
        }

        "toggle" {
            foreach item $args {
                if {![TableList::exists $path $item]} {
                    return -code error "item \"$item\" does not exist"
                }
                set row [Widget::getoption $path#item#$item -row]
                if {[lsearch -exact $data(selected) $item] > -1} {
                    $table selection clear $row,0
                } else {
                    $table selection set $row,0
                }
            }

            TableList::selection $path update
        }

        "update" {
            if {[string equal [winfo class $path] "Table"]} {
                set table $path
                set path  [winfo parent $path]
                Widget::getVariable $path data
            }

            set data(selected) [list]
            foreach row [$table tag row sel] {
                lappend data(selected) [lindex $data(items) $row]
            }

            event generate $path <<TableListSelect>>

            return $data(selected)
        }
    }
}


proc TableList::sort { path col args } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    array set _args {
        parent  root
    }
    BWidget::ParseArgs _args $args -options [list -parent] \
        -switches [list -increasing -decreasing -recursive]
    
    set col    [TableList::_get_col_index $path $col]
    set parent $_args(parent)
    set column $path#column#$col

    if {![TableList::exists $path $parent]} {
        return -code error "item \"$parent\" does not exist"
    }

    set sortargs [TableList::_option $path $col -sortargs]

    if {[set idx [lsearch -exact $sortargs "-recursive"]] > -1} {
        set _args(recursive) 1
        set sortargs [lreplace $sortargs $idx $idx]
    }

    set direction 0
    if {!$direction} {
        set direction -1
        if {$col == $data(sortColumn)} {
            if {$data(sortDirection) == 1} {
                set direction -1
            } else {
                set direction 1
            }
        }
    }

    if {[lsearch -exact $_args(SWITCHES) "-increasing"] > -1 } {
        lappend sortargs -increasing
    } elseif {[lsearch -exact $_args(SWITCHES) "-decreasing"] > -1} {
        lappend sortargs -decreasing
    } else {
        if {$direction == -1} {
            lappend sortargs -increasing
        } else {
            lappend sortargs -decreasing
        }
    }

    foreach item $items($parent,c) {
        set value [lindex [Widget::getoption $path#item#$item -values] $col]
        lappend sort($value) $item
        if {[info exists items($item,c)]} { lappend parents $item }
    }

    set items($parent,c) [list]
    foreach value [eval lsort $sortargs [list [array names sort]]] {
        eval lappend items($parent,c) $sort($value)
    }

    if {$_args(recursive) && [info exists parents]} {
        foreach parent $parents {
            TableList::sort $path $col -parent $parent \
                -recursive [lindex $sortargs end]
        }
    }

    set data(sortColumn)    $col
    set data(sortDirection) $direction

    _redraw_cols_idle $path
    _redraw_rows_idle $path
}


proc TableList::toggle { path item } {
    if {![TableList::exists $path $item]} {
        return -code error "item \"$item\" does not exist"
    }

    if {[Widget::getoption $path#item#$item -open]} {
        TableList::itemconfigure $path $item -open 0
    } else {
        TableList::itemconfigure $path $item -open 1
    }
}


proc TableList::visible { path item } {
    if {![TableList::exists $path $item]} {
        return -code error "item \"$item\" does not exist"
    }

    return [expr {[Widget::getoption $path#item#$item -row] > -1}]
}


proc TableList::_path_command { path cmd larg } {
    if {[string length [info commands ::TableList::$cmd]]} {
        return [eval [linsert $larg 0 TableList::$cmd $path]]
    } else {
        set table [TableList::gettable $path]
        if {$cmd eq "set"} {
            $table configure -state normal
            set result [eval [linsert $larg 0 $table $cmd]]
            $table configure -state disabled
        } else {
            set result [eval [linsert $larg 0 $table $cmd]]
        }
        
        return $result
    }
}


proc TableList::_redraw_item { path item {level -1} } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    set col [_get_col_index $path [Widget::getoption $path -treecolumn]]
    if {$col < 0} { return }

    set parent      $items($item)
    set hasChildren [info exists items($item,c)]
    if {$parent eq "root" && !$hasChildren} { return }

    if {$level < 0} {
        set level  0
        while {$parent ne "root"} {
            incr level
            set parent $items($parent)
        }
    }

    set row    $data(rowCount)
    set table  [TableList::gettable $path]
    set window $path.label$row,$col
    set label  $window

    if {![winfo exists $window]} {
        set bg [Widget::cget $path -bg]

        if {$hasChildren} {
            frame $window -bg $bg

            button $window.b -bg $bg -bd 1 -relief flat \
                -command [list $path toggle $item]
            pack $window.b -side left -padx [list [expr {$level * 20}] 0]

            set label $window.l
        }

        Label $label -bg $bg -elide 1 -anchor nw \
            -font $data(font) -borderwidth 0 \
            -padx 0 -pady 0 -highlightthickness 0
        bind $label <1> \
            [list TableList::_handle_tree_label_click $path $row $col]

        if {$hasChildren} {
            pack $label -side left -expand 1 -fill x
        } else {
            $label configure -padx [expr {$level * 20}]
        }
    }

    if {[winfo exists $window.b]} {
        set image [BWidget::Icon tree-plus]
        if {[Widget::getoption $path#item#$item -open]} {
            set image [BWidget::Icon tree-minus]
        }
        $window.b configure -image $image
        set label $window.l
    }

    $label configure -text "[_get_set_value $path $row $col]"

    $table window configure $row,$col -sticky news \
        -window $window -padx 1 -pady 1
    lappend data(labels) $row,$col

    _redraw_cols_idle $path
}


proc TableList::_redraw_rows_idle { path } {
    Widget::getVariable $path data

    if {![info exists data(redrawRows)]} {
        after idle [list TableList::_redraw_rows $path]
        set data(redrawRows) 1
    }
}


proc TableList::_redraw_rows { path {parent root} {level 0} } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    if {$parent eq "root"} {
        set data(items)    [list]
        set data(rowCount) -1

        set table   [TableList::gettable $path]
        if {[llength $data(labels)]} {
            eval [list $table window delete] $data(labels)
        }
    } else {
        _redraw_item $path $parent $level

        if {![Widget::getoption $path#item#$parent -open]} { return }

        incr level
    }

    foreach item $items($parent,c) {
        lappend data(items) $item
        Widget::setoption $path#item#$item -row [incr data(rowCount)]
        TableList::_redraw_rows $path $item $level
    }

    if {$parent eq "root"} {
        set table [TableList::gettable $path]

        incr data(rowCount)
        set rowcount $data(rowCount)
        if {[Widget::getoption $path -showtitles]} { incr rowcount }

        $table configure -rows $rowcount -state disabled

        Widget::setoption $path -rows $data(rowCount)

        set rows [list]
        for {set i 1} {$i < [$table cget -rows]} {incr i 2} {
            lappend rows $i
        }
        eval [list $table tag row alt] $rows

        if {[llength $data(selected)]} {
            set selected [list]
            foreach item $data(selected) {
                if {[Widget::exists $path#item#$item]} {
                    lappend selected $item
                }
            }
            eval [list TableList::selection $path set] $selected
        }

        unset -nocomplain data(redrawRows)
    }
}


proc TableList::_sort_rows_idle { path } {
    Widget::getVariable $path data

    if {![info exists data(sortRows)]} {
        after idle [list TableList::_sort_rows $path]
        set data(sortRows) 1
    }
}


proc TableList::_sort_rows { path } {
    Widget::getVariable $path data

    TableList::sort $path $data(sortColumn) $data(sortDirection)

    unset -nocomplain data(sortRows)
}


proc TableList::_columnconfigure { path col options } {
    Widget::getVariable $path data

    set column $path#column#$col

    set oldcol  [Widget::getoption $column -column]
    set oldname [Widget::getoption $column -name]

    set res [Widget::configure $column $options]

    set table [gettable $path]

    set redrawCol 0

    if {[Widget::hasChanged $column -name name]} {
        set idx [lsearch -exact $data(columns) $oldname]
        set data(columns) [lreplace $data(columns) $idx $idx $name]
    }

    if {[Widget::hasChanged $column -state state] && $state eq "disabled"} {
        if {[info exists data(editing)] && $col == $data(editcol)} {
            TableList::edit $path finish
        }
    }

    if {[Widget::hasChanged $column -column newcol]} {
        Widget::setoption $column -column $oldcol
        TableList::column $path move $col [expr {$newcol + 1}]
    }

    if {[Widget::hasChanged $column -title title]} {
        set redrawCol 1
    }

    if {[Widget::hasChanged $column -width width]} {
        set redrawCol 1
        $table width $col $width
    }

    if {[Widget::hasChanged $column -showarrow arrow]} {
        set redrawCol 1
    }

    if {[Widget::hasChanged $column -formatcommand cmd]} {
        ## Force the table widget to redraw.
        $table configure -state normal -state disabled
    }

    if {$redrawCol} { _redraw_col $path $col }

    return $res
}


proc TableList::_redraw_cols_idle { path } {
    Widget::getVariable $path data

    if {![info exists data(redrawCols)]} {
        after idle [list TableList::_redraw_cols $path]
        set data(redrawCols) 1
    }
}


proc TableList::_redraw_cols { path } {
    Widget::getVariable $path data

    set cols [[gettable $path] cget -cols]
    for {set i 0} {$i < $cols} {incr i} {
        _redraw_col $path $i
    }

    unset -nocomplain data(redrawCols)
}


proc TableList::_redraw_col { path col } {
    Widget::getVariable $path data

    set table  [TableList::gettable $path]
    set column $path#column#$col

    if {![Widget::exists $column]} {
        ## This is a new column.
        lappend data(columns) column$col

        set data($col,path)        $path.column$col
        set data($col,size)        0
        set data($col,largest)     ""
        set data($col,invalidSize) 1
        set data($col,titleElided) 0

        set data($data($col,path),col) $col

        set opts [list -name column$col -column $col -width [$table width $col]]
        Widget::init TableList::Column $column $opts
    }

    set label $data($col,path)

    if {[Widget::getoption $path -showtitles]} {
        if {![winfo exists $label]} {
            set top [winfo toplevel $path]
            label $label -relief raised -borderwidth 2 -compound right -anchor w
            bindtags $label [list $label TableListLabel $top all]
            $table window configure -1,$col -window $label -sticky news \
                -padx 0 -pady 0
            $table tag col column$col $col
        }

        set title [Widget::getoption $column -title]

        $label configure -font $data(font)

        if {$col == $data(sortColumn) && [_option $path $col -showarrow]} {
            if {$data(sortDirection) == -1} {
                set image [Widget::getoption $path -upimage]
            } else {
                set image [Widget::getoption $path -downimage]
            }
            $label configure -image $image -text "$title  "
        } else {
            $label configure -image "" -text $title
        }

        _configure_col $label [winfo width $label]
    }
}


proc TableList::_reorder_cols_idle { path columns } {
    Widget::getVariable $path data

    if {![info exists data(reorderCols)]} {
        after idle [list TableList::_reorder_cols $path $columns]
        set data(reorderCols) 1
    }
}


proc TableList::_reorder_cols { path columns } {
    Widget::getVariable $path data

    set newidx 0
    foreach column $columns {
        set oldidx [lsearch -exact $data(columns) $column]

        foreach var $data(colvars) {
            set new($newidx,$var) $data($oldidx,$var)
            unset data($oldidx,$var)
        }

        incr newidx
    }

    array set data [array get new]

    set data(columns) $columns

    set col    0
    set table  [gettable $path]
    set widths [list]
    foreach column $data(columns) {
        Widget::setoption $path#column#$col -column $col
        lappend widths $col [Widget::getoption $path#column#$col -width]
        if {[Widget::getoption $path -showtitles]} {
            $table window configure -1,$col -window $data($col,path) \
                -sticky news -padx 0 -pady 0
        }
        incr col
    }

    eval [list $table width] $widths

    _redraw_cols $path

    unset -nocomplain data(reorderCols)
}


proc TableList::_invalidate_cols_idle { path } {
    Widget::getVariable $path data
    if {![info exists data(invalidCols)]} {
        set data(invalidCols) 1
        after idle [list TableList::_invalidate_cols $path]
    }
}


proc TableList::_invalidate_cols { path } {
    Widget::getVariable $path data

    set table [gettable $path]

    for {set col 0} {$col < [$table cget -cols]} {incr col} {
        set data($col,invalidSize) 1
    }

    unset -nocomplain data(invalidCols)
}


proc TableList::_border_column { widget col x y } {
    set n $::TableList::_threshold
    set w [winfo width $widget]

    if {$col > 0 && $x <= $n}   { return [incr col -1] }
    if {$x >= [expr {$w - $n}]} { return $col }
    return -1
}


proc TableList::_title_motion { widget x y } {
    set path [winfo parent $widget]
    Widget::getVariable $path data

    set col $data($widget,col)
    if {[_border_column $widget $col $x $y] > -1} {
        $widget configure -cursor [Widget::cget $path -bordercursor]
    } else {
        $widget configure -cursor [Widget::cget $path -cursor]
    }
}


proc TableList::_title_button_1 { widget X x y } {
    set path  [winfo parent $widget]
    Widget::getVariable $path data

    set col    $data($widget,col)
    set table  [gettable $path]
    set border [_border_column $widget $col $x $y]

    if {$border > -1} {
        set data(resize)      1
        set data(resizeX)     $X
        set data(resizeCol)   $border
        set data(resizeWidth) [winfo width $data($border,path)]
    } else {
        set data(resize) 0
        if {[Widget::getoption $path#column#$col -sortable]} {
            set data(sort) 1
            TableList::edit $path cancel
            $widget configure -relief sunken
        }
    }
}


proc TableList::_title_motion_1 { widget X } {
    set path  [winfo parent $widget]
    Widget::getVariable $path data

    if {$data(resize)} {
        set width [expr {$data(resizeWidth) + ($X - $data(resizeX))}]
        if {$width > 0} { [gettable $path] width $data(resizeCol) -$width }
    }
}


proc TableList::_title_release_1 { widget } {
    set path [winfo parent $widget]
    Widget::getVariable $path data

    set table [TableList::gettable $path]

    if {$data(sort)} {
        set col $data($widget,col)
        set column $path#column#$col
        TableList::sort $path [Widget::getoption $column -column]
        $widget configure -relief raised
    }

    set data(sort)   0
    set data(resize) 0

    focus $table
}


proc TableList::_title_double_1 { widget x y } {
    set path [winfo parent $widget]
    Widget::getVariable $path data

    set table [gettable $path]

    if {$widget eq $table} {
        set col [lindex [$widget border mark $x $y col] 0]
        if {![string length $col]} { return }
    } else {
        set col $data($widget,col)
        if {[set col [_border_column $widget $col $x $y]] < 0} { return }
    }

    ## They double-clicked on a column resize border.  We want to
    ## shrink or expand the column width to fit the largest string
    ## in the column.

    if {$data($col,invalidSize)} {
        _configure_col_size $path $col
    }

    set width [expr {$data($col,size) + 8}]

    $table width $col -$width

    if {$widget ne $table} {
        _configure_col $widget $width

        update idletasks

        ## Adjust the cursor.
        set X [winfo pointerx $path]
        set Y [winfo pointery $path]
        set w [winfo containing $X $Y]
        set x [expr {$X - [winfo rootx $w]}]
        set y [expr {$Y - [winfo rooty $w]}]

        _title_motion $w $x $y
    }

    focus $table
}


proc TableList::_configure_col { label width } {
    set path  [winfo parent $label]
    Widget::getVariable $path data

    set col    $data($label,col)
    set column $path#column#$col

    set table [gettable $path]
    set font  [$table cget -font]
    set title [Widget::getoption $column -title]
    set ellipsis [$table cget -ellipsis]

    set sorted 0
    if {$col == $data(sortColumn) && [_option $path $col -showarrow]} {
        set sorted 1
        incr width -[image width [$label cget -image]]
        incr width -[font measure $font "  "]
    }

    set text   $title
    set elided 0
    while {[font measure $font $title] > $width} {
        set text   [string range $text 0 end-1]
        set title  $text$ellipsis
        set elided 1
        if {![string length $text]} { break }
    }

    set data($col,titleElided) $elided

    if {!$elided && $sorted} { append title "  " }

    $label configure -text $title

    Widget::setoption $column -width [$table width $col]
}


proc TableList::_get_set_value { path row col {which -1} {value ""} } {
    if {$row < 0} { return }

    Widget::getVariable $path data
    set item [lindex $data(items) $row]

    if {![Widget::exists $path#item#$item]} { return }

    if {$which <= 0} {
        if {![string length $item]} { return }
        set value [lindex [Widget::getoption $path#item#$item -values] $col]

        if {$which == 0} {
            set cmd [Widget::getoption $path#column#$col -formatcommand]
            if {[string length $cmd]} { set value [eval $cmd [list $value]] }
        }

        return $value
    }

    set values [Widget::getoption $path#item#$item -values]
    set values [lreplace $values $col $col $value]
    Widget::setoption $path#item#$item -values $values

    return $value
}


proc TableList::_configure_col_size { path {col -1} {string ""} } {
    Widget::getVariable $path data

    if {[string length $string]} {
        set size [font measure $data(font) $string]
        if {$size > $data($col,size)} { set data($col,size) $size }
        return
    }

    set table [gettable $path]
    set rows  [$table cget -rows]
    set cols  [$table cget -cols]

    if {$col < 0} {
        for {set i 0} {$i < $cols} {incr i} { lappend cols $i }
    } else {
        set cols $col
    }

    set treecol [_get_col_index $path [Widget::getoption $path -treecolumn]]

    foreach col $cols {
        set data($col,size)        0
        set data($col,invalidSize) 0
        set row 0
        foreach item $data(items) {
            set size [font measure $data(font) [$table get $row,$col]]
            if {$col == $treecol && [winfo exists $path.label$row,$col]} {
                incr size [winfo width $path.label$row,$col.b]
            }
            if {$size > $data($col,size)} {
                set data($col,size)    $size
                set data($col,largest) $item
            }
            incr row
        }
    }
}


proc TableList::_table_button_1 { table x y } {
    set path [winfo parent $table]
    Widget::getVariable $path data

    set row  [$table index @$x,$y row]
    set col  [$table index @$x,$y col]
    set last [$table index end row]
    set cell $row,$col

    set bbox [$table bbox $cell]
    if {![llength $bbox]} { return }
    foreach [list bx by bw bh] $bbox { break }

    TableList::edit $path finish
    TableList::selection $path clear

    if {$row == $last && $y > [expr {$by + $bh}]} { return -code break }

    set item [lindex $data(items) $row]
    set data(selectionAnchor) $row
    TableList::selection $path set $item
    if {$item ne "" && ![info exists data(editing)]} {
        TableList::edit $path start $item $col
    }
}


proc TableList::_start_edit { path item col } {
    Widget::getVariable $path data

    if {[TableList::_is_disabled $path $item $col]} { return }

    if {[info exists data(editing)]} { TableList::edit $path finish }

    update idletasks

    foreach var [list editpath entrypath browsepath valuespath] {
        set data($var) ""
    }

    set col [_get_col_index $path $col]

    set column $path#column#$col

    set font     $data(font)
    set window   [Widget::getoption $column -editwindow]
    set values   [Widget::getoption $column -values]
    set valcmd   [Widget::getoption $column -valuescommand]
    set editable [Widget::getoption $column -editable]

    set combobox 0
    if {[string length $values] || [string length $valcmd]} { set combobox 1 }

    frame $path.edit

    set var [Widget::widgetVar $path data(editvalue)]

    if {![string length $window]} {
	if {![Widget::getoption $column -browsebutton]} {
            if {!$combobox} {
		set widget $path.edit.e
                set entry  $widget
		Entry $entry -bd 1 -font $font -textvariable $var \
                    -editable $editable
	    } else {
                set widget  $path.edit.cb
		set entry   $widget.e
                set modcmd  [Widget::getoption $column -modifycommand]
                set postcmd [Widget::getoption $column -postcommand]

                if {[string length $valcmd]} {
                    set values [_eval_command $path $item $column $valcmd]
                }

		ComboBox $widget -borderwidth 1 -font $font \
                    -hottrack 1 -exportselection 0 -textvariable $var \
                    -values $values -editable $editable \
                    -postcommand [_map_command $path $item $column $postcmd] \
                    -modifycommand [_map_command $path $item $column $modcmd]

                set data(valuespath) $widget
	    }
	} else {
            if {!$combobox} {
                set widget $path.edit.e
                set entry  $widget
                Entry $entry -bd 1 -font $font -textvariable $var -width 1 \
                    -editable $editable
            } else {
                set widget  $path.edit.combo
		set entry   $widget.e
                set modcmd  [Widget::getoption $column -modifycommand]
                set postcmd [Widget::getoption $column -postcommand]

                if {[string length $valcmd]} {
                    set values [_eval_command $path $item $column $valcmd]
                }

		ComboBox $widget -borderwidth 1 -font $font \
                    -exportselection 0 -hottrack 1 -textvariable $var \
                    -values $values -editable $editable \
                    -modifycommand $modcmd -postcommand $postcmd

                set data(valuespath) $widget
            }

            set data(browsepath) $path.edit.b

            set args    [_option $path $col -browseargs]
            set command [_option $path $col -browsecommand]
            lappend args -command [_map_command $path $item $col $command]
            set args [linsert $args 0 -text ...]

            if {[BWidget::using ttk]} {
                eval [list ttk::button $data(browsepath)] $args
            } else {
                set args [linsert $args 0 -relief link]
                eval [list Button $path.edit.b] $args

                if {[string length [$path.edit.b cget -image]]} {
                    $path.edit.b configure \
                        -height [expr {[winfo reqheight $entry] - 4}]
                }
            }
            pack $path.edit.b -side right
	}

        pack $widget -side left -expand 1 -fill x
        bind $entry <Escape> "$path edit cancel; break"
        bind $entry <Return> "$path edit finish; break"
    } else {
	## The user has given us a window to use for editing.  Walk
	## through the immediate children and see if we can find an
	## entry widget to focus on.

        place $window -in $path.edit -x 0 -y 0 -relwidth 1.0 -relheight 1.0

        set widget $window
	set entry  $window
	foreach child [winfo children $window] {
	    if {[string equal [winfo class $child] "Entry"]} {
                set entry $child
                break
            }
	}
    }

    set row   [Widget::getoption $path#item#$item -row]
    set cell  $row,$col
    set table [TableList::gettable $path]

    set data(value)     [_get_set_value $path $row $col]
    set data(values)    $values
    set data(editing)   $item
    set data(editcol)   $col
    set data(editrow)   $row
    set data(editable)  $editable
    set data(editpath)  $path.edit
    set data(entrypath) $entry
    set data(editvalue) $data(value)

    $table see $cell

    $table window configure $cell -window $data(editpath) -sticky news -padx 2

    set class [winfo class $entry]
    if {$editable && ($class eq "Entry" || $class eq "Spinbox")} {
        bind $entry <Shift-Tab> [list TableList::_handle_tab_key_press $path -1]
        bind $entry <Tab> [list TableList::_handle_tab_key_press $path 1]
	$entry selection range 0 end
    }

    focus -force $entry

    set cmd [_option $path $col -editstartcommand]
    if {![_eval_command $path $item $col $cmd]} { edit $path cancel; return }

    ## If we're displaying a combobox with non-editable values,
    ## go ahead and post the combobox.
    if {$combobox && !$editable} {
        set listbox [$widget getlistbox]
        bind $listbox <Shift-Tab> \
            [list TableList::_handle_tab_key_press $path -1 1]
        bind $listbox <Tab> [list TableList::_handle_tab_key_press $path 1 1]
        $widget post
    }
}


proc TableList::_map_command { path item col command } {
    set row [Widget::getoption $path#item#$item -row]
    set map [list %W $path %i $item %r $row %c $col %C $row,$col]
    return  [string map $map $command]
}


proc TableList::_eval_command { path item col command } {
    if {![string length $command]} { return 1 }
    set command [_map_command $path $item $col $command]
    return [uplevel #0 $command]
}


proc TableList::_option { path col option {default ""} } {
    Widget::getVariable $path data
    set widgets [list $path#column#$col $path]
    return [eval [list Widget::getOption $option $default] $widgets]
}


proc TableList::_get_col_index { path col } {
    if {[string is integer -strict $col]} {
        set index $col
    } elseif {[string equal $col "end"]} {
        set index [Widget::getoption $path -cols]
    } else {
        Widget::getVariable $path data
        set index [lsearch -exact $data(columns) $col]
        if {$index < 0} { return -code error "column \"$col\" does not exist" }
    }

    return $index
}


proc TableList::_handle_key_press { table K } {
    set path [winfo parent $table]
    Widget::getVariable $path data

    if {$data(keyColumn) < 0} { return }

    if {[info exists data(findAfterId)]} { after cancel $data(findAfterId) }

    set var [Widget::widgetVar $path data(keyFind)]
    set data(findAfterId) [after 1000 [list unset -nocomplain $var]]

    if {[string length $K] == 1} {
        append data(keyFind) $K
        set list [TableList::get $path col $data(keyColumn)]
        set row  [lsearch -glob $list $data(keyFind)*]
        if {$row < 0} {
            set data(keyFind) $K
            set row  [lsearch -glob $list $data(keyFind)*]
        } else {
            TableList::selection $path set [lindex $data(items) $row]
            $table see $row,$data(keyColumn)
        }
    }
}


proc TableList::_handle_tab_key_press { path dir {unpost 0} } {
    Widget::getVariable $path data

    set table [TableList::gettable $path]
    set item  $data(editing)

    set col  [expr {$data(editcol) + $dir}]
    set row  [Widget::getoption $path#item#$item -row]
    set cols [Widget::cget $path -cols]
    set rows [Widget::getoption $path -rows]

    if {$col < 0 || $col == $cols} {
        ## End of the line.
        while {1} {
            if {$col < 0} {
                set col [expr {$cols - 1}]
                incr row $dir
                continue
            }

            if {[expr {$col + 1}] > $cols} {
                set col 0
                incr row $dir
                continue
            }

            if {$row < 0} {
                set row [expr {$rows - 1}]
                continue
            }

            if {[expr {$row + 1}] > $rows} {
                set row 0
                continue
            }

            if {[Widget::getoption $path#column#$col -state] eq "disabled"} {
                incr col $dir
                continue
            }

            set item [lindex $data(items) $row]

            if {[Widget::getoption $path#item#$item -state] eq "disabled"} {
                incr row $dir
                continue
            }

            break
        }

    } else {
        set item $data(editing)
    }

    if {$unpost} {
        $data(valuespath) unpost
    }

    TableList::edit $path finish

    if {![info exists data(editing)]} {
        TableList::edit $path start $item $col
    }

    return -code break
}


proc TableList::_is_disabled { path item col } {
    return [expr {[Widget::getoption $path -state] eq "disabled"
        || [Widget::getoption $path#column#$col -state] eq "disabled"
        || [Widget::getoption $path#item#$item -state] eq "disabled"}]
}


proc TableList::_handle_tree_label_click { path row col } {
    Widget::getVariable $path data

    set item [lindex $data(items) $row]
    set column $path#column#$col
    set window $path.label$row,$col

    ## Clicking the label in a disabled state toggles it.
    if {[TableList::_is_disabled $path $item $col]} {
        TableList::toggle $path $item
    } else {
        TableList::edit $path start $item $col
    }
}


proc TableList::_select_row { table x y which } {
    set path [winfo parent $table]
    Widget::getVariable $path data

    set row [$table index @$x,$y row]

    TableList::edit $path finish

    if {$which == 1} {
        ## Shift click
        set anchor $data(selectionAnchor)
        TableList::selection $path range \
            [lindex $data(items) $anchor] [lindex $data(items) $row]
    } elseif {$which == 2} {
        ## Control click
        TableList::selection $path toggle [lindex $data(items) $row]
    }
}


proc TableList::_destroy { path } {
    variable ::Widget::_class

    Widget::destroy $path

    foreach widget [array names _class $path*] {
        Widget::destroy $widget 0
    }
}
Added lib/BWidget/text.tcl.






















































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
##  $Id$
##
##  Index of commands:
##     - Text::create
##     - Text::configure
##     - Text::cget

namespace eval Text {
    Widget::define Text text

    Widget::tkinclude Text text :cmd \
    	remove { -state -foreground -background }

    Widget::declare Text {
        {-state               Enum    "normal" 0 {disabled normal readonly}}
        {-textvariable        String  "" 0}
        {-background          Color   "SystemWindow" 0}
        {-foreground          Color   "SystemWindowText" 0}
        {-disabledbackground  Color   "SystemButtonFace" 0}
        {-disabledforeground  Color   "SystemDisabledText" 0}

        {-bg                  Synonym -background}
    }

    bind ReadonlyText <1>   {focus %W}
    bind ReadonlyText <Key> {Text::_handle_key_movement %W %K}
}


# ------------------------------------------------------------------------------
#  Command Text::create
# ------------------------------------------------------------------------------
proc Text::create { path args } {
    Widget::initArgs Text $args maps

    eval [list text $path] $maps(:cmd)
    Widget::initFromODB Text $path $maps(Text)

    bind $path <Destroy> [list Text::_destroy $path]
    bindtags $path [list $path ReadonlyText Text [winfo toplevel $path] all]

    Widget::getVariable $path data

    set data(varName) ""

    set state [Widget::getoption $path -state]

    if {$state eq "disabled" || $state eq "readonly"} {
        $path configure -insertwidth 0
    }

    if {$state eq "disabled"} {
        $path configure \
            -foreground [Widget::getoption $path -disabledforeground] \
            -background [Widget::getoption $path -disabledbackground]
    }

    Widget::create Text $path

    Text::_trace_variable $path

    proc ::$path { cmd args } \
    	"return \[Text::_path_command [list $path] \$cmd \$args\]"

    return $path
}


# ------------------------------------------------------------------------------
#  Command Text::configure
# ------------------------------------------------------------------------------
proc Text::configure { path args } {
    set oldstate [Widget::getoption $path -state]

    set res [Widget::configure $path $args]

    if {[Widget::anyChangedX $path -state -background -foreground]} {
        set state [Widget::getoption $path -state]

        if {$state ne "normal"} {
            $path:cmd configure -insertwidth 0
        } else {
            $path:cmd configure -insertwidth 2
        }

        if {$state eq "disabled"} {
            $path:cmd configure \
                -foreground [Widget::getoption $path -disabledforeground] \
                -background [Widget::getoption $path -disabledbackground]
        } else {
            $path:cmd configure \
                -foreground [Widget::cget $path -foreground] \
                -background [Widget::cget $path -background]
        }
    }

    if {[Widget::hasChanged $path -textvariable textvar]} {
        Text::_trace_variable $path
    }

    return $res
}


# ------------------------------------------------------------------------------
#  Command Text::cget
# ------------------------------------------------------------------------------
proc Text::cget { path option } {
    if { [string equal "-text" $option] } {
	return [$path:cmd get]
    }
    Widget::cget $path $option
}


proc Text::clear { path } {
    $path:cmd delete 1.0 end
}


proc Text::insert { path args } {
    if {[Widget::getoption $path -state] eq "normal"} {
        eval [list $path:cmd insert] $args
        Text::_trace_variable $path 1
    }
}


proc Text::delete { path args } {
    if {[Widget::getoption $path -state] eq "normal"} {
        eval [list $path:cmd delete] $args
        Text::_trace_variable $path 1
    }
}


proc Text::Insert { path args } {
    eval [list $path:cmd insert] $args
}


proc Text::Delete { path args } {
    eval [list $path:cmd delete] $args
}


# ------------------------------------------------------------------------------
#  Command Text::_path_command
# ------------------------------------------------------------------------------
proc Text::_path_command { path cmd larg } {
    if {[info commands ::Text::$cmd] ne ""} {
        return [eval [linsert $larg 0 Text::$cmd $path]]
    } else {
        return [eval [linsert $larg 0 $path:cmd $cmd]]
    }
}


proc Text::_trace_variable { path {doSet 0} } {
    Widget::getVariable $path data

    set varName [Widget::getoption $path -textvariable]

    if {$data(varName) eq "" && $varName eq ""} { return }

    set ops [list unset write]
    set cmd [list Text::_handle_variable_trace $path]

    uplevel #0 [list trace remove variable $data(varName) $ops $cmd]

    set data(varName) $varName

    if {$varName ne ""} {
        upvar #0 $varName var

        if {$doSet} {
            set var [$path:cmd get 1.0 end-1c]
        } else {
            if {![info exists var]} { set var "" }

            $path:cmd delete 1.0 end
            $path:cmd insert end $var
        }

        uplevel #0 [list trace add variable $varName $ops $cmd]
    }
}


proc Text::_handle_variable_trace { path name1 name2 op } {
    if {$name2 ne ""} {
        upvar #0 ${name1}($name2) var
    } else {
        upvar #0 $name1 var
    }

    if {$op eq "write"} {
        $path:cmd delete 1.0 end
        $path:cmd insert end $var
    } else {
        set var [$path:cmd get 1.0 end-1c]
    }
}


proc Text::_handle_key_movement { path key } {
    if {[Widget::getoption $path -state] eq "readonly"} {
        switch -- $key {
            "Up"    { set cmd [list yview scroll -1 unit] }
            "Down"  { set cmd [list yview scroll  1 unit] }
            "Left"  { set cmd [list xview scroll -1 unit] }
            "Right" { set cmd [list xview scroll  1 unit] }
            "Prior" { set cmd [list yview scroll -1 page] }
            "Next"  { set cmd [list yview scroll  1 page] }
            "Home"  { set cmd [list yview moveto 0.0] }
            "End"   { set cmd [list yview moveto 1.0] }
        }
        if {[info exists cmd]} {
            eval [list $path:cmd] $cmd
            return -code break
        }
    }
}


proc Text::_destroy { path } {
    Widget::getVariable $path data

    set ops [list unset write]
    set cmd [list Text::_handle_variable_trace $path]

    uplevel #0 [list trace remove variable $data(varName) $ops $cmd]

    Widget::destroy $path
}
Added lib/BWidget/titleframe.tcl.




















































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# ------------------------------------------------------------------------------
#  titleframe.tcl
#  This file is part of Unifix BWidget Toolkit
# ------------------------------------------------------------------------------
#  Index of commands:
#     - TitleFrame::create
#     - TitleFrame::configure
#     - TitleFrame::cget
#     - TitleFrame::getframe
#     - TitleFrame::_place
# ------------------------------------------------------------------------------

namespace eval TitleFrame {
    Widget::define TitleFrame titleframe

    Widget::declare TitleFrame {
        {-relief      TkResource groove 0 frame}
        {-borderwidth TkResource 2      0 frame}
        {-font        String     "TkTextFont"     0}
        {-background  Color      "SystemButtonFace"     0}
        {-foreground  Color      "SystemButtonText"     0}
        {-state       Enum       "normal"     0 {active disabled normal}}
        {-text        String     ""     0}
        {-ipad        Int        4      0 "%d >=0"}
        {-side        Enum       left   0 {left center right}}
        {-baseline    Enum       center 0 {top center bottom}}
        {-fg          Synonym    -foreground}
        {-bg          Synonym    -background}
        {-bd          Synonym    -borderwidth}
    }

    Widget::addmap TitleFrame "" :cmd {-background {}}
    Widget::addmap TitleFrame "" .l   {
    	-background {} -foreground {} -text {} -font {}
    }
    Widget::addmap TitleFrame "" .l   {-state {}}
    Widget::addmap TitleFrame "" .p   {-background {}}
    Widget::addmap TitleFrame "" .b   {
    	-background {} -relief {} -borderwidth {}
    }
    Widget::addmap TitleFrame "" .b.p {-background {}}
    Widget::addmap TitleFrame "" .f   {-background {}}
}


# ------------------------------------------------------------------------------
#  Command TitleFrame::create
# ------------------------------------------------------------------------------
proc TitleFrame::create { path args } {
    Widget::initArgs TitleFrame $args maps

    set frame  [eval [list frame $path] $maps(:cmd) \
	    -class TitleFrame -relief flat -bd 0 -highlightthickness 0]

    Widget::initFromODB TitleFrame $path $maps(TitleFrame)

    set padtop [eval [list frame $path.p] $maps(:cmd) \
	    -relief flat -borderwidth 0]
    set border [eval [list frame $path.b] $maps(.b) -highlightthickness 0]
    set label  [eval [list label $path.l] $maps(.l) \
            -highlightthickness 0 -relief flat -bd 0 -padx 2 -pady 0]
    set padbot [eval [list frame $border.p] $maps(.p) \
	    -relief flat -bd 0 -highlightthickness 0]
    set frame  [eval [list frame $path.f] $maps(.f) \
	    -relief flat -bd 0 -highlightthickness 0]
    set height [winfo reqheight $label]

    switch [Widget::getoption $path -side] {
        left   { set relx 0.0; set x 5;  set anchor nw }
        center { set relx 0.5; set x 0;  set anchor n  }
        right  { set relx 1.0; set x -5; set anchor ne }
    }

    set bd [Widget::cget $path -borderwidth]
    switch [Widget::getoption $path -baseline] {
        top    {
	    set y    0
	    set htop $height
	    set hbot 1
	}
        center {
	    set y    0
	    set htop [expr {$height/2}]
	    set hbot [expr {$height/2+$height%2+1}]
	}
        bottom {
	    set y    [expr {$bd+1}]
	    set htop 1
	    set hbot $height
	}
    }
    $padtop configure -height $htop
    $padbot configure -height $hbot

    set pad [Widget::getoption $path -ipad]
    pack $padbot -side top -fill x
    pack $frame  -in $border -fill both -expand yes -padx $pad -pady $pad

    pack $padtop -side top -fill x
    pack $border -fill both -expand yes

    place $label -relx $relx -x $x -anchor $anchor -y $y

    bind $label <Configure> [list TitleFrame::_place $path]

    return [Widget::create TitleFrame $path]
}


# ------------------------------------------------------------------------------
#  Command TitleFrame::configure
# ------------------------------------------------------------------------------
proc TitleFrame::configure { path args } {
    set res [Widget::configure $path $args]

    if { [Widget::hasChanged $path -ipad pad] } {
        pack configure $path.f -padx $pad -pady $pad
    }
    if { [Widget::hasChanged $path -borderwidth val] |
         [Widget::hasChanged $path -font        val] |
         [Widget::hasChanged $path -side        val] |
         [Widget::hasChanged $path -baseline    val] } {
        _place $path
    }

    return $res
}


# ------------------------------------------------------------------------------
#  Command TitleFrame::cget
# ------------------------------------------------------------------------------
proc TitleFrame::cget { path option } {
    return [Widget::cget $path $option]
}


# ------------------------------------------------------------------------------
#  Command TitleFrame::getframe
# ------------------------------------------------------------------------------
proc TitleFrame::getframe { path } {
    return $path.f
}


# ------------------------------------------------------------------------------
#  Command TitleFrame::_place
# ------------------------------------------------------------------------------
proc TitleFrame::_place { path } {
    set height [winfo height $path.l]
    switch [Widget::getoption $path -side] {
        left    { set relx 0.0; set x 10;  set anchor nw }
        center  { set relx 0.5; set x 0;   set anchor n  }
        right   { set relx 1.0; set x -10; set anchor ne }
    }
    set bd [Widget::cget $path -borderwidth]
    switch [Widget::getoption $path -baseline] {
        top    { set htop $height; set hbot 1; set y 0 }
        center {
            set htop [expr {$height/2}]
            set hbot [expr {$height/2+$height%2+1}]
            set y 0
        }
        bottom { set htop 1; set hbot $height; set y [expr {$bd+1}] }
    }
    $path.p   configure -height $htop
    $path.b.p configure -height $hbot

    place $path.l -relx $relx -x $x -anchor $anchor -y $y
}
Added lib/BWidget/todo.txt.
















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
Need to get Dialog icons for BlueSphere into the image library.
    User dialogs don't work.

Develop a TTKNoteBook that uses the themed notebook but adds the cool
features everyone likes in the BWidget NoteBook.

Multiple-selection drag-and-drop should work for listbox and tree.

Make all widgets create before Widget::init so that we get no scratch widgets.

Calendar
    Add browse and extended select modes to Calendar.

DateEntry
    Add a DateEntry widget that uses the Calendar popup.

DynamicHelp
    Table balloons might need an option to destroy after every cell change.

Entry
    Non-editable entry should still be able to select and copy text.

ListBox
    Add -deltay option to ListBox items.  Need to change the behavior of
    -yscrollincrement to be 1 if any item in the listbox has an alternate
    -deltay.

    Make the ListBox widget use an index for node names.  It will cut
    down on memory consumption and make it so that nodes can have any
    special characters.

    Add a -background option for items.  Need to draw a box underneath each
    item that has a background different from the listbox background.

MessageDlg
    Add a -name option that names dialogs together and lets users
    say they don't want to see them again, etc...
        Use a checkbox to remember the selection.  This will save us
        from having to create a new dialog for every new button.

Properties
    Finish the -window option.  Putting a cell into edit mode needs
    to change the window, and finishing the edit needs to change the
    window back.

SplitList
    Need an option that tells us whether the user can reorder items within
    the same list.

    Need options to specify images for the buttons.

    Need an option to use TableList instead of ListBox.

TableList
    Add a right-click on table columns to allow the user to select visible
    columns and even click "More..." to customize the order of columns.

    Figure out the best way to draw tree items with padding.

    We may need to redraw rows after a "$table set" command that gets
    passed to Tktable.

    Finish the delete command.

    Finish the get command.  Needs to handle -parent option and 'column'
    should handle -unformatted correctly.
        The get command needs to return unformatted by default.

        Add a -visible option to only get visible items.

    Add -stretch to all columns.  Tktable only stretches last.

    Add -resizable to table and columns.

    Add arrow key bindings when editing.

    Finish column command: delete, insert, reorder.
        Reorder columns needs to reorder the data in the array.

        Move table tags when we move a column.

        Maybe we should rename tags based on column -name.

    Add -hide option to columns.

    Add -maxwidth -and -minwidth to columns.

    Add some way to filter the values in the table so that a filter can
    be applied to limit the results in the table.

    Add options to items:
        -background -font -foreground -selectable -selectbg -selectfg

Tree
    Make the Tree widget use an index for node names.  It will cut
    down on memory consumption and make it so that nodes can have any
    special characters.

    Finish the search subcommand.  Move nodes into a nodes array and
    leave data in the data array.

    Cleanup "selection range."  It looks pretty crappy.

    Rewrite _redraw_selection to use item indexes instead of tags.
Added lib/BWidget/tree.tcl.
































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
# ----------------------------------------------------------------------------
#  tree.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: tree.tcl,v 1.51 2004/04/26 18:42:03 hobbs Exp $
# ----------------------------------------------------------------------------
#  Index of commands:
#
#   Public Commands:
#     - Tree::create
#     - Tree::configure
#     - Tree::cget
#     - Tree::insert
#     - Tree::itemconfigure
#     - Tree::itemcget
#     - Tree::bindText
#     - Tree::bindImage
#     - Tree::delete
#     - Tree::move
#     - Tree::reorder
#     - Tree::selection
#     - Tree::exists
#     - Tree::parent
#     - Tree::index
#     - Tree::nodes
#     - Tree::see
#     - Tree::opentree
#     - Tree::closetree
#     - Tree::edit
#     - Tree::xview
#     - Tree::yview
#
#   Private Commands:
#     - Tree::_update_edit_size
#     - Tree::_destroy
#     - Tree::_see
#     - Tree::_recexpand
#     - Tree::_subdelete
#     - Tree::_update_scrollregion
#     - Tree::_cross_event
#     - Tree::_draw_node
#     - Tree::_draw_subnodes
#     - Tree::_update_nodes
#     - Tree::_draw_tree
#     - Tree::_redraw_tree
#     - Tree::_redraw_selection
#     - Tree::_redraw_idle
#     - Tree::_drag_cmd
#     - Tree::_drop_cmd
#     - Tree::_over_cmd
#     - Tree::_auto_scroll
#     - Tree::_scroll
# ----------------------------------------------------------------------------

namespace eval Tree {
    Widget::define Tree tree DragSite DropSite DynamicHelp

    namespace eval Node {
        Widget::declare Tree::Node {
            {-text       String     ""      0}
            {-font       String     ""      0}
            {-image      String     ""      0}
            {-window     String     ""      0}
            {-fill       Color      "SystemButtonText"   0}
            {-data       String     ""      0}
            {-open       Boolean    0       0}
	    {-selectable Boolean    1       0}
            {-drawcross  Enum       auto    0 {auto allways never}}
	    {-padx       Int        -1      0 "%d >= -1"}
	    {-deltax     Int        -1      0 "%d >= -1"}
	    {-anchor     String     "w"     0 ""}
        }
    }

    DynamicHelp::include Tree::Node balloon

    Widget::tkinclude Tree canvas .c \
        remove {
            -insertwidth -insertbackground -insertborderwidth -insertofftime
            -insertontime -selectborderwidth -closeenough -confine -scrollregion
            -xscrollincrement -yscrollincrement -width -height
        } initialize {
            -background #FFFFFF -relief sunken -borderwidth 2 
	    -takefocus 1 -highlightthickness 1 -width 200
        }

    DragSite::include Tree "TREE_NODE" 1
    DropSite::include Tree {
        TREE_NODE {copy {} move {}}
    }

    Widget::declare Tree {
        {-deltax            Int        10       0 "%d >= 0"}
        {-deltay            Int        15       0 "%d >= 0"}
        {-padx              Int        20       0 "%d >= 0"}
        {-font              String     "TkTextFont" 0}
        {-background        Color      "SystemWindow"  0}
        {-selectbackground  Color      "SystemHighlight"  0}
        {-selectforeground  Color      "SystemHighlightText" 0}
	{-selectcommand     String     ""       0}
        {-selectmode        Enum       "single" 0 {extended none single}}
        {-width             TkResource ""       0 listbox}
        {-height            TkResource ""       0 listbox}
        {-selectfill        Boolean    0        0}
        {-showlines         Boolean    1        0}
        {-linesfill         Color      "SystemButtonText"  0}
        {-linestipple       TkResource ""       0 {label -bitmap}}
	{-crossfill         Color      "SystemButtonText"  0}
        {-redraw            Boolean    1        0}
        {-opencmd           String     ""       0}
        {-closecmd          String     ""       0}
        {-dropovermode      Flag       "wpn"    0 "wpn"}
        {-dropcmd           String     "Tree::_drag_and_drop" 0}

        {-crossopenimage    String     ""       0}
        {-crosscloseimage   String     ""       0}
        {-crossopenbitmap   String     ""       0}
        {-crossclosebitmap  String     ""       0}

        {-bg                Synonym    -background}
    }

    Widget::addmap Tree "" .c { -deltay -yscrollincrement }

    bind Tree <FocusIn>   [list after idle {BWidget::refocus %W %W.c}]
    bind Tree <Destroy>   [list Tree::_destroy %W]
    bind Tree <Configure> [list Tree::_update_scrollregion %W]

    bind TreeSentinalStart <Button-1> {
	if {$::Tree::sentinal(%W)} {
	    set ::Tree::sentinal(%W) 0
	    break
	}
    }

    bind TreeSentinalEnd <Button-1> {
	set ::Tree::sentinal(%W) 0
    }

    bind TreeFocus <Button-1> [list focus %W]

    BWidget::bindMouseWheel TreeCanvas

    variable _edit
    set _edit(editing) 0
}


# ----------------------------------------------------------------------------
#  Command Tree::create
# ----------------------------------------------------------------------------
proc Tree::create { path args } {
    Widget::initArgs Tree $args maps

    eval [list frame $path -class Tree] $maps(:cmd)

    # For 8.4+ we don't want to inherit the padding
    if {[info tclversion] > 8.3} { $path configure -padx 0 -pady 0 }

    Widget::initFromODB Tree $path $maps(Tree)

    set ::Tree::sentinal($path.c) 0

    Widget::getVariable $path data

    set data(root)         [list [list]]
    set data(selnodes)     [list]
    set data(upd,level)    0
    set data(upd,nodes)    [list]
    set data(upd,afterid)  ""
    set data(dnd,scroll)   ""
    set data(dnd,afterid)  ""
    set data(dnd,selnodes) [list]
    set data(dnd,node)     ""

    ## The items array contains a list of canvas items
    ## for each node in the tree.  The list contains:
    ##
    ## lineItem textItem crossItem windowItem boxItem
    ##
    Widget::getVariable $path items

    eval [list canvas $path.c] $maps(.c) -xscrollincrement 8
    bindtags $path.c [list TreeSentinalStart TreeFocus $path.c Canvas \
	    TreeCanvas [winfo toplevel $path] all TreeSentinalEnd]
    pack $path.c -expand yes -fill both
    $path.c bind cross <ButtonPress-1> [list Tree::_cross_event $path]

    # Added by ericm@scriptics.com
    # These allow keyboard traversal of the tree
    bind $path.c <KeyPress-Up>    [list Tree::_keynav up $path]
    bind $path.c <KeyPress-Down>  [list Tree::_keynav down $path]
    bind $path.c <KeyPress-Right> [list Tree::_keynav right $path]
    bind $path.c <KeyPress-Left>  [list Tree::_keynav left $path]
    bind $path.c <KeyPress-space> [list +Tree::_keynav space $path]

    # These allow keyboard control of the scrolling
    bind $path.c <Control-KeyPress-Up>    [list $path.c yview scroll -1 units]
    bind $path.c <Control-KeyPress-Down>  [list $path.c yview scroll  1 units]
    bind $path.c <Control-KeyPress-Left>  [list $path.c xview scroll -1 units]
    bind $path.c <Control-KeyPress-Right> [list $path.c xview scroll  1 units]
    # ericm@scriptics.com

    DragSite::setdrag $path $path.c Tree::_init_drag_cmd \
	    [Widget::cget $path -dragendcmd] 1
    DropSite::setdrop $path $path.c Tree::_over_cmd Tree::_drop_cmd 1

    Widget::create Tree $path

    set w [Widget::cget $path -width]
    set h [Widget::cget $path -height]
    set dy [Widget::cget $path -deltay]
    $path.c configure -width [expr {$w*8}] -height [expr {$h*$dy}]

    set mode [Widget::getoption $path -selectmode]
    if {$mode ne "none"} {
        Tree::bindText  $path <Double-1> [list $path toggle]
        Tree::bindImage $path <Double-1> [list $path toggle]
        Tree::bindText  $path <Button-1> [list $path selection set]
        Tree::bindImage $path <Button-1> [list $path selection set]
    }

    if {$mode eq "extended"} {
        Tree::bindText  $path <Control-Button-1> [list $path selection toggle]
        Tree::bindImage $path <Control-Button-1> [list $path selection toggle]
    }

    # Add sentinal bindings for double-clicking on items, to handle the 
    # gnarly Tk bug wherein:
    # ButtonClick
    # ButtonClick
    # On a canvas item translates into button click on the item, button click
    # on the canvas, double-button on the item, single button click on the
    # canvas (which can happen if the double-button on the item causes some
    # other event to be handled in between when the button clicks are examined
    # for the canvas)
    $path.c bind TreeItemSentinal <Double-Button-1> \
	[list set ::Tree::sentinal($path.c) 1]
    # ericm


    set image  [Widget::getoption $path -crossopenimage]
    set bitmap [Widget::getoption $path -crossopenbitmap]
    if {![string length $image] && ![string length $bitmap]} {
        Widget::setoption $path -crossopenimage [BWidget::Icon tree-minus]
    }

    set image  [Widget::getoption $path -crosscloseimage]
    set bitmap [Widget::getoption $path -crossclosebitmap]
    if {![string length $image] && ![string length $bitmap]} {
        Widget::setoption $path -crosscloseimage [BWidget::Icon tree-plus]
    }

    return $path
}


# ----------------------------------------------------------------------------
#  Command Tree::configure
# ----------------------------------------------------------------------------
proc Tree::configure { path args } {
    Widget::getVariable $path data

    set res [Widget::configure $path $args]

    set ch1 [expr {[Widget::hasChanged $path -deltax val]
                   || [Widget::hasChanged $path -deltay dy]
                   || [Widget::hasChanged $path -padx val]
                   || [Widget::hasChanged $path -showlines val]
                   || [Widget::hasChanged $path -font font]}]

    set ch2 [expr {[Widget::hasChanged $path -selectbackground val] |
                   [Widget::hasChanged $path -selectforeground val]}]

    if {[Widget::hasChanged $path -linesfill fill]
        || [Widget::hasChanged $path -linestipple stipple] } {
        $path.c itemconfigure line  -fill $fill -stipple $stipple
    }

    if {[Widget::hasChanged $path -crossfill fill]} {
        $path.c itemconfigure cross -foreground $fill
    }

    if {[Widget::hasChanged $path -selectfill fill]} {
	# Make sure that the full-width boxes have either all or none
	# of the standard node bindings
	if {$fill} {
	    foreach event [$path.c bind "node"] {
		$path.c bind "box" $event [$path.c bind "node" $event]
	    }
	} else {
	    foreach event [$path.c bind "node"] {
		$path.c bind "box" $event {}
	    }
	}
    }

    if { $ch1 } {
        _redraw_idle $path 3
    } elseif { $ch2 } {
        _redraw_idle $path 1
    }

    if { [Widget::hasChanged $path -height h] } {
        $path.c configure -height [expr {$h*$dy}]
    }
    if { [Widget::hasChanged $path -width w] } {
        $path.c configure -width [expr {$w*8}]
    }

    if { [Widget::hasChanged $path -redraw bool] && $bool } {
        set upd $data(upd,level)
        set data(upd,level) 0
        _redraw_idle $path $upd
    }

    set force [Widget::hasChanged $path -dragendcmd dragend]
    DragSite::setdrag $path $path.c Tree::_init_drag_cmd $dragend $force
    DropSite::setdrop $path $path.c Tree::_over_cmd Tree::_drop_cmd

    return $res
}


# ----------------------------------------------------------------------------
#  Command Tree::cget
# ----------------------------------------------------------------------------
proc Tree::cget { path option } {
    return [Widget::cget $path $option]
}


# ----------------------------------------------------------------------------
#  Command Tree::insert
# ----------------------------------------------------------------------------
proc Tree::insert { path index parent node args } {
    Widget::getVariable $path data

    set node [_node_name $path $node]
    set node [Widget::nextIndex $path $node]

    if {[info exists data($node)]} {
        return -code error "node \"$node\" already exists"
    }

    if {![info exists data($parent)]} {
        return -code error "node \"$parent\" does not exist"
    }

    Widget::init Tree::Node $path.$node $args

    if {[string equal $index "end"]} {
        lappend data($parent) $node
    } else {
        set data($parent) [linsert $data($parent) [incr index] $node]
    }
    set data($node) [list $parent]

    if {[string equal $parent "root"]} {
        _redraw_idle $path 3
    } elseif {[Tree::visible $path $parent]} {
        # parent is visible...
        if {[Widget::getoption $path.$parent -open]} {
            # ...and opened -> redraw whole
            _redraw_idle $path 3
        } else {
            # ...and closed -> redraw cross
            lappend data(upd,nodes) $parent 8
            _redraw_idle $path 2
        }
    }

    return $node
}


# ----------------------------------------------------------------------------
#  Command Tree::itemconfigure
# ----------------------------------------------------------------------------
proc Tree::itemconfigure { path node args } {
    Widget::getVariable $path data

    set node [_node_name $path $node]
    if {[string equal $node "root"] || ![info exists data($node)]} {
        return -code error "node \"$node\" does not exist"
    }

    set result [Widget::configure $path.$node $args]

    _set_help $path $node

    if { [visible $path $node] } {
        set lopt   {}
        set flag   0
        foreach opt {-window -image -drawcross -font -text -fill} {
            set flag [expr {$flag << 1}]
            if {[Widget::hasChanged $path.$node $opt val]} {
                set flag [expr {$flag | 1}]
            }
        }

        if {[Widget::hasChanged $path.$node -open val]} {
            if {[llength $data($node)] > 1} {
                # node have subnodes - full redraw
                _redraw_idle $path 3
            } else {
                # force a redraw of the plus/minus sign
                set flag [expr {$flag | 8}]
            }
        }

	if {$data(upd,level) < 3 && [Widget::hasChanged $path.$node -padx x]} {
	    _redraw_idle $path 3
	}

	if { $data(upd,level) < 3 && $flag } {
            if { [set idx [lsearch -exact $data(upd,nodes) $node]] == -1 } {
                lappend data(upd,nodes) $node $flag
            } else {
                incr idx
                set flag [expr {[lindex $data(upd,nodes) $idx] | $flag}]
                set data(upd,nodes) [lreplace $data(upd,nodes) $idx $idx $flag]
            }
            _redraw_idle $path 2
        }
    }
    return $result
}


# ----------------------------------------------------------------------------
#  Command Tree::itemcget
# ----------------------------------------------------------------------------
proc Tree::itemcget { path node option } {
    Widget::getVariable $path data
    set node [_node_name $path $node]
    if {[string equal $node "root"] || ![info exists data($node)]} {
        return -code error "node \"$node\" does not exist"
    }

    return [Widget::cget $path.$node $option]
}


# ----------------------------------------------------------------------------
#  Command Tree::bindText
# ----------------------------------------------------------------------------
proc Tree::bindText { path event script } {
    if {[string length $script]} {
	append script " \[Tree::_get_node_name [list $path] current 2\]"
    }
    $path.c bind "node" $event $script
    if {[Widget::getoption $path -selectfill]} {
	$path.c bind "box" $event $script
    } else {
	$path.c bind "box" $event {}
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::bindImage
# ----------------------------------------------------------------------------
proc Tree::bindImage { path event script } {
    if {[string length $script]} {
	append script " \[Tree::_get_node_name [list $path] current 2\]"
    }
    $path.c bind "img" $event $script
    if {[Widget::getoption $path -selectfill]} {
	$path.c bind "box" $event $script
    } else {
	$path.c bind "box" $event {}
    }
}


proc Tree::bindTree { path args } {
    return [eval [list bind $path.c] $args]
}


proc Tree::clear { path } {
    eval [list Tree::delete $path] [Tree::nodes $path root]
}


# ----------------------------------------------------------------------------
#  Command Tree::delete
# ----------------------------------------------------------------------------
proc Tree::delete { path args } {
    Widget::getVariable $path data

    foreach lnodes $args {
	foreach node $lnodes {
            set node [_node_name $path $node]
	    if { ![string equal $node "root"] && [info exists data($node)] } {
		set parent [lindex $data($node) 0]
		set idx	   [lsearch -exact $data($parent) $node]
		set data($parent) [lreplace $data($parent) $idx $idx]
		_subdelete $path [list $node]
	    }
	}
    }

    _redraw_idle $path 3
}


# ----------------------------------------------------------------------------
#  Command Tree::move
# ----------------------------------------------------------------------------
proc Tree::move { path parent node index } {
    Widget::getVariable $path data

    set node [_node_name $path $node]
    if { [string equal $node "root"] || ![info exists data($node)] } {
        return -code error "node \"$node\" does not exist"
    }
    if { ![info exists data($parent)] } {
        return -code error "node \"$parent\" does not exist"
    }
    set p $parent
    while {![string equal $p "root"]} {
        if {[string equal $p $node]} {
            return -code error "node \"$parent\" is a descendant of \"$node\""
        }
        set p [Tree::parent $path $p]
    }

    set oldp        [lindex $data($node) 0]
    set idx         [lsearch -exact $data($oldp) $node]
    set data($oldp) [lreplace $data($oldp) $idx $idx]
    set data($node) [concat [list $parent] [lrange $data($node) 1 end]]

    if {[string equal $index "end"]} {
        lappend data($parent) $node
    } else {
        set data($parent) [linsert $data($parent) [incr index] $node]
    }

    if {([string equal $oldp "root"] ||
          ([visible $path $oldp] && [Widget::getoption $path.$oldp -open]))
          || ([string equal $parent "root"] ||
          ([visible $path $parent]
               && [Widget::getoption $path.$parent -open]))} {
        _redraw_idle $path 3
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::reorder
# ----------------------------------------------------------------------------
proc Tree::reorder { path node neworder } {
    Widget::getVariable $path data

    set node [_node_name $path $node]
    if { ![info exists data($node)] } {
        return -code error "node \"$node\" does not exist"
    }
    set children [lrange $data($node) 1 end]
    if { [llength $children] } {
        set children [BWidget::lreorder $children $neworder]
        set data($node) [linsert $children 0 [lindex $data($node) 0]]
        if { [visible $path $node] && [Widget::getoption $path.$node -open] } {
            _redraw_idle $path 3
        }
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::selection
# ----------------------------------------------------------------------------
proc Tree::selection { path cmd args } {
    Widget::getVariable $path data

    switch -- $cmd {
	toggle {
            foreach node $args {
                set node [_node_name $path $node]
                if {![info exists data($node)]} {
		    return -code error "$path selection toggle: 
                        Cannot toggle unknown node \"$node\"."
		}
	    }

            foreach node $args {
                set node [_node_name $path $node]
                if {[set idx [lsearch -exact $data(selnodes) $node]] != -1} {
                    set data(selnodes) [lreplace $data(selnodes) $idx $idx]
		} else {
                    lappend data(selnodes) $node
		}
            }
	}

        set {
            foreach node $args {
                set node [_node_name $path $node]
                if {![info exists data($node)]} {
		    return -code error "$path selection set: \
                        Cannot select unknown node \"$node\"."
		}
	    }
            set data(selnodes) {}
            foreach node $args {
                set node [_node_name $path $node]
		if { [Widget::getoption $path.$node -selectable] } {
		    if { [lsearch -exact $data(selnodes) $node] == -1 } {
			lappend data(selnodes) $node
		    }
		}
            }
	    _call_selectcmd $path
        }

        add {
            foreach node $args {
                set node [_node_name $path $node]
                if {![info exists data($node)]} {
		    return -code error "$path selection add: \
                        Cannot select unknown node \"$node\"."
		}
	    }

            foreach node $args {
                set node [_node_name $path $node]
		if {[Widget::getoption $path.$node -selectable]} {
		    if {[lsearch -exact $data(selnodes) $node] == -1} {
			lappend data(selnodes) $node
		    }
		}
            }
	    _call_selectcmd $path
        }

	range {
	    # Here's our algorithm:
	    #    make a list of all nodes, then take the range from node1
	    #    to node2 and select those nodes
	    #
	    # This works because of how this widget handles redraws:
	    #    The tree is always completely redrawn, and always from
	    #    top to bottom. So the list of visible nodes *is* the
	    #    list of nodes, and we can use that to decide which nodes
	    #    to select.

	    if {[llength $args] != 2} {
		return -code error \
                    [BWidget::wrongNumArgsString \
                        "$path selection range node1 node2"]
	    }

	    foreach {node1 node2} $args break

            set node1 [_node_name $path $node1]
            set node2 [_node_name $path $node2]
	    if {![info exists data($node1)]} {
		return -code error "$path selection range: \
                    Cannot start range at unknown node \"$node1\"."
	    }
	    if {![info exists data($node2)]} {
		return -code error "$path selection range: \
                    Cannot end range at unknown node \"$node2\"."
	    }

	    set nodes {}
	    foreach nodeItem [$path.c find withtag node] {
		set node [Tree::_get_node_name $path $nodeItem 2]
		if { [Widget::getoption $path.$node -selectable] } {
		    lappend nodes $node
		}
	    }

	    # surles: Set the root string to the first element on the list.
	    if {$node1 == "root"} {
		set node1 [lindex $nodes 0]
	    }

	    if {$node2 == "root"} {
		set node2 [lindex $nodes 0]
	    }

	    # Find the first visible ancestor of node1, starting with node1
	    while {[set index1 [lsearch -exact $nodes $node1]] == -1} {
		set node1 [lindex $data($node1) 0]
	    }

	    # Find the first visible ancestor of node2, starting with node2
	    while {[set index2 [lsearch -exact $nodes $node2]] == -1} {
		set node2 [lindex $data($node2) 0]
	    }

	    # If the nodes were given in backwards order, flip the
	    # indices now
	    if {$index2 < $index1} {
		incr index1 $index2
		set index2 [expr {$index1 - $index2}]
		set index1 [expr {$index1 - $index2}]
	    }

	    set data(selnodes) [lrange $nodes $index1 $index2]
	    _call_selectcmd $path
	}

        remove {
            foreach node $args {
                set node [_node_name $path $node]
                if { [set idx [lsearch -exact $data(selnodes) $node]] != -1 } {
                    set data(selnodes) [lreplace $data(selnodes) $idx $idx]
                }
            }
	    _call_selectcmd $path
        }

        clear {
	    if {[llength $args] != 0} {
		return -code error \
                    [BWidget::wrongNumArgsString "$path selection clear"]
	    }
            set data(selnodes) {}
	    _call_selectcmd $path
        }

        get {
	    if {[llength $args] != 0} {
		return -code error \
                    [BWidget::wrongNumArgsString "$path selection get"]
	    }
            return $data(selnodes)
        }

        includes {
	    if {[llength $args] != 1} {
		return -code error \
                    [BWidget::wrongNumArgsString \
                        "$path selection includes node"]
	    }
	    set node [lindex $args 0]
            set node [_node_name $path $node]
            return [expr {[lsearch -exact $data(selnodes) $node] != -1}]
        }

        default {
            return
        }
    }

    event generate $path <<TreeSelect>>

    _redraw_idle $path 1
}


proc Tree::getcanvas { path } {
    return $path.c
}


# ----------------------------------------------------------------------------
#  Command Tree::exists
# ----------------------------------------------------------------------------
proc Tree::exists { path node } {
    Widget::getVariable $path data
    set node [_node_name $path $node]
    return [info exists data($node)]
}


# ----------------------------------------------------------------------------
#  Command Tree::visible
# ----------------------------------------------------------------------------
proc Tree::visible { path node } {
    Widget::getVariable $path items
    set node [_node_name $path $node]
    return [info exists items($node)]
}


# ----------------------------------------------------------------------------
#  Command Tree::parent
# ----------------------------------------------------------------------------
proc Tree::parent { path node } {
    Widget::getVariable $path data

    set node [_node_name $path $node]
    if {![info exists data($node)]} {
        return -code error "node \"$node\" does not exist"
    }
    return [lindex $data($node) 0]
}


# ----------------------------------------------------------------------------
#  Command Tree::index
# ----------------------------------------------------------------------------
proc Tree::index { path node } {
    Widget::getVariable $path data

    set node [_node_name $path $node]
    if {[string equal $node "root"] || ![info exists data($node)]} {
        return -code error "node \"$node\" does not exist"
    }
    set parent [lindex $data($node) 0]
    return [expr {[lsearch -exact $data($parent) $node] - 1}]
}


# ----------------------------------------------------------------------------
#  Tree::find
#     Returns the node given a position.
#  findInfo     @x,y ?confine?
#               lineNumber
# ----------------------------------------------------------------------------
proc Tree::find { path findInfo {confine ""} } {
    if {[regexp -- {^@([0-9]+),([0-9]+)$} $findInfo match x y]} {
        set x [$path.c canvasx $x]
        set y [$path.c canvasy $y]
    } elseif {[regexp -- {^[0-9]+$} $findInfo lineNumber]} {
        set dy [Widget::cget $path -deltay]
        set y  [expr {$dy*($lineNumber+0.5)}]
        set confine ""
    } else {
        return -code error "invalid find spec \"$findInfo\""
    }

    set found  0
    set region [$path.c bbox all]
    if {[llength $region]} {
        set xi [lindex $region 0]
        set xs [lindex $region 2]
        foreach id [$path.c find overlapping $xi $y $xs $y] {
            set ltags [$path.c gettags $id]
            set item  [lindex $ltags 1]
            if { [string equal $item "node"] ||
                 [string equal $item "img"]  ||
                 [string equal $item "win"] } {
                # item is the label or image/window of the node
                set node  [Tree::_get_node_name $path $id 2]
                set found 1
                break
            }
        }
    }

    if {$found} {
        if {[string equal $confine "confine"]} {
            # test if x stand inside node bbox
	    set padx [_get_node_padx $path $node]
            set xi [expr {[lindex [$path.c coords n:$node] 0] - $padx}]
            set xs [lindex [$path.c bbox n:$node] 2]
            if {$x >= $xi && $x <= $xs} {
                return $node
            }
        } else {
            return $node
        }
    }

    return
}


# ----------------------------------------------------------------------------
#  Command Tree::line
#     Returns the line where is drawn a node.
# ----------------------------------------------------------------------------
proc Tree::line { path node } {
    Widget::getVariable $path items
    set node [_node_name $path $node]
    set line [lindex $items($node) 0]
    if {[string length $line]} { return $line }
    return -1
}


# ----------------------------------------------------------------------------
#  Command Tree::nodes
# ----------------------------------------------------------------------------
proc Tree::nodes { path node {first ""} {last ""} } {
    Widget::getVariable $path data

    set node [_node_name $path $node]
    if {![info exists data($node)]} {
        return -code error "node \"$node\" does not exist"
    }

    if {![string length $first]} {
        return [lrange $data($node) 1 end]
    }

    if {![string length $last]} {
        return [lindex [lrange $data($node) 1 end] $first]
    } else {
        return [lrange [lrange $data($node) 1 end] $first $last]
    }
}


# Tree::visiblenodes --
#
#	Retrieve a list of all the nodes in a tree.
#
# Arguments:
#	path	Tree to retrieve nodes for.
#       node    Starting node.
#
# Results:
#	nodes	list of nodes in the tree.

proc Tree::visiblenodes { path {node root} } {
    Widget::getVariable $path data

    set nodes [list]
    foreach node [lrange $data($node) 1 end] {
        lappend nodes $node
        if {[Widget::getoption $path.$node -open]} {
            eval lappend nodes [Tree::visiblenodes $path $node]
        }
    }

    return $nodes
}

# ----------------------------------------------------------------------------
#  Command Tree::see
# ----------------------------------------------------------------------------
proc Tree::see { path node } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    set node [_node_name $path $node]
    if {[Widget::getoption $path -redraw] && $data(upd,afterid) != ""} {
        after cancel $data(upd,afterid)
        _redraw_tree $path
    }

    if {[info exists items($node)]} {
        Tree::_see $path [lindex $items($node) 1]
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::opentree
# ----------------------------------------------------------------------------
# JDC: added option recursive
proc Tree::opentree { path node {recursive 1} } {
    Widget::getVariable $path data

    set node [_node_name $path $node]
    if {[string equal $node "root"] || ![info exists data($node)]} {
        return -code error "node \"$node\" does not exist"
    }

    _recexpand $path $node 1 $recursive [Widget::getoption $path -opencmd]
    _redraw_idle $path 3
}


# ----------------------------------------------------------------------------
#  Command Tree::closetree
# ----------------------------------------------------------------------------
proc Tree::closetree { path node {recursive 1} } {
    Widget::getVariable $path data

    set node [_node_name $path $node]
    if {[string equal $node "root"] || ![info exists data($node)]} {
        return -code error "node \"$node\" does not exist"
    }

    _recexpand $path $node 0 $recursive [Widget::getoption $path -closecmd]
    _redraw_idle $path 3
}


proc Tree::toggle { path node } {
    if {[Tree::itemcget $path $node -open]} {
        $path closetree $node 0
    } else {
        $path opentree $node 0
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::edit
# ----------------------------------------------------------------------------
proc Tree::edit { path node text {verifycmd ""} {clickres 0} {select 1}} {
    variable _edit
    Widget::getVariable $path data
    Widget::getVariable $path items

    set node [_node_name $path $node]
    if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } {
        after cancel $data(upd,afterid)
        _redraw_tree $path
    }

    if {[info exists items($node)]} {
        set _edit(editing) 1

        set idn [lindex $items($node) 1]

        Tree::_see $path $idn

        set oldfg  [$path.c itemcget $idn -fill]
        set sbg    [Widget::cget $path -selectbackground]
        set coords [$path.c coords $idn]
        set x      [lindex $coords 0]
        set y      [lindex $coords 1]
        set ht     [$path.c cget -highlightthickness]
        set bd     [expr {[$path.c cget -borderwidth] + $ht}]
        set w      [expr {[winfo width $path] - 2 * $bd}]
        set wmax   [expr {[$path.c canvasx $w] - $x}]

        set _edit(wait) 0
        set _edit(path) $path
        set _edit(node) $node
        set _edit(text) $text

        $path.c itemconfigure $idn    -fill [Widget::cget $path -background]
        $path.c itemconfigure s:$node -fill {} -outline {}

        set frame  [frame $path.edit \
                    -relief flat -borderwidth 0 -highlightthickness 0 \
                    -background [Widget::cget $path -background]]
        set ent    [entry $frame.edit \
                    -width              0     \
                    -relief             solid \
                    -borderwidth        1     \
                    -highlightthickness 0     \
                    -foreground         [Widget::getoption $path.$node -fill] \
                    -background         [Widget::cget $path -background] \
                    -selectforeground   [Widget::cget $path -selectforeground] \
                    -selectbackground   $sbg  \
                    -font               [_get_option $path $node -font] \
                    -textvariable       Tree::_edit(text)]
        pack $ent -ipadx 8 -anchor w

        set _edit(frame) $frame
        set _edit(entry) $ent

        set idw [$path.c create window $x $y -window $frame -anchor w]
        trace variable Tree::_edit(text) w \
	    [list Tree::_update_edit_size $path $ent $idw $wmax]
        tkwait visibility $ent
        grab  $frame
        BWidget::focus set $ent

        _update_edit_size $path $ent $idw $wmax
        update

        if {$select} {
            $ent selection range 0 end
            $ent icursor end
            $ent xview end
        }

        bindtags $ent [list $ent Entry]
        bind $ent <Escape> {set Tree::_edit(wait) 0}
        bind $ent <Return> {set Tree::_edit(wait) 1}
        if {$clickres == 0 || $clickres == 1} {
            bind $frame <Button>  [list set Tree::_edit(wait) $clickres]
        }

        set ok 0
        while {!$ok} {
            focus -force $ent
            tkwait variable Tree::_edit(wait)
            if {!$_edit(wait) || ![llength $verifycmd] ||
                 [uplevel \#0 $verifycmd [list $_edit(text)]]} {
                set ok 1
            }
        }

        trace vdelete Tree::_edit(text) w \
	    [list Tree::_update_edit_size $path $ent $idw $wmax]
        grab release $frame
        BWidget::focus release $ent

        set _edit(editing) 0

        destroy $frame
        $path.c delete $idw
        $path.c itemconfigure $idn    -fill $oldfg
        $path.c itemconfigure s:$node -fill $sbg -outline $sbg

        if {$_edit(wait)} {
            return $_edit(text)
        }
    }
}


proc Tree::editing { path } {
    variable _edit
    if {$_edit(editing) && $_edit(path) eq $path} { return 1 }
    return 0
}


# ----------------------------------------------------------------------------
#  Command Tree::xview
# ----------------------------------------------------------------------------
proc Tree::xview { path args } {
    return [eval [linsert $args 0 $path.c xview]]
}


# ----------------------------------------------------------------------------
#  Command Tree::yview
# ----------------------------------------------------------------------------
proc Tree::yview { path args } {
    return [eval [linsert $args 0 $path.c yview]]
}


proc Tree::search { path args } {
    Widget::getVariable $path data

    array set _args {
        -pattern  *
    }
    array set _args $args

    return [array names data $_args(-pattern)]
}


proc Tree::level { path node } {
    Widget::getVariable $path data

    if {[string equal $node "root"]} { return 0 }

    if {![info exists data($node)]} {
        return -code error "node \"$node\" does not exists"
    }

    set level  1
    set parent [lindex $data($node) 0]
    while {![string equal $parent "root"]} {
        incr level
        set parent [lindex $data($parent) 0]
    }

    return $level
}


proc Tree::_call_selectcmd { path } {
    Widget::getVariable $path data

    set selectcmd [Widget::getoption $path -selectcommand]
    if {[llength $selectcmd]} {
	lappend selectcmd $path
	lappend selectcmd $data(selnodes)
	uplevel \#0 $selectcmd
    }
    return
}


# ----------------------------------------------------------------------------
#  Command Tree::_update_edit_size
# ----------------------------------------------------------------------------
proc Tree::_update_edit_size { path entry idw wmax args } {
    set entw [winfo reqwidth $entry]
    if {$entw + 8 >= $wmax} {
        $path.c itemconfigure $idw -width $wmax
    } else {
        $path.c itemconfigure $idw -width 0
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::_see
# ----------------------------------------------------------------------------
proc Tree::_see { path idn } {
    set bbox [$path.c bbox $idn]
    set scrl [$path.c cget -scrollregion]

    set ymax [lindex $scrl 3]
    set dy   [$path.c cget -yscrollincrement]
    set yv   [$path yview]
    set yv0  [expr {round([lindex $yv 0]*$ymax/$dy)}]
    set yv1  [expr {round([lindex $yv 1]*$ymax/$dy)}]
    set y    [expr {int([lindex [$path.c coords $idn] 1]/$dy)}]

    if {$y < $yv0} {
        $path.c yview scroll [expr {$y-$yv0}] units
    } elseif { $y >= $yv1 } {
        $path.c yview scroll [expr {$y-$yv1+1}] units
    }

    set xmax [lindex $scrl 2]
    set dx   [$path.c cget -xscrollincrement]
    set xv   [$path xview]
    set x0   [expr {int([lindex $bbox 0]/$dx)}]
    set xv0  [expr {round([lindex $xv 0]*$xmax/$dx)}]
    set xv1  [expr {round([lindex $xv 1]*$xmax/$dx)}]

    if {$x0 >= $xv1 || $x0 < $xv0} {
	$path.c xview scroll [expr {$x0-$xv0}] units
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::_recexpand
# ----------------------------------------------------------------------------
# JDC : added option recursive
proc Tree::_recexpand { path node expand recursive cmd } {
    Widget::getVariable $path data

    if {[Widget::getoption $path.$node -open] != $expand} {
        Widget::setoption $path.$node -open $expand
        if {[llength $cmd]} {
            uplevel \#0 $cmd [list $node]
        }
    }

    if {$recursive} {
	foreach subnode [lrange $data($node) 1 end] {
	    _recexpand $path $subnode $expand $recursive $cmd
	}
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::_subdelete
# ----------------------------------------------------------------------------
proc Tree::_subdelete { path lnodes } {
    Widget::getVariable $path data

    set sel $data(selnodes)

    while {[llength $lnodes]} {
        set lsubnodes [list]
        foreach node $lnodes {
            foreach subnode [lrange $data($node) 1 end] {
                lappend lsubnodes $subnode
            }
            unset data($node)
	    set idx [lsearch -exact $sel $node]
	    if {$idx >= 0} {
		set sel [lreplace $sel $idx $idx]
	    }
            if {[set win [Widget::getoption $path.$node -window]] != ""} {
                destroy $win
            }
            Widget::destroy $path.$node 0
        }
        set lnodes $lsubnodes
    }

    set data(selnodes) $sel
}


# ----------------------------------------------------------------------------
#  Command Tree::_update_scrollregion
# ----------------------------------------------------------------------------
proc Tree::_update_scrollregion { path } {
    set bd   [$path.c cget -borderwidth]
    set ht   [$path.c cget -highlightthickness]
    set bd   [expr {2 * ($bd + $ht)}]
    set w    [expr {[winfo width  $path] - $bd}]
    set h    [expr {[winfo height $path] - $bd}]
    set xinc [$path.c cget -xscrollincrement]
    set yinc [$path.c cget -yscrollincrement]
    set bbox [$path.c bbox node]
    if {[llength $bbox]} {
        set xs [lindex $bbox 2]
        set ys [lindex $bbox 3]

        if {$w < $xs} {
            set w [expr {int($xs)}]
            if {[set r [expr {$w % $xinc}]]} {
                set w [expr {$w+$xinc-$r}]
            }
        }
        if {$h < $ys} {
            set h [expr {int($ys)}]
            if {[set r [expr {$h % $yinc}]]} {
                set h [expr {$h+$yinc-$r}]
            }
        }
    }

    $path.c configure -scrollregion [list 0 0 $w $h]

    if {[Widget::getoption $path -selectfill]} {
        _redraw_selection $path
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::_cross_event
# ----------------------------------------------------------------------------
proc Tree::_cross_event { path } {
    Widget::getVariable $path data

    set node [Tree::_get_node_name $path current 1]
    if {[Widget::getoption $path.$node -open]} {
        Tree::itemconfigure $path $node -open 0
        if {[llength [set cmd [Widget::getoption $path -closecmd]]]} {
            uplevel \#0 $cmd [list $node]
        }
    } else {
        Tree::itemconfigure $path $node -open 1
        if {[llength [set cmd [Widget::getoption $path -opencmd]]]} {
            uplevel \#0 $cmd [list $node]
        }
    }
}


proc Tree::_draw_cross { path node open x y } {
    Widget::getVariable $path items
    set idc [lindex $items($node) 2]

    if {$open} {
        set img [Widget::cget $path -crossopenimage]
        set bmp [Widget::cget $path -crossopenbitmap]
    } else {
        set img [Widget::cget $path -crosscloseimage]
        set bmp [Widget::cget $path -crossclosebitmap]
    }

    ## If we already have a cross for this node, we just adjust the image.
    if {[string length $idc]} {
        if {![string length $img]} {
            $path.c itemconfigure $idc -bitmap $bmp
        } else {
            $path.c itemconfigure $idc -image $img
        }
        return $idc
    }

    if {![Widget::getoption $path -showlines]} { set x [expr {$x + 6}] }

    ## Create a new image for the cross.  If the user has specified an
    ## image, it overrides a bitmap.
    if {![string length $img]} {
        set idc [$path.c create bitmap $x $y \
            -bitmap     $bmp \
            -background [$path.c cget -background] \
            -foreground [Widget::getoption $path -crossfill] \
            -tags       [list cross c:$node] -anchor c]
    } else {
        set idc [$path.c create image $x $y \
            -image      $img \
            -tags       [list cross c:$node] -anchor c]
    }

    return $idc
}


# ----------------------------------------------------------------------------
#  Command Tree::_draw_node
# ----------------------------------------------------------------------------
proc Tree::_draw_node { path node x0 y0 deltax deltay padx showlines } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    set x1 [expr {$x0+$deltax+5}]
    set y1 $y0
    if {$showlines} {
        set i [$path.c create line $x0 $y0 $x1 $y0 \
            -fill    [Widget::getoption $path -linesfill]   \
            -stipple [Widget::getoption $path -linestipple] \
            -tags    line]

        lappend items($node) $i
    } else {
        lappend items($node) ""
    }

    set i [$path.c create text [expr {$x1+$padx}] $y0 \
        -anchor w \
        -text   [Widget::getoption $path.$node -text] \
        -fill   [Widget::getoption $path.$node -fill] \
        -font   [_get_option $path $node -font] \
    	-tags   [Tree::_get_node_tags $path $node [list node n:$node]]]
    lappend items($node) $i

    set len [expr {[llength $data($node)] > 1}]
    set dc  [Widget::getoption $path.$node -drawcross]
    set exp [Widget::getoption $path.$node -open]

    if {$len && $exp} {
        set y1 [_draw_subnodes $path [lrange $data($node) 1 end] \
                [expr {$x0+$deltax}] $y0 $deltax $deltay $padx $showlines]
    }

    if {![string equal $dc "never"] && ($len || [string equal $dc "allways"])} {
        lappend items($node) [_draw_cross $path $node $exp $x0 $y0]
    } else {
        lappend items($node) ""
    }

    if {[set win [Widget::getoption $path.$node -window]] != ""} {
	set a [Widget::cget $path.$node -anchor]
        set i [$path.c create window $x1 $y0 -window $win -anchor $a \
		-tags [Tree::_get_node_tags $path $node [list win i:$node]]]
        lappend items($node) $i
    } elseif {[set img [Widget::getoption $path.$node -image]] != ""} {
	set a [Widget::cget $path.$node -anchor]
        set i [$path.c create image $x1 $y0 -image $img -anchor $a \
		-tags   [Tree::_get_node_tags $path $node [list img i:$node]]]
        lappend items($node) $i
    } else {
        lappend items($node) ""
    }

    set nid [lindex $items($node) 1]
    set iid [lindex $items($node) 3]
    set box [$path.c bbox $nid $iid]
    set id [$path.c create rect 0 [lindex $box 1] \
		[winfo screenwidth $path] [lindex $box 3] \
		-tags [Tree::_get_node_tags $path $node [list box b:$node]] \
		-fill {} -outline {}]
    $path.c lower $id
    lappend items($node) $id

    _set_help $path $node

    return $y1
}


# ----------------------------------------------------------------------------
#  Command Tree::_draw_subnodes
# ----------------------------------------------------------------------------
proc Tree::_draw_subnodes { path nodes x0 y0 deltax deltay padx showlines } {
    set y1 $y0
    foreach node $nodes {
	set padx   [_get_node_padx $path $node]
	set deltax [_get_node_deltax $path $node]
        set yp $y1
        set y1 [_draw_node $path $node $x0 [expr {$y1+$deltay}] \
                $deltax $deltay $padx $showlines]
    }
    if {$showlines && [llength $nodes]} {
	if {$y0 < 0} {
	    # Adjust the drawing of the line to the first root node
	    # to start at the vertical point (not go up).
	    incr y0 $deltay
	}
        set id [$path.c create line $x0 $y0 $x0 [expr {$yp+$deltay}] \
                    -fill    [Widget::getoption $path -linesfill]   \
                    -stipple [Widget::getoption $path -linestipple] \
                    -tags    line]

        $path.c lower $id
    }
    return $y1
}


# ----------------------------------------------------------------------------
#  Command Tree::_update_nodes
# ----------------------------------------------------------------------------
proc Tree::_update_nodes { path } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    foreach {node flag} $data(upd,nodes) {
        if {![info exists items($node)]} { continue }
        set idn [lindex $items($node) 1]

	set padx   [_get_node_padx $path $node]
	set deltax [_get_node_deltax $path $node]
	set c  [$path.c coords $idn]
	set x1 [expr {[lindex $c 0]-$padx}]
	set x0 [expr {$x1-$deltax-5}]
	set y0 [lindex $c 1]
	if {$flag & 48} {
	    # -window or -image modified
	    set win  [Widget::getoption $path.$node -window]
	    set img  [Widget::getoption $path.$node -image]
	    set anc  [Widget::cget $path.$node -anchor]
            set idi  [lindex $items($node) 3]
	    set type [lindex [$path.c gettags $idi] 1]
	    if {[string length $win]} {
		if {[string equal $type "win"]} {
		    $path.c itemconfigure $idi -window $win
		} else {
		    $path.c delete $idi
                    set tags [_get_node_tags $path $node [list win i:$node]]
		    set idi [$path.c create window $x1 $y0 -window $win \
                        -anchor $anc -tags $tags]
                    set items($node) [lreplace $items($node) 3 3 $idi]
		}
	    } elseif {[string length $img]} {
		if {[string equal $type "img"]} {
		    $path.c itemconfigure $idi -image $img
		} else {
		    $path.c delete $idi
                    set tags [_get_node_tags $path $node [list win i:$node]]
		    set idi [$path.c create image $x1 $y0 -image $img \
                        -anchor $anc -tags $tags]
                    set items($node) [lreplace $items($node) 3 3 $idi]
		}
	    } else {
		$path.c delete $idi
                set items($node) [lreplace $items($node) 3 3 ""]
	    }
	}

	if {$flag & 8} {
	    # -drawcross modified
	    set len [expr {[llength $data($node)] > 1}]
	    set dc  [Widget::getoption $path.$node -drawcross]
	    set exp [Widget::getoption $path.$node -open]

	    if {![string equal $dc "never"]
		&& ($len || [string equal $dc "allways"])} {
		set idc [_draw_cross $path $node $exp $x0 $y0]
                set items($node) [lreplace $items($node) 2 2 $idc]
	    } else {
                set idc [lindex $items($node) 2]
		$path.c delete $idc
                set items($node) [lreplace $items($node) 2 2 ""]
	    }
	}

	if {$flag & 7} {
	    # -font, -text or -fill modified
	    $path.c itemconfigure $idn \
		-text [Widget::getoption $path.$node -text] \
		-fill [Widget::getoption $path.$node -fill] \
		-font [_get_option $path $node -font]
	}
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::_draw_tree
# ----------------------------------------------------------------------------
proc Tree::_draw_tree { path } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    if {[info exists items]} { unset items }

    $path.c delete all
    set cursor [$path.c cget -cursor]
    $path.c configure -cursor watch

    set x0 8
    if {![Widget::getoption $path -showlines]} { set x0 0 }

    Tree::_draw_subnodes $path [lrange $data(root) 1 end] $x0 \
        [expr {-[Widget::cget $path -deltay]/2}] \
        [Widget::getoption $path -deltax] \
        [Widget::cget $path -deltay] \
        [Widget::getoption $path -padx]   \
        [Widget::getoption $path -showlines]
    $path.c configure -cursor $cursor
}


# ----------------------------------------------------------------------------
#  Command Tree::_redraw_tree
# ----------------------------------------------------------------------------
proc Tree::_redraw_tree { path } {
    Widget::getVariable $path data

    if {[Widget::getoption $path -redraw]} {
        if {$data(upd,level) == 2} {
            _update_nodes $path
        } elseif {$data(upd,level) == 3} {
            _draw_tree $path
        }
        _redraw_selection $path
        _update_scrollregion $path
        set data(upd,nodes)   {}
        set data(upd,level)   0
        set data(upd,afterid) ""
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::_redraw_selection
# ----------------------------------------------------------------------------
proc Tree::_redraw_selection { path } {
    Widget::getVariable $path data

    set selbg [Widget::cget $path -selectbackground]
    set selfg [Widget::cget $path -selectforeground]
    set fill  [Widget::getoption $path -selectfill]
    if {$fill} {
        set scroll [$path.c cget -scrollregion]
        if {[llength $scroll]} {
            set xmax [expr {[lindex $scroll 2]-1}]
        } else {
            set xmax [winfo width $path]
        }
    }
    foreach id [$path.c find withtag sel] {
        set node [Tree::_get_node_name $path $id 1]
        $path.c itemconfigure "n:$node" \
            -fill [Widget::getoption $path.$node -fill]
    }
    $path.c delete sel
    foreach node $data(selnodes) {
        set bbox [$path.c bbox "n:$node"]
        if {[llength $bbox]} {
            if {$fill} {
		# get the image to (if any), as it may have different height
		set bbox [$path.c bbox "n:$node" "i:$node"]
                set bbox [list 0 [lindex $bbox 1] $xmax [lindex $bbox 3]]
            }
            set id [$path.c create rectangle $bbox -tags [list sel s:$node] \
			-fill $selbg -outline $selbg]
            $path.c itemconfigure "n:$node" -fill $selfg
            $path.c lower $id
        }
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::_redraw_idle
# ----------------------------------------------------------------------------
proc Tree::_redraw_idle { path level } {
    Widget::getVariable $path data

    if {[Widget::getoption $path -redraw] && $data(upd,afterid) == ""} {
        set data(upd,afterid) [after idle [list Tree::_redraw_tree $path]]
    }
    if {$level > $data(upd,level)} {
        set data(upd,level) $level
    }
    return ""
}


# ----------------------------------------------------------------------------
#  Command Tree::_init_drag_cmd
# ----------------------------------------------------------------------------
proc Tree::_init_drag_cmd { path X Y top } {
    set path [winfo parent $path]
    set ltags [$path.c gettags current]
    set item  [lindex $ltags 1]
    if {[string equal $item "node"]
        || [string equal $item "img"]
        || [string equal $item "win"]} {
        set node [Tree::_get_node_name $path current 2]
        if {[llength [set cmd [Widget::getoption $path -draginitcmd]]]} {
            return [uplevel \#0 $cmd [list $path $node $top]]
        }
        if {[set type [Widget::getoption $path -dragtype]] == ""} {
            set type "TREE_NODE"
        }
        if {[set img [Widget::getoption $path.$node -image]] != ""} {
            pack [label $top.l -image $img -padx 0 -pady 0]
        }
        return [list $type {copy move link} $node]
    }
    return {}
}


# ----------------------------------------------------------------------------
#  Command Tree::_drop_cmd
# ----------------------------------------------------------------------------
proc Tree::_drop_cmd { path source X Y op type dnddata } {
    set path [winfo parent $path]
    Widget::getVariable $path data

    $path.c delete drop
    if {[string length $data(dnd,afterid)]} {
        after cancel $data(dnd,afterid)
        set data(dnd,afterid) ""
    }
    set data(dnd,scroll) ""
    if {[llength $data(dnd,node)]
	&& [llength [set cmd [Widget::getoption $path -dropcmd]]]} {
	return [uplevel \#0 $cmd \
                [list $path $source $data(dnd,node) $op $type $dnddata]]
    }
    return 0
}


# ----------------------------------------------------------------------------
#  Command Tree::_over_cmd
# ----------------------------------------------------------------------------
proc Tree::_over_cmd { path source event X Y op type dnddata } {
    set path [winfo parent $path]
    Widget::getVariable $path data

    if {[string equal $event "leave"]} {
        # we leave the window tree
        $path.c delete drop
        if {[string length $data(dnd,afterid)]} {
            after cancel $data(dnd,afterid)
            set data(dnd,afterid) ""
        }
        set data(dnd,scroll) ""
        return 0
    }

    if {[string equal $event "enter"]} {
        # we enter the window tree - dnd data initialization
        set mode [Widget::getoption $path -dropovermode]
        set data(dnd,mode) 0
        foreach c {w p n} {
            set data(dnd,mode) [expr {($data(dnd,mode) << 1) 
                                | ([string first $c $mode] != -1)}]
        }
        set bbox [$path.c bbox all]
        if {[llength $bbox]} {
            set data(dnd,xs) [lindex $bbox 2]
            set data(dnd,empty) 0
        } else {
            set data(dnd,xs) 0
            set data(dnd,empty) 1
        }
        set data(dnd,node) {}
    }

    set x [expr {$X-[winfo rootx $path]}]
    set y [expr {$Y-[winfo rooty $path]}]

    $path.c delete drop
    set data(dnd,node) {}

    # test for auto-scroll unless mode is widget only
    if {$data(dnd,mode) != 4 && [_auto_scroll $path $x $y] != ""} { return 2 }

    if {$data(dnd,mode) & 4} {
        # dropovermode includes widget
        set target [list widget]
        set vmode  4
    } else {
        set target [list ""]
        set vmode  0
    }

    if {($data(dnd,mode) & 2) && $data(dnd,empty)} {
        # dropovermode includes position and tree is empty
        lappend target [list root 0]
        set vmode  [expr {$vmode | 2}]
    }

    set xs $data(dnd,xs)
    set xc [$path.c canvasx $x]
    if {$xc <= $xs} {
        set yc   [$path.c canvasy $y]
        set dy   [$path.c cget -yscrollincrement]
        set line [expr {int($yc/$dy)}]
        set xi   0
        set yi   [expr {$line*$dy}]
        set ys   [expr {$yi+$dy}]
        set found 0
        foreach id [$path.c find overlapping $xi $yi $xs $ys] {
            set ltags [$path.c gettags $id]
            set item  [lindex $ltags 1]
            if {[string equal $item "node"]
                || [string equal $item "img"]
                || [string equal $item "win"]} {
                # item is the label or image/window of the node
                set node [Tree::_get_node_name $path $id 2]
		set found 1
		break
	    }
	}

	if {$found} {
	    set padx   [_get_node_padx $path $node]
	    set deltax [_get_node_deltax $path $node]
            set xi [expr {[lindex [$path.c coords n:$node] 0] - $padx - 1}]
                if {$data(dnd,mode) & 1} {
                    # dropovermode includes node
                    lappend target $node
                    set vmode [expr {$vmode | 1}]
                } else {
                    lappend target ""
                }

                if {$data(dnd,mode) & 2} {
                    # dropovermode includes position
                    if {$yc >= $yi+$dy/2} {
                        # position is after $node
                        if {[Widget::getoption $path.$node -open] &&
                             [llength $data($node)] > 1} {
                            # $node is open and have subnodes
                            # drop position is 0 in children of $node
                            set parent $node
                            set index  0
                            set xli    [expr {$xi-5}]
                        } elseif {[Widget::getoption $path.$node -open]} {
                            ## $node is open but has no children.
                            set parent $node
                            set index  0
                            set xli    [expr {$xi-5}]
                        } else {
                            # $node is not open and doesn't have subnodes
                            # drop position is after $node in children of
                            # parent of $node
                            set parent [lindex $data($node) 0]
                            set index  [lsearch -exact $data($parent) $node]
                            set xli    [expr {$xi - $deltax - 5}]
                        }
                        set yl $ys
                    } else {
                        # position is before $node
                        # drop position is before $node in children of parent
                        # of $node
                        set parent [lindex $data($node) 0]
                        set index \
                            [expr {[lsearch -exact $data($parent) $node] - 1}]
                        set xli    [expr {$xi - $deltax - 5}]
                        set yl     $yi
                    }
                    lappend target [list $parent $index]
                    set vmode  [expr {$vmode | 2}]
                } else {
                    lappend target {}
                }

                if {($vmode & 3) == 3} {
                    # result have both node and position
                    # we compute what is the preferred method
                    if {$yc-$yi <= 3 || $ys-$yc <= 3} {
                        lappend target "position"
                    } else {
                        lappend target "node"
                    }
                }
            }
        }

    if {$vmode && [llength [set cmd [Widget::getoption $path -dropovercmd]]]} {
        # user-defined dropover command
        set res     [uplevel \#0 $cmd \
                        [list $path $source $target $op $type $dnddata]]
        set code    [lindex $res 0]
        set newmode 0
        if {$code & 1} {
            # update vmode
            set mode [lindex $res 1]
            if {($vmode & 1) && [string equal $mode "node"]} {
                set newmode 1
            } elseif {($vmode & 2) && [string equal $mode "position"]} {
                set newmode 2
            } elseif {($vmode & 4) && [string equal $mode "widget"]} {
                set newmode 4
            }
        }
        set vmode $newmode
    } else {
        if {($vmode & 3) == 3} {
            # result have both item and position
            # we choose the preferred method
            if {[string equal [lindex $target 3] "position"]} {
                set vmode [expr {$vmode & ~1}]
            } else {
                set vmode [expr {$vmode & ~2}]
            }
        }

        if {$data(dnd,mode) == 4 || $data(dnd,mode) == 0} {
            # dropovermode is widget or empty - recall is not necessary
            set code 1
        } else {
            set code 3
        }
    }

    if {!$data(dnd,empty)} {
	# draw dnd visual following vmode
	if {$vmode & 1} {
	    set data(dnd,node) [list "node" [lindex $target 1]]
	    $path.c create rectangle $xi $yi $xs $ys -tags drop
	} elseif {$vmode & 2} {
	    set data(dnd,node) [concat "position" [lindex $target 2]]
	    $path.c create line \
                [list $xli [expr {$yl-$dy/2}] $xli $yl $xs $yl] -tags drop
	} elseif {$vmode & 4} {
	    set data(dnd,node) [list "widget"]
	} else {
	    set code [expr {$code & 2}]
	}
    }

    if {$code & 1} {
        DropSite::setcursor based_arrow_down
    } else {
        DropSite::setcursor dot
    }
    return $code
}


# Tree::_drag_and_drop --
#
#	A default command to handle drag-and-drop functions local to this
#       tree.  With this as the default -dropcmd, the user can simply
#       enable drag-and-drop and be able to move items within this tree
#       with no further code.
#
# Arguments:
#       Standard arguments passed to a dropcmd.
#
# Results:
#	none
proc Tree::_drag_and_drop { path from endItem operation type startItem } {
    ## This proc only handles drag-and-drop commands within itself.
    ## If the widget this came from is not our widget (minus the canvas),
    ## we don't want to do anything.  They need to handle this themselves.
    if {[winfo parent $from] != $path} { return }

    set place [lindex $endItem 0]

    switch -- $place {
        "node" {
            set node   [lindex $endItem 1]
            set parent [$path parent $node]
            set index  [$path index $node]
        }

        "position" {
            set parent [lindex $endItem 1]
            set index  [lindex $endItem 2]
        } 

        default {
            return
        }
    }

    if {[string equal $operation "copy"]} {
        set options [Widget::options $path.$startItem]
        eval $path insert $idx [list $startItem#auto] $options
    } else {
        $path move $parent $startItem $index
    }
}


# ----------------------------------------------------------------------------
#  Command Tree::_auto_scroll
# ----------------------------------------------------------------------------
proc Tree::_auto_scroll { path x y } {
    Widget::getVariable $path data

    set xmax   [winfo width  $path]
    set ymax   [winfo height $path]
    set scroll {}
    if {$y <= 6} {
        if {[lindex [$path.c yview] 0] > 0} {
            set scroll [list yview -1]
            DropSite::setcursor sb_up_arrow
        }
    } elseif {$y >= $ymax-6} {
        if {[lindex [$path.c yview] 1] < 1} {
            set scroll [list yview 1]
            DropSite::setcursor sb_down_arrow
        }
    } elseif {$x <= 6} {
        if {[lindex [$path.c xview] 0] > 0} {
            set scroll [list xview -1]
            DropSite::setcursor sb_left_arrow
        }
    } elseif {$x >= $xmax-6} {
        if {[lindex [$path.c xview] 1] < 1} {
            set scroll [list xview 1]
            DropSite::setcursor sb_right_arrow
        }
    }

    if {[string length $data(dnd,afterid)]
        && ![string equal $data(dnd,scroll) $scroll]} {
        after cancel $data(dnd,afterid)
        set data(dnd,afterid) ""
    }

    set data(dnd,scroll) $scroll
    if {[string length $scroll] && ![string length $data(dnd,afterid)]} {
        set data(dnd,afterid) [after 200 [list Tree::_scroll $path $scroll]]
    }
    return $data(dnd,afterid)
}


# ----------------------------------------------------------------------------
#  Command Tree::_scroll
# ----------------------------------------------------------------------------
proc Tree::_scroll { path cmd dir } {
    Widget::getVariable $path data

    if {($dir == -1 && [lindex [$path.c $cmd] 0] > 0)
        || ($dir == 1  && [lindex [$path.c $cmd] 1] < 1)} {
        $path.c $cmd scroll $dir units
        set data(dnd,afterid) [after 100 [list Tree::_scroll $path $cmd $dir]]
    } else {
        set data(dnd,afterid) ""
        DropSite::setcursor dot
    }
}

# Tree::_keynav --
#
#	Handle navigational keypresses on the tree.
#
# Arguments:
#	which      tag indicating the direction of motion:
#                  up         move to the node graphically above current
#                  down       move to the node graphically below current
#                  left       close current if open, else move to parent
#                  right      open current if closed, else move to child
#                  open       open current if closed, close current if open
#       win        name of the tree widget
#
# Results:
#	None.

proc Tree::_keynav {which path} {
    # Keyboard navigation is riddled with special cases.  In order to avoid
    # the complex logic, we will instead make a list of all the visible,
    # selectable nodes, then do a simple next or previous operation.

    # One easy way to get all of the visible nodes is to query the canvas
    # object for all the items with the "node" tag; since the tree is always
    # completely redrawn, this list will be in vertical order.
    set nodes {}
    foreach nodeItem [$path.c find withtag node] {
	set node [Tree::_get_node_name $path $nodeItem 2]
	if {[Widget::cget $path.$node -selectable]} {
	    lappend nodes $node
	}
    }

    # Keyboard navigation is all relative to the current node
    # surles: Get the current node for single or multiple selection schemas.
    set node [_get_current_node $path]

    switch -exact -- $which {
	"up" {
	    # Up goes to the node that is vertically above the current node
	    # (NOT necessarily the current node's parent)
            if {![string length $node]} { return }

	    set index [lsearch -exact $nodes $node]
	    incr index -1
	    if {$index >= 0} {
		$path selection set [lindex $nodes $index]
		_set_current_node $path [lindex $nodes $index]
		$path see [lindex $nodes $index]
		return
	    }
	}

	"down" {
	    # Down goes to the node that is vertically below the current node
            if {![string length $node]} {
		$path selection set [lindex $nodes 0]
		_set_current_node $path [lindex $nodes 0]
		$path see [lindex $nodes 0]
		return
	    }

	    set index [lsearch -exact $nodes $node]
	    incr index
	    if {$index < [llength $nodes]} {
		$path selection set [lindex $nodes $index]
		_set_current_node $path [lindex $nodes $index]
		$path see [lindex $nodes $index]
		return
	    }
	}

	"right" {
	    # On a right arrow, if the current node is closed, open it.
	    # If the current node is open, go to its first child
            if {![string length $node]} { return }

            if {[Widget::getoption $path.$node -open]} {
                if { [llength [$path nodes $node]] } {
		    set index [lsearch -exact $nodes $node]
		    incr index
		    if {$index < [llength $nodes]} {
			$path selection set [lindex $nodes $index]
			_set_current_node $path [lindex $nodes $index]
			$path see [lindex $nodes $index]
			return
		    }
                }
            } else {
                $path itemconfigure $node -open 1
                if {[llength [set cmd [Widget::getoption $path -opencmd]]]} {
                    uplevel \#0 $cmd [list $node]
                }
                return
            }
	}

	"left" {
	    # On a left arrow, if the current node is open, close it.
	    # If the current node is closed, go to its parent.
            if {![string length $node]} { return }

	    if {[Widget::getoption $path.$node -open]} {
		$path itemconfigure $node -open 0
                if {[llength [set cmd [Widget::getoption $path -closecmd]]]} {
                    uplevel \#0 $cmd [list $node]
                }
		return
	    } else {
		set parent [$path parent $node]
	        if {[string equal $parent "root"]} {
		    set parent $node
                } else {
                    while {![$path itemcget $parent -selectable]} {
		        set parent [$path parent $parent]
		        if {[string equal $parent "root"]} {
			    set parent $node
			    break
		        }
                    }
		}
		$path selection set $parent
		_set_current_node $path $parent
		$path see $parent
		return
	    }
	}

	"space" {
            if {[string length $node]} {
                Tree::toggle $path $node
            }
	}
    }
}

# Tree::_get_current_node --
#
#	Get the current node for either single or multiple
#	node selection trees.  If the tree allows for 
#	multiple selection, return the cursor node.  Otherwise,
#	if there is a selection, return the first node in the
#	list.  If there is no selection, return the root node.
#
# arguments:
#       win        name of the tree widget
#
# Results:
#	The current node.

proc Tree::_get_current_node {win} {
    if {[info exists selectTree::selectCursor($win)]} {
	set result $selectTree::selectCursor($win)
    } elseif {[llength [set selList [$win selection get]]]} {
	set result [lindex $selList 0]
    } else {
	set result ""
    }
    return $result
}

# Tree::_set_current_node --
#
#	Set the current node for either single or multiple
#	node selection trees.
#
# arguments:
#       win        Name of the tree widget
#	node	   The current node.
#
# Results:
#	None.

proc Tree::_set_current_node {win node} {
    if {[info exists selectTree::selectCursor($win)]} {
	set selectTree::selectCursor($win) $node
    }
    return
}

# Tree::_get_node_name --
#
#	Given a canvas item, get the name of the tree node represented by that
#	item.
#
# Arguments:
#	path		tree to query
#	item		Optional canvas item to examine; if omitted, 
#			defaults to "current"
#	tagindex	Optional tag index, since the n:nodename tag is not
#			in the same spot for all canvas items.  If omitted,
#			defaults to "end-1", so it works with "current" item.
#
# Results:
#	node	name of the tree node.

proc Tree::_get_node_name {path {item current} {tagindex end-1}} {
    return [string range [lindex [$path.c gettags $item] $tagindex] 2 end]
}

# Tree::_get_node_padx --
#
#	Given a node in the tree, return it's padx value.  If the value is
#	less than 0, default to the padx of the entire tree.
#
# Arguments:
#	path		Tree to query
#	node		Node in the tree
#
# Results:
#	padx		The numeric padx value
proc Tree::_get_node_padx {path node} {
    set padx [Widget::getoption $path.$node -padx]
    if {$padx < 0} { set padx [Widget::getoption $path -padx] }
    return $padx
}

# Tree::_get_node_deltax --
#
#	Given a node in the tree, return it's deltax value.  If the value is
#	less than 0, default to the deltax of the entire tree.
#
# Arguments:
#	path		Tree to query
#	node		Node in the tree
#
# Results:
#	deltax		The numeric deltax value
proc Tree::_get_node_deltax {path node} {
    set deltax [Widget::getoption $path.$node -deltax]
    if {$deltax < 0} { set deltax [Widget::getoption $path -deltax] }
    return $deltax
}


# Tree::_get_node_tags --
#
#	Given a node in the tree, return a list of tags to apply to its
#       canvas item.
#
# Arguments:
#	path		Tree to query
#	node		Node in the tree
#	tags		A list of tags to add to the final list
#
# Results:
#	list		The list of tags to apply to the canvas item
proc Tree::_get_node_tags {path node {tags ""}} {
    eval [linsert $tags 0 lappend list TreeItemSentinal]
    if {[Widget::getoption $path.$node -helptext] == ""} { return $list }

    switch -- [Widget::getoption $path.$node -helptype] {
	balloon {
	    lappend list BwHelpBalloon
	}
	variable {
	    lappend list BwHelpVariable
	}
    }
    return $list
}

# Tree::_set_help --
#
#	Register dynamic help for a node in the tree.
#
# Arguments:
#	path		Tree to query
#	node		Node in the tree
#       force		Optional argument to force a reset of the help
#
# Results:
#	none
proc Tree::_set_help { path node } {
    Widget::getVariable $path help

    set item $path.$node
    set opts [list -helptype -helptext -helpvar]
    foreach {cty ctx cv} [eval [linsert $opts 0 Widget::hasChangedX $item]] break
    set text [Widget::getoption $item -helptext]

    ## If we've never set help for this item before, and text is not blank,
    ## we need to setup help.  We also need to reset help if any of the
    ## options have changed.
    if { (![info exists help($node)] && $text != "") || $cty || $ctx || $cv } {
	set help($node) 1
	set type [Widget::getoption $item -helptype]
        switch $type {
            balloon {
		DynamicHelp::register $path.c balloon n:$node $text
		DynamicHelp::register $path.c balloon i:$node $text
		DynamicHelp::register $path.c balloon b:$node $text
            }
            variable {
		set var [Widget::getoption $item -helpvar]
		DynamicHelp::register $path.c variable n:$node $var $text
		DynamicHelp::register $path.c variable i:$node $var $text
		DynamicHelp::register $path.c variable b:$node $var $text
            }
        }
    }
}

proc Tree::_mouse_select { path cmd args } {
    eval [linsert $args 0 selection $path $cmd]
    switch -- $cmd {
        "add" - "clear" - "remove" - "set" - "toggle" {
            event generate $path <<TreeSelect>>
        }
    }
}


proc Tree::_node_name { path node } {
    set map [list & _ | _ ^ _ ! _]
    return  [string map $map $node]
}


proc Tree::_get_option { path node option {default ""} } {
    return [Widget::getOption $option $default $path.$node $path]
}


# ----------------------------------------------------------------------------
#  Command Tree::_destroy
# ----------------------------------------------------------------------------
proc Tree::_destroy { path } {
    Widget::getVariable $path data

    if {[string length $data(upd,afterid)]} {
        after cancel $data(upd,afterid)
    }

    if {[string length $data(dnd,afterid)]} {
        after cancel $data(dnd,afterid)
    }

    _subdelete $path [lrange $data(root) 1 end]
    Widget::destroy $path
}
Added lib/BWidget/ttkbutton.tcl.














































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# ----------------------------------------------------------------------------
#  button.tcl
#  This file is part of Unifix BWidget Toolkit
# ----------------------------------------------------------------------------
#  Index of commands:
#
#   Public Commands
#     - TTKButton::create
#     - TTKButton::configure
#     - TTKButton::cget
#     - TTKButton::invoke
#
#   Private Commands (event bindings)
#     - TTKButton::_destroy
#     - TTKButton::_enter
#     - TTKButton::_leave
#     - TTKButton::_press
#     - TTKButton::_release
#     - TTKButton::_repeat
# ----------------------------------------------------------------------------

namespace eval TTKButton {
    Widget::define TTKButton button DynamicHelp

    Widget::tkinclude TTKButton ttk::button :cmd \
        remove { -class }

    Widget::declare TTKButton {
        {-name                 String     ""      0 }
        {-repeatdelay          Int        0       0 "%d >= 0" }
        {-repeatinterval       Int        0       0 "%d >= 0" }
    }

    if 0 {
        Widget::declare Button {
            {-name                 String     ""      0 }
            {-text                 String     ""      0 }
            {-textvariable         String     ""      0 }
            {-underline            Int        -1      0 "%d >= -1" }
            {-armcommand           String     ""      0 }
            {-disarmcommand        String     ""      0 }
            {-command              String     ""      0 }
            {-state                TkResource ""      0 button }
            {-repeatdelay          Int        0       0 "%d >= 0" }
            {-repeatinterval       Int        0       0 "%d >= 0" }
            {-relief               Enum       raised  0 
                    {raised sunken flat ridge solid groove link}}
            {-image                String     ""      0 }
            {-activeimage          String     ""      0 }
            {-pressedimage         String     ""      0 }
            {-disabledimage        String     ""      0 }
        }

        Widget::syncoptions Button "" :cmd { -text {} -underline {} }
    }

    DynamicHelp::include TTKButton balloon

    variable _current ""
    variable _pressed ""

    #bind BwButton <Enter>           {Button::_enter %W}
    #bind BwButton <Leave>           {Button::_leave %W}
    #bind BwButton <ButtonPress-1>   {Button::_press %W}
    #bind BwButton <ButtonRelease-1> {Button::_release %W}
    #bind BwButton <Key-space>       {Button::invoke %W; break}
    #bind BwButton <Return>          {Button::invoke %W; break}
    #bind BwButton <Destroy>         {Widget::destroy %W}
}


# ----------------------------------------------------------------------------
#  Command TTKButton::create
# ----------------------------------------------------------------------------
proc TTKButton::create { path args } {
    foreach {opt val} $args {
        if {[Widget::optionExists TTKButton $opt]} {
            lappend opts $opt $val
        }
    }

    Widget::initArgs TTKButton $opts maps

    eval [list ttk::button $path] $maps(:cmd)

    Widget::initFromODB TTKButton $path $maps(TTKButton)

    set var [$path cget -textvariable]
    if {![string length $var]} {
        set desc [BWidget::getname [Widget::getoption $path -name]]
        if {[llength $desc]} {
            set text  [lindex $desc 0]
            set under [lindex $desc 1]
            $path configure -text $text -underline $under
        } else {
            set text  [$path cget -text]
            set under [$path cget -underline]
        }
    } else {
        set text  ""
        set under -1
        $path configure -underline $under
    }

    ## Add our binding to pick up <Destroy> events.
    set top [winfo toplevel $path]
    bindtags $path [list $path TButton TTKButton $top all]

    DynamicHelp::sethelp $path $path 1

    return [Widget::create TTKButton $path]
}


# ----------------------------------------------------------------------------
#  Command TTKButton::configure
# ----------------------------------------------------------------------------
proc TTKButton::configure { path args } {
    set oldunder [$path:cmd cget -underline]
    if {$oldunder != -1} {
        set text      [$path:cmd cget -text]
        set oldaccel1 [string tolower [string index $text $oldunder]]
        set oldaccel2 [string toupper $oldaccel1]
    } else {
        set oldaccel1 ""
        set oldaccel2 ""
    }
    set res [Widget::configure $path $args]

    if {[Widget::anyChangedX $path -textvariable -name -text -underline]} {
	set var   [Widget::cget $path -textvariable]
	set text  [Widget::cget $path -text]
	set under [Widget::cget $path -underline]

        if {![string length $var]} {
            set desc [BWidget::getname [Widget::cget $path -name]]
            if {[llength $desc]} {
                set text  [lindex $desc 0]
                set under [lindex $desc 1]
            }
        } else {
            set under -1
            set text  ""
        }
        set top [winfo toplevel $path]
        if {![string equal $oldaccel1 ""]} {
            bind $top <Alt-$oldaccel1> {}
            bind $top <Alt-$oldaccel2> {}
        }
        set accel1 [string tolower [string index $text $under]]
        set accel2 [string toupper $accel1]
        if {![string equal $accel1 ""]} {
            bind $top <Alt-$accel1> [list TTKButton::invoke $path]
            bind $top <Alt-$accel2> [list TTKButton::invoke $path]
        }
        $path:cmd configure -text $text -underline $under -textvariable $var
    }

    DynamicHelp::sethelp $path $path

    return $res
}


# ----------------------------------------------------------------------------
#  Command TTKButton::cget
# ----------------------------------------------------------------------------
proc TTKButton::cget { path option } {
    Widget::cget $path $option
}


proc TTKButton::state { path args } {
    return [uplevel #0 [list $path:cmd state] $args]
}


proc TTKButton::instate { path args } {
    return [uplevel #0 [list $path:cmd instate] $args]
}


proc TTKButton::invoke { path } {
    return [uplevel #0 [list $path:cmd invoke]]
}


# ----------------------------------------------------------------------------
#  Command TTKButton::_enter
# ----------------------------------------------------------------------------
proc TTKButton::_enter { path } {
    variable _current
    variable _pressed

    set _current $path
    if {![string equal [Widget::cget $path -state] "disabled"]} {
        $path:cmd configure -state active
        if {[string equal $_pressed $path]} {
            $path:cmd configure -relief sunken
        } elseif {[string equal [Widget::cget $path -relief] "link"]} {
            $path:cmd configure -relief raised
        }

        set image [Widget::cget $path -activeimage]
        if {[string equal $_pressed $path]} {
            set pressedimage [Widget::cget $path -pressedimage]
            if {![string equal $pressedimage ""]} { set image $pressedimage }
        }
        if {![string equal $image ""]} { $path:cmd configure -image $image }
    }
}


# ----------------------------------------------------------------------------
#  Command TTKButton::_leave
# ----------------------------------------------------------------------------
proc TTKButton::_leave { path } {
    variable _current
    variable _pressed

    set _current ""
    if {[string equal [Widget::cget $path -state] "disabled"]} {
        set dimg [Widget::cget $path -disabledimage]
        if {![string equal $dimg ""]} { $path:cmd configure -state normal }
    } else {
        set relief [Widget::cget $path -relief]
        if {[string equal $_pressed $path]} {
            if {[string equal $relief "link"]} {
                set relief raised
            }
        } elseif {[string equal $relief "link"]} {
            set relief flat
        }

        $path:cmd configure \
            -relief $relief \
            -state  [Widget::cget $path -state] \
            -image  [Widget::cget $path -image]
    }
}


# ----------------------------------------------------------------------------
#  Command TTKButton::_press
# ----------------------------------------------------------------------------
proc TTKButton::_press { path } {
    variable _pressed

    if {![string equal [Widget::cget $path -state] "disabled"]} {
        set _pressed $path
	$path:cmd configure -relief sunken

        set img [Widget::cget $path -pressedimage]
        if {![string equal $img ""]} { $path:cmd configure -image $img }

	set cmd [Widget::getoption $path -armcommand]
        if {![string equal $cmd ""]} {
            uplevel \#0 $cmd
	    set repeatdelay [Widget::getoption $path -repeatdelay]
	    set repeatint [Widget::getoption $path -repeatinterval]
            if {$repeatdelay > 0} {
                after $repeatdelay [list TTKButton::_repeat $path]
            } elseif {$repeatint > 0} {
                after $repeatint [list TTKButton::_repeat $path]
	    }
        }
    }
}


# ----------------------------------------------------------------------------
#  Command TTKButton::_release
# ----------------------------------------------------------------------------
proc TTKButton::_release { path } {
    variable _current
    variable _pressed

    if {[string equal $_pressed $path]} {
        set pressed $_pressed
        set _pressed ""
        set relief [Widget::getoption $path -relief]
	after cancel [list TTKButton::_repeat $path]

        if {[string equal $relief "link"]} {
            set relief raised
        }
        
        set image [Widget::cget $path -image]
        if {[string equal $pressed $path]} {
            set activeimage [Widget::cget $path -activeimage]
            if {![string equal $activeimage ""]} { set image $activeimage }
        }

        $path:cmd configure -relief $relief -image $image

	set cmd [Widget::getoption $path -disarmcommand]
        if {![string equal $cmd ""]} {
            uplevel \#0 $cmd
        }

        if {[string equal $_current $path] &&
             ![string equal [Widget::cget $path -state] "disabled"] && \
	     [set cmd [Widget::getoption $path -command]] != ""} {
            uplevel \#0 $cmd
        }
    }
}


# ----------------------------------------------------------------------------
#  Command TTKButton::_repeat
# ----------------------------------------------------------------------------
proc TTKButton::_repeat { path } {
    variable _current
    variable _pressed

    if {$_current == $path && $_pressed == $path &&
         ![string equal [Widget::cget $path -state] "disabled"] &&
         [set cmd [Widget::getoption $path -armcommand]] != ""} {
        uplevel \#0 $cmd
    }
    if { $_pressed == $path &&
         ([set delay [Widget::getoption $path -repeatinterval]] >0 ||
          [set delay [Widget::getoption $path -repeatdelay]] > 0) } {
        after $delay [list TTKButton::_repeat $path]
    }
}
Added lib/BWidget/utils.tcl.














































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
# ----------------------------------------------------------------------------
#  utils.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: utils.tcl,v 1.11 2004/01/06 07:22:39 damonc Exp $
# ----------------------------------------------------------------------------
#  Index of commands:
#     - BWidget::globalexists
#     - BWidget::setglobal
#     - BWidget::getglobal
#     - BWidget::traceglobal
#     - BWidget::assert
#     - BWidget::clonename
#     - BWidget::get3dcolor
#     - BWidget::XLFDfont
#     - BWidget::place
#     - BWidget::grab
#     - BWidget::focus
# ----------------------------------------------------------------------------

namespace eval BWidget {
    variable _gstack [list]
    variable _fstack [list]
}


proc BWidget::use { args } {
    variable includes

    if {![llength $args]} {
        ## Setup some default packages.
        BWidget::use aqua [expr {$::tcl_version >= 8.4
                            && [string equal [tk windowingsystem] "aqua"]}]
        return
    }

    set package [lindex $args 0]
    set value   [lindex $args 1]
    set force   [string equal [lindex $args 2] "-force"]
    if {![string length $value]} { set value 1 }

    if {$value && ($force || ![info exists includes($package)])} {
        ## Each package supported to enhance BWidgets is setup here.
        switch -- $package {
            "aqua" {

            }

            "png" {
                if {[catch { package require img::png } err]} {
                    if {[catch { package require tkpng } err]} {
                        return -code error "Could not find img::png or tkpng\
                            package to support PNG data"
                    } else {
                        set ::BWidget::imageFormat png
                    }
                } else {
                    set ::BWidget::imageFormat PNG
                }

                if {![info exists ::BWidget::iconLibraryFile]} {
                    set ::BWidget::iconLibraryFile \
                        [file join $::BWidget::imageDir BWidget.png.tkico]
                }
            }

            "ttk" {
                Widget::theme 1

                variable ::BWidget::colors

                foreach {opt val} [style configure .] {
                    switch -- $opt {
                        "-background" {
                            set colors(SystemButtonFace) $val
                        }

                        "-foreground" {
                            set colors(SystemWindowText) $val
                        }

                        "-selectbackground" {
                            set colors(SystemHighlight) $val
                        }

                        "-selectforeground" {
                            set colors(SystemHighlightText) $val
                        }

                        "-troughcolor" {
                            set colors(SystemScrollbar) $val
                        }
                    }
                }
            }
        }
    }

    set includes($package) $value
    return $value
}


proc BWidget::using { package } {
    if {[info exists ::BWidget::includes($package)]} {
        return $::BWidget::includes($package)
    }
    return 0
}


# ----------------------------------------------------------------------------
#  Command BWidget::globalexists
# ----------------------------------------------------------------------------
proc BWidget::globalexists { varName } {
    return [uplevel \#0 [list info exists $varName]]
}


# ----------------------------------------------------------------------------
#  Command BWidget::setglobal
# ----------------------------------------------------------------------------
proc BWidget::setglobal { varName value } {
    return [uplevel \#0 [list set $varName $value]]
}


# ----------------------------------------------------------------------------
#  Command BWidget::getglobal
# ----------------------------------------------------------------------------
proc BWidget::getglobal { varName } {
    return [uplevel \#0 [list set $varName]]
}


# ----------------------------------------------------------------------------
#  Command BWidget::traceglobal
# ----------------------------------------------------------------------------
proc BWidget::traceglobal { cmd varName args } {
    return [uplevel \#0 [list trace $cmd $varName] $args]
}



# ----------------------------------------------------------------------------
#  Command BWidget::lreorder
# ----------------------------------------------------------------------------
proc BWidget::lreorder { list neworder } {
    set pos     0
    set newlist {}
    foreach e $neworder {
        if { [lsearch -exact $list $e] != -1 } {
            lappend newlist $e
            set tabelt($e)  1
        }
    }
    set len [llength $newlist]
    if { !$len } {
        return $list
    }
    if { $len == [llength $list] } {
        return $newlist
    }
    set pos 0
    foreach e $list {
        if { ![info exists tabelt($e)] } {
            set newlist [linsert $newlist $pos $e]
        }
        incr pos
    }
    return $newlist
}


proc BWidget::lremove { list args } {
    foreach elem $args {
        set x [lsearch -exact $list $elem]     
        if {$x > -1} { set list [lreplace $list $x $x] }
    }
    return $list
}


proc BWidget::lassign { list args } {
    foreach elem $list varName $args {
        if {[string equal $varName ""]} { break }
        uplevel 1 [list set $varName $elem]
    }
}


# ----------------------------------------------------------------------------
#  Command BWidget::assert
# ----------------------------------------------------------------------------
proc BWidget::assert { exp {msg ""}} {
    set res [uplevel 1 expr $exp]
    if { !$res} {
        if { $msg == "" } {
            return -code error "Assertion failed: {$exp}"
        } else {
            return -code error $msg
        }
    }
}


# ----------------------------------------------------------------------------
#  Command BWidget::clonename
# ----------------------------------------------------------------------------
proc BWidget::clonename { menu } {
    set path     ""
    set menupath ""
    set found    0
    foreach widget [lrange [split $menu "."] 1 end] {
        if { $found || [winfo class "$path.$widget"] == "Menu" } {
            set found 1
            append menupath "#" $widget
            append path "." $menupath
        } else {
            append menupath "#" $widget
            append path "." $widget
        }
    }
    return $path
}


# ----------------------------------------------------------------------------
#  Command BWidget::getname
# ----------------------------------------------------------------------------
proc BWidget::getname { name } {
    if { [string length $name] } {
        set text [option get . "${name}Name" ""]
        if { [string length $text] } {
            return [parsetext $text]
        }
    }
    return {}
 }


# ----------------------------------------------------------------------------
#  Command BWidget::parsetext
# ----------------------------------------------------------------------------
proc BWidget::parsetext { text } {
    set result ""
    set index  -1
    set start  0
    while { [string length $text] } {
        set idx [string first "&" $text]
        if { $idx == -1 } {
            append result $text
            set text ""
        } else {
            set char [string index $text [expr {$idx+1}]]
            if { $char == "&" } {
                append result [string range $text 0 $idx]
                set    text   [string range $text [expr {$idx+2}] end]
                set    start  [expr {$start+$idx+1}]
            } else {
                append result [string range $text 0 [expr {$idx-1}]]
                set    text   [string range $text [expr {$idx+1}] end]
                incr   start  $idx
                set    index  $start
            }
        }
    }
    return [list $result $index]
}


# ----------------------------------------------------------------------------
#  Command BWidget::get3dcolor
# ----------------------------------------------------------------------------
proc BWidget::get3dcolor { path bgcolor {multiplier 0} {divideBy 100} } {
    set fmt "#%04x%04x%04x"

    if {$multiplier} {
        foreach val [winfo rgb $path $bgcolor] {
            lappend list [expr {$multiplier * $val / $divideBy}]
        }
        return [eval format $fmt $list]
    }

    if {[string equal $bgcolor "SystemButtonFace"]} {
        lappend list System3dDarkShadow SystemButtonHighlight
        lappend list SystemButtonShadow System3dLight
        return $list
    }

    foreach val [winfo rgb $path $bgcolor] {
        lappend dark  [expr {48 * $val / 100}]
        lappend dark2 [expr {72 * $val / 100}]

        set tmp1 [expr {14*$val/10}]
        if { $tmp1 > 65535 } { set tmp1 65535 }

        set tmp2 [expr {(65535+$val)/2}]
        lappend light  [expr {($tmp1 > $tmp2) ? $tmp1:$tmp2}]

        set tmp [expr {92 * $val / 90}]
        lappend light2 [expr {($tmp > 65535) ? 65535 : $tmp}]
    }

    lappend list [eval format $fmt $dark]
    lappend list [eval format $fmt $light]
    lappend list [eval format $fmt $dark2]
    lappend list [eval format $fmt $light2]

    return $list
}


proc BWidget::color2hex { path color } {
    if {[catch { winfo rgb $path $color } rgb]} {
	return -code error "Invalid color '$color'"
    }
    foreach {r g b} $rgb { break }
    return [format {#%4.4x%4.4x%4.4x} $r $g $b]
}


proc BWidget::getGradientColors { col1Str col2Str size {offset 0} } {
    if {[catch { winfo rgb . $col1Str } color1]} {
	return -code error "Invalid color '$col1Str'"
    }

    if {[catch { winfo rgb . $col2Str } color2]} {
	return -code error "Invalid color '$col2Str'"
    }

    set max [expr {$size - $offset}]

    foreach {r1 g1 b1} $color1 { break }
    foreach {r2 g2 b2} $color2 { break }
    set rRange [expr {double($r2) - $r1}]
    set gRange [expr {double($g2) - $g1}]
    set bRange [expr {double($b2) - $b1}]
    set rRatio [expr {$rRange / $max}]
    set gRatio [expr {$gRange / $max}]
    set bRatio [expr {$bRange / $max}]

    set colors [list]

    for {set i 0} {$i < $offset} {incr i} {
        lappend colors [format {#%4.4x%4.4x%4.4x} $r1 $g1 $b1]
    }

    for {set i 0} {$i < $max} {incr i} {
	set nR [expr {int( $r1 + ($rRatio * $i) )}]
	set nG [expr {int( $g1 + ($gRatio * $i) )}]
	set nB [expr {int( $b1 + ($bRatio * $i) )}]
        lappend colors [format {#%4.4x%4.4x%4.4x} $nR $nG $nB]
    }

    return $colors
}


# ----------------------------------------------------------------------------
#  Command BWidget::XLFDfont
# ----------------------------------------------------------------------------
proc BWidget::XLFDfont { cmd args } {
    switch -- $cmd {
        create {
            set font "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
        }
        configure {
            set font [lindex $args 0]
            set args [lrange $args 1 end]
        }
        default {
            return -code error "XLFDfont: command incorrect: $cmd"
        }
    }
    set lfont [split $font "-"]
    if { [llength $lfont] != 15 } {
        return -code error "XLFDfont: description XLFD incorrect: $font"
    }

    foreach {option value} $args {
        switch -- $option {
            -foundry { set index 1 }
            -family  { set index 2 }
            -weight  { set index 3 }
            -slant   { set index 4 }
            -size    { set index 7 }
            default  { return -code error "XLFDfont: option incorrect: $option" }
        }
        set lfont [lreplace $lfont $index $index $value]
    }
    return [join $lfont "-"]
}



# ----------------------------------------------------------------------------
#  Command BWidget::place
# ----------------------------------------------------------------------------
#
# Notes:
#  For Windows systems with more than one monitor the available screen area may
#  have negative positions. Geometry settings with negative numbers are used
#  under X to place wrt the right or bottom of the screen. On windows, Tk
#  continues to do this. However, a geometry such as 100x100+-200-100 can be
#  used to place a window onto a secondary monitor. Passing the + gets Tk
#  to pass the remainder unchanged so the Windows manager then handles -200
#  which is a position on the left hand monitor.
#  I've tested this for left, right, above and below the primary monitor.
#  Currently there is no way to ask Tk the extent of the Windows desktop in 
#  a multi monitor system. Nor what the legal co-ordinate range might be.
#
proc BWidget::place { path w h args } {
    update idletasks
    if {$w == 0} { set w [winfo reqwidth  $path] }
    if {$h == 0} { set h [winfo reqheight $path] }

    set arglen [llength $args]
    if { $arglen > 3 } {
        return -code error "BWidget::place: bad number of argument"
    }

    if { $arglen > 0 } {
        set where [lindex $args 0]
	set list  [list "at" "center" "left" "right" "above" "below"]
        set idx   [lsearch -exact $list $where]
        if { $idx == -1 } {
	    return -code error [BWidget::badOptionString position $where $list]
        }
        if { $idx == 0 } { ## at
            set err [catch {
                # purposely removed the {} around these expressions - [PT]
                set x [expr int([lindex $args 1])]
                set y [expr int([lindex $args 2])]
            }]
            if { $err } {
                return -code error "BWidget::place: incorrect position"
            }
            if {[string equal $::tcl_platform(platform) "windows"]} {
                # handle windows multi-screen. -100 != +-100
                if {[string index [lindex $args 1] 0] != "-"} {
                    set x "+$x"
                }
                if {[string index [lindex $args 2] 0] != "-"} {
                    set y "+$y"
                }
            } else {
                if { $x >= 0 } {
                    set x "+$x"
                }
                if { $y >= 0 } {
                    set y "+$y"
                }
            }
        } else {
            if { $arglen == 2 } {
                set widget [lindex $args 1]
                if { ![winfo exists $widget] } {
                    set msg "BWidget::place: \"$widget\" does not exist"
                    return -code error $msg
                }
	    } else {
		set widget .
	    }

            set sw    [winfo screenwidth  $path]
            set sh    [winfo screenheight $path]
            set rootx [winfo rootx $widget]
            set rooty [winfo rooty $widget]

            if { $idx == 1 } { ## center
                if { $arglen == 2 } {
                    # center to widget
                    set x0 [expr {$rootx + ([winfo width  $widget] - $w)/2}]
                    set y0 [expr {$rooty + ([winfo height $widget] - $h)/2}]
                } else {
                    # center to screen
                    set x0 [expr {($sw - $w)/2 - [winfo vrootx $path]}]
                    set y0 [expr {($sh - $h)/2 - [winfo vrooty $path]}]
                }
                set x "+$x0"
                set y "+$y0"
                if {$::tcl_platform(platform) != "windows"} {
                    if { $x0+$w > $sw } {set x "-0"; set x0 [expr {$sw-$w}]}
                    if { $x0 < 0 }      {set x "+0"}
                    if { $y0+$h > $sh } {set y "-0"; set y0 [expr {$sh-$h}]}
                    if { $y0 < 0 }      {set y "+0"}
                }
            } else {
                set x0 $rootx
                set y0 $rooty
                set x1 [expr {$x0 + [winfo width  $widget]}]
                set y1 [expr {$y0 + [winfo height $widget]}]
                if { $idx == 2 || $idx == 3 } { ## left or right
                    set y "+$y0"
                    if {$::tcl_platform(platform) != "windows"} {
                        if { $y0+$h > $sh } {set y "-0"; set y0 [expr {$sh-$h}]}
                        if { $y0 < 0 }      {set y "+0"}
                    }
                    if { $idx == 2 } {
                        # try left, then right if out, then 0 if out
                        if { $x0 >= $w } {
                            set x [expr {$x0-$sw}]
                        } elseif { $x1+$w <= $sw } {
                            set x "+$x1"
                        } else {
                            set x "+0"
                        }
                    } else {
                        # try right, then left if out, then 0 if out
                        if { $x1+$w <= $sw } {
                            set x "+$x1"
                        } elseif { $x0 >= $w } {
                            set x [expr {$x0-$sw}]
                        } else {
                            set x "-0"
                        }
                    }
                } else { ## above or below
                    set x "+$x0"
                    if {[string equal $::tcl_platform(platform) "windows"]} {
                        if { $x0+$w > $sw } {set x "-0"; set x0 [expr {$sw-$w}]}
                        if { $x0 < 0 }      {set x "+0"}
                    }
                    if { $idx == 4 } {
                        # try top, then bottom, then 0
                        if { $h <= $y0 } {
                            set y [expr {$y0-$sh}]
                        } elseif { $y1+$h <= $sh } {
                            set y "+$y1"
                        } else {
                            set y "+0"
                        }
                    } else {
                        # try bottom, then top, then 0
                        if { $y1+$h <= $sh } {
                            set y "+$y1"
                        } elseif { $h <= $y0 } {
                            set y [expr {$y0-$sh}]
                        } else {
                            set y "-0"
                        }
                    }
                }
            }
        }

        ## If there's not a + or - in front of the number, we need to add one.
        if {[string is integer [string index $x 0]]} { set x +$x }
        if {[string is integer [string index $y 0]]} { set y +$y }

        wm geometry $path "${w}x${h}${x}${y}"
    } else {
        wm geometry $path "${w}x${h}"
    }
    update idletasks
}


# ----------------------------------------------------------------------------
#  Command BWidget::grab
# ----------------------------------------------------------------------------
proc BWidget::grab { option path } {
    variable _gstack

    if { $option == "release" } {
        catch {::grab release $path}
        while { [llength $_gstack] } {
            set grinfo  [lindex $_gstack end]
            set _gstack [lreplace $_gstack end end]
            foreach {oldg mode} $grinfo {
                if { ![string equal $oldg $path] && [winfo exists $oldg] } {
                    if { $mode == "global" } {
                        catch {::grab -global $oldg}
                    } else {
                        catch {::grab $oldg}
                    }
                    return
                }
            }
        }
    } else {
        set oldg [::grab current]
        if { $oldg != "" } {
            lappend _gstack [list $oldg [::grab status $oldg]]
        }
        if { $option == "global" } {
            ::grab -global $path
        } else {
            ::grab $path
        }
    }
}


# ----------------------------------------------------------------------------
#  Command BWidget::focus
# ----------------------------------------------------------------------------
proc BWidget::focus { option path {refocus 1} } {
    variable _fstack

    if { $option == "release" } {
        while { [llength $_fstack] } {
            set oldf [lindex $_fstack end]
            set _fstack [lreplace $_fstack end end]
            if { ![string equal $oldf $path] && [winfo exists $oldf] } {
                if {$refocus} {catch {::focus -force $oldf}}
                return
            }
        }
    } elseif { $option == "set" } {
        lappend _fstack [::focus]
        ::focus -force $path
    }
}

# BWidget::refocus --
#
#	Helper function used to redirect focus from a container frame in 
#	a megawidget to a component widget.  Only redirects focus if
#	focus is already on the container.
#
# Arguments:
#	container	container widget to redirect from.
#	component	component widget to redirect to.
#
# Results:
#	None.

proc BWidget::refocus {container component} {
    if { [string equal $container [::focus]] } {
	::focus $component
    }
    return
}

## These mirror tk::(Set|Restore)FocusGrab

# BWidget::SetFocusGrab --
#   swap out current focus and grab temporarily (for dialogs)
# Arguments:
#   grab	new window to grab
#   focus	window to give focus to
# Results:
#   Returns nothing
#
proc BWidget::SetFocusGrab {grab {focus {}}} {
    variable _focusGrab
    set index "$grab,$focus"

    lappend _focusGrab($index) [::focus]
    set oldGrab [::grab current $grab]
    lappend _focusGrab($index) $oldGrab
    if {[winfo exists $oldGrab]} {
	lappend _focusGrab($index) [::grab status $oldGrab]
    }
    # The "grab" command will fail if another application
    # already holds the grab.  So catch it.
    catch {::grab $grab}
    if {[winfo exists $focus]} {
	::focus $focus
    }
}

# BWidget::RestoreFocusGrab --
#   restore old focus and grab (for dialogs)
# Arguments:
#   grab	window that had taken grab
#   focus	window that had taken focus
#   destroy	destroy|withdraw - how to handle the old grabbed window
# Results:
#   Returns nothing
#
proc BWidget::RestoreFocusGrab {grab focus {destroy destroy}} {
    variable _focusGrab
    set index "$grab,$focus"
    if {[info exists _focusGrab($index)]} {
	foreach {oldFocus oldGrab oldStatus} $_focusGrab($index) break
	unset _focusGrab($index)
    } else {
	set oldGrab ""
    }

    catch {::focus $oldFocus}
    ::grab release $grab
    if {[string equal $destroy "withdraw"]} {
	wm withdraw $grab
    } else {
	::destroy $grab
    }
    if {[winfo exists $oldGrab] && [winfo ismapped $oldGrab]} {
	if {[string equal $oldStatus "global"]} {
	    ::grab -global $oldGrab
	} else {
	    ::grab $oldGrab
	}
    }
}

# BWidget::badOptionString --
#
#	Helper function to return a proper error string when an option
#       doesn't match a list of given options.
#
# Arguments:
#	type	A string that represents the type of option.
#	value	The value that is in-valid.
#       list	A list of valid options.
#
# Results:
#	None.
proc BWidget::badOptionString { type value list } {
    set list [lsort $list]

    ## Make a special case for the -- option.  We always
    ## want that to go at the end of the list.
    set x [lsearch -exact $list "--"]
    if {$x > -1} {
        set list [lreplace $list $x $x]
        lappend list --
    }

    set last [lindex $list end]
    set list [lreplace $list end end]
    set msg  "bad $type \"$value\": must be "
    
    if {![llength $list]} {
        append msg "$last"
    } elseif {[llength $list] == 1} {
        append msg "$list or $last"
    } else {
        append msg "[join $list ", "], or $last"
    }
    
    return $msg
}


proc BWidget::wrongNumArgsString { string } {
    return "wrong # args: should be \"$string\""
}


proc BWidget::read_file { file } {
    set fp [open $file]
    set x  [read $fp [file size $file]]
    close $fp
    return $x
}


proc BWidget::classes { class } {
    variable use

    ${class}::use
    set classes [list $class]
    if {![info exists use($class)]} { return }
    foreach class $use($class) {
	eval lappend classes [classes $class]
    }
    return [lsort -unique $classes]
}


proc BWidget::library { args } {
    variable use

    set exclude [list]
    if {[set x [lsearch -exact $args "-exclude"]] > -1} {
        set exclude [lindex $args [expr {$x + 1}]]
        set args    [lreplace $args $x [expr {$x + 1}]]
    }

    set libs    [list widget init utils]
    set classes [list]
    foreach class $args {
	${class}::use
        foreach c [classes $class] {
            if {[lsearch -exact $exclude $c] > -1} { continue }
            lappend classes $c
        }
    }

    eval lappend libs [lsort -unique $classes]

    set library ""
    foreach lib $libs {
	if {![info exists use($lib,file)]} {
	    set file [file join $::BWIDGET::LIBRARY $lib.tcl]
	} else {
	    set file [file join $::BWIDGET::LIBRARY $use($lib,file).tcl]
	}
        append library [read_file $file]
    }

    return $library
}


proc BWidget::inuse { class } {
    variable ::Widget::_inuse

    if {![info exists _inuse($class)]} { return 0 }
    return [expr $_inuse($class) > 0]
}


proc BWidget::write { filename {mode w} } {
    variable use

    if {![info exists use(classes)]} { return }

    set classes [list]
    foreach class $use(classes) {
	if {![inuse $class]} { continue }
	lappend classes $class
    }

    set fp [open $filename $mode]
    puts $fp [eval library $classes]
    close $fp

    return
}


# BWidget::bindMouseWheel --
#
#	Bind mouse wheel actions to a given widget.
#
# Arguments:
#	widget - The widget to bind.
#
# Results:
#	None.
proc BWidget::bindMouseWheel { widgetOrClass } {
    bind $widgetOrClass <MouseWheel>         {
        if {![string equal [%W yview] "0 1"]} {
            %W yview scroll [expr {-%D/24}]  units
        }
    }

    bind $widgetOrClass <Shift-MouseWheel>   {
        if {![string equal [%W yview] "0 1"]} {
            %W yview scroll [expr {-%D/120}] pages
        }
    }

    bind $widgetOrClass <Control-MouseWheel> {
        if {![string equal [%W yview] "0 1"]} {
            %W yview scroll [expr {-%D/120}] units
        }
    }

    bind $widgetOrClass <Button-4> {event generate %W <MouseWheel> -delta  120}
    bind $widgetOrClass <Button-5> {event generate %W <MouseWheel> -delta -120}
}


proc BWidget::Icon { name } {
    if {![Widget::exists $::BWidget::iconLibrary]} {
        BWidget::LoadBWidgetIconLibrary
    }

    return [$::BWidget::iconLibrary image $name]
}


proc BWidget::LoadBWidgetIconLibrary {} {
    if {![Widget::exists $::BWidget::iconLibrary]} {
        IconLibrary $::BWidget::iconLibrary -file $::BWidget::iconLibraryFile
    }
}


proc BWidget::CreateImage { gifdata pngdata args } {
    lappend args -format $::BWidget::imageFormat
    if {[BWidget::using png]} {
        lappend args -data $pngdata
    } else {
        lappend args -data $gifdata
    }

    return [eval image create photo $args]
}


proc BWidget::ParseArgs { _arrayName _arglist args } {
    upvar 1 $_arrayName array

    array set _args {
        -strict     0
        -options    {}
        -switches   {}
        -required   {}
        -nocomplain 0
    }
    array set _args $args
    if {[info exists _args(-errorvar)]} { upvar 1 $_args(-errorvar) error }

    set switches $_args(-switches)
    foreach switch $switches {
        set array([string range $switch 1 end]) 0
    }

    set options [list]
    foreach opt $_args(-options) {
        set option $opt
        if {[llength $opt] == 2} {
            set option [lindex $opt 0]
            set array([string range $option 1 end]) [lindex $opt 1]
        }
        lappend options $option
    }

    set array(OPTIONS)  [list]
    set array(SWITCHES) [list]

    set oplen   [llength $options]
    set swlen   [llength $switches]
    set index   0
    set waiting 0
    foreach arg $_arglist {
        switch -glob -- $arg {
            "--" {
                incr index
                break
            }

            "-*" {
                if {$waiting} {
                    set waiting 0
                    set array($option) $arg
                    lappend array(OPTIONS) -$option $arg
                    continue
                }

                    if {$swlen && [lsearch -exact $switches $arg] > -1} {
                        lappend array(SWITCHES) $arg
                        set array([string range $arg 1 end]) 1
                    } elseif {$oplen && [lsearch -exact $options $arg] < 0} {
                        if {$_args(-nocomplain)} { return 0 }
                        return -code error "unknown option \"$arg\""
                    } elseif {$_args(-strict)} {
                        ## Option didn't match a switch, and we're being strict.
                        set switches [concat -- $_args(-switches)]
                        set msg [BWidget::badOptionString option $arg $switches]
                        return -code error $msg
                    } else {
                        set waiting 1
                        set option [string range $arg 1 end]
                    }
                }

            default {
                if {$waiting} {
                    set waiting 0
                    set array($option) $arg
                    lappend array(OPTIONS) -$option $arg
                } else {
                    break
                }
            }
        }

        incr index
    }

    set array(_ARGS_) [lrange $_arglist $index end]

    if {[llength $_args(-required)]} {
        foreach arg [lsort -dict $_args(-required)] {
            if {![info exists array([string range $arg 1 end])]} {
                return -code error "missing required argument $arg"
            }
        }
    }

    return 1
}


proc BWidget::CopyBindings { from to } {
    foreach event [bind $from] {
        bind $to $event [bind $from $event]
    }
}


proc BWidget::DrawCanvasBorder { canvas relief color coords args } {
    lassign $coords x0 y0 x1 y1
    lassign [BWidget::get3dcolor $canvas $color] dark light dark2 light2

    switch -- $relief {
        "raised" - "sunken" {
            lappend lines [list $x0 $y1 $x0 $y0 $x1 $y0]
            lappend lines [list $x1 $y0 $x1 $y1 $x0 $y1]
            lappend lines [list \
                [expr {$x0 + 1}] [expr {$y1 - 2}] \
                [expr {$x0 + 1}] [expr {$y0 + 1}] \
                [expr {$x1 - 1}] [expr {$y0 + 1}]]
            lappend lines [list \
                [expr {$x0 + 1}] [expr {$y1 - 1}] \
                [expr {$x1 - 1}] [expr {$y1 - 1}] \
                [expr {$x1 - 1}] $y0]

            set colors [list $light $dark $light2 $dark2]
            if {[string equal $relief "sunken"]} {
                set colors [list $dark $light $dark2 $light2]
            }
        }

        "groove" - "ridge" {
            lappend lines [list \
                $x0 $y1 \
                $x1 $y1 \
                $x1 $y0 \
                $x1 [expr {$y0 + 1}] \
                [expr {$x0 + 1}] [expr {$y0 + 1}] \
                [expr {$x0 + 1}] $y1 \
            ]

            lappend lines [list \
                $x0 $y0 \
                [expr {$x1 - 1}] $y0 \
                [expr {$x1 - 1}] [expr {$y1 - 1}] \
                $x0 [expr {$y1 - 1}] \
                $x0 $y0 \
            ]

            set colors [list $light $dark2]
            if {[string equal $relief "ridge"]} {
                set colors [list $dark2 $light]
            }
        }

        "rounded" {
            set coords [list \
                [expr {$x0 + 1}] $y0 \
                [expr {$x1 - 1}] $y0 \
                $x1 [expr {$y0 + 1}] \
                $x1 [expr {$y1 - 1}] \
                [expr {$x1 - 1}] $y1 \
                [expr {$x0 + 1}] $y1 \
                $x0 [expr {$y1 - 1}] \
                $x0 [expr {$y0 + 1}] \
                [expr {$x0 + 1}] $y0 \
            ]

            set opts [list -outline $dark2 -fill $color]
            eval [list $canvas create poly $coords] $opts $args

            return
        }

        "highlight" {
            set opts [list -outline $dark -fill $light]
            eval [list $canvas create rect $coords] $opts $args

            set coords [list [incr x0] [incr y0] [incr x1 -1] [incr y1 -1]]
            eval [list $canvas create rect $coords -outline $dark2] $args

            return
        }
    }

    foreach line $lines color $colors {
        eval [list $canvas create line $line -fill $color] $args
    }
}

proc ::BWidget::FadeWindowIn { top {increment 0.08} {current 0} } {
    if {[tk windowingsystem] eq "x11"
        || ![package vsatisfies [info patchlevel] 8.4.8]} {
        wm deiconify $top
        return
    }

    if {$current == 0} {
        wm attributes $top -alpha [set current 0.01]
	wm deiconify $top
    }

    set current [expr {$current + $increment}]

    if {$current < 1.0} {
        wm attributes $top -alpha $current
        update idletasks

        after 10 [list BWidget::FadeWindowIn $increment $current]
    } else {
	wm attributes $top -alpha 0.99999
    }
}

proc ::BWidget::FadeWindowOut { top {destroy 0} {increment 0.08} {current 0} } {
    if {![winfo exists $top]} { return }

    if {[tk windowingsystem] eq "x11"
        || ![package vsatisfies [info patchlevel] 8.4.8]} {
        if {$destroy} {
            destroy $top
        } else {
            wm withdraw $top
        }
        return
    }

    if {$current == 0} {
	set current [wm attributes $top -alpha]
    }

    set current [expr {$current - $increment}]

    if {$current >= .01} {
        wm attributes $top -alpha $current
        update idletasks

        after 10 [list BWidget::FadeWindowOut $top $destroy $increment $current]
    } else {
        if {$destroy} {
            destroy $top
        } else {
	    wm withdraw   $top
	    wm attributes $top -alpha 0.99999
        }
    }
}
Added lib/BWidget/widget.tcl.








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
# ----------------------------------------------------------------------------
#  widget.tcl
#  This file is part of Unifix BWidget Toolkit
#  $Id: widget.tcl,v 1.27 2003/10/28 05:03:17 damonc Exp $
# ----------------------------------------------------------------------------
#  Index of commands:
#
#   Public Commands:
#     - Widget::tkinclude
#     - Widget::bwinclude
#     - Widget::declare
#     - Widget::addmap
#     - Widget::init
#     - Widget::destroy
#     - Widget::setoption
#     - Widget::configure
#     - Widget::cget
#     - Widget::subcget
#     - Widget::hasChanged
#     - Widget::options
#
#   Private Commands:
#     - Widget::_get_tkwidget_options
#     - Widget::_test_tkresource
#     - Widget::_test_bwresource
#     - Widget::_test_synonym
#     - Widget::_test_string
#     - Widget::_test_flag
#     - Widget::_test_enum
#     - Widget::_test_int
#     - Widget::_test_boolean
# ----------------------------------------------------------------------------
# Each megawidget gets a namespace of the same name inside the Widget namespace
# Each of these has an array opt, which contains information about the 
# megawidget options.  It maps megawidget options to a list with this format:
#     {optionType defaultValue isReadonly {additionalOptionalInfo}}
# Option types and their additional optional info are:
#	TkResource	{genericTkWidget genericTkWidgetOptionName}
#	BwResource	{nothing}
#	Enum		{list of enumeration values}
#	Int		{Boundary information}
#	Boolean		{nothing}
#	String		{nothing}
#	Flag		{string of valid flag characters}
#	Synonym		{nothing}
#	Color		{nothing}
#
# Next, each namespace has an array map, which maps class options to their
# component widget options:
#	map(-foreground) => {.e -foreground .f -foreground}
#
# Each has an array ${path}:opt, which contains the value of each megawidget
# option for a particular instance $path of the megawidget, and an array
# ${path}:mod, which stores the "changed" status of configuration options.

# Steps for creating a bwidget megawidget:
# 1. parse args to extract subwidget spec
# 2. Create frame with appropriate class and command line options
# 3. Get initialization options from optionDB, using frame
# 4. create subwidgets

# Uses newer string operations
package require Tcl 8.1.1

namespace eval Widget {
    variable _class
    variable _tk_widget

    ## This controls whether we try to use themed widgets from Ttk.
    variable _theme 0

    variable  _optiontype
    array set _optiontype {
        TkResource Widget::_test_tkresource
        BwResource Widget::_test_bwresource
        Enum       Widget::_test_enum
        Int        Widget::_test_int
        Boolean    Widget::_test_boolean
        Boolean2   Widget::_test_boolean2
        String     Widget::_test_string
        Flag       Widget::_test_flag
        Synonym    Widget::_test_synonym
        Color      Widget::_test_color
        Color2     Widget::_test_color2
        Padding    Widget::_test_padding
    }

    proc use {} {}
}


proc Widget::CreateTempWidget { class {command frame} } {
    set class [string map [list :: ""] $class]
    set path  ".#BWidget.#Class#$class"
    if {![winfo exists .#BWidget]} { frame .#BWidget }
    if {![winfo exists $path]} {
        if {[string equal $command "frame"]
            || [string equal $command "toplevel"]} {
            $command $path -class $class
            if {[string equal $command "toplevel"]} { wm withdraw $path }
        } else {
            $command $path
        }
    }
    return $path
}


# ----------------------------------------------------------------------------
#  Command Widget::tkinclude
#     Includes tk widget resources to BWidget widget.
#  class      class name of the BWidget
#  tkwidget   tk widget to include
#  subpath    subpath to configure
#  args       additionnal args for included options
# ----------------------------------------------------------------------------
proc Widget::tkinclude { class tkwidget subpath args } {
    foreach {cmd lopt} $args {
        # cmd can be
        #   include      options to include            lopt = {opt ...}
        #   remove       options to remove             lopt = {opt ...}
        #   rename       options to rename             lopt = {opt newopt ...}
        #   prefix       options to prefix             lopt = {pref opt opt ..}
        #   initialize   set default value for options lopt = {opt value ...}
        #   readonly     set readonly flag for options lopt = {opt flag ...}
        switch -- $cmd {
            remove {
                foreach option $lopt {
                    set remove($option) 1
                }
            }

            include {
                foreach option $lopt {
                    set include($option) 1
                }
            }

            prefix {
                set prefix [lindex $lopt 0]
                foreach option [lrange $lopt 1 end] {
                    set rename($option) "-$prefix[string range $option 1 end]"
                }
            }

            rename - readonly - initialize {
                array set $cmd $lopt
            }

            default {
                return -code error "invalid argument \"$cmd\""
            }
        }
    }

    namespace eval $class {}
    upvar 0 ${class}::opt classopt
    upvar 0 ${class}::map classmap
    upvar 0 ${class}::map$subpath submap
    upvar 0 ${class}::optionExports exports
    upvar 0 ${class}::subpaths subpaths

    if {![info exists subpaths($subpath)]} { set subpaths($subpath) [list] }
    eval [list lappend subpaths($subpath)] [array get initialize]

    set widg [Widget::CreateTempWidget $tkwidget $tkwidget]
    # create resources informations from tk widget resources
    foreach optdesc [_get_tkwidget_options $tkwidget] {
        set option [lindex $optdesc 0]

        if {[info exists remove($option)]} { continue }
        if {[info exists include] && ![info exists include($option)]} {continue}

        if {[llength $optdesc] == 3} {
            # option is a synonym
            set syn [lindex $optdesc 1]
            if {![info exists remove($syn)]} {
                # original option is not removed
                if {[info exists rename($syn)]} {
                    set classopt($option) [list Synonym $rename($syn)]
                } else {
                    set classopt($option) [list Synonym $syn]
                }
            }

            continue
        }

        set ro      0
        set value   [lindex $optdesc 1]
        set realopt $option

        if {[info exists rename($option)]} {
            set realopt $option
            set option  $rename($option)
        }

        if {[info exists readonly($option)]} {
            set ro $readonly($option)
        }

        set optionval [list $tkwidget $realopt]
        set classopt($option) [list TkResource $value $ro $optionval]

        if {![info exists initialize($option)]} {
            set conf    [_configure_option $option ""]
            set dbName  [lindex $conf 0]
            set dbClass [lindex $conf 1]

            set def [option get $widg $dbName $dbClass]
            if {[string length $def]} {
                set value $def
                lappend subpaths($subpath) $option $value
            }
        }

        # Add an option database entry for this option
        #set optionDbName ".[lindex [_configure_option $option ""] 0]"
        #if {![string equal $subpath ":cmd"]} {
            #set optionDbName "$subpath$optionDbName"
        #}
        #option add *${class}$optionDbName $value widgetDefault
        #lappend exports($option) "$optionDbName"

        # Store the forward and backward mappings for this
        # option <-> realoption pair
        lappend classmap($option) $subpath "" $realopt
        set submap($realopt) $option
    }
}


# ----------------------------------------------------------------------------
#  Command Widget::bwinclude
#     Includes BWidget resources to BWidget widget.
#  class    class name of the BWidget
#  subclass BWidget class to include
#  subpath  subpath to configure
#  args     additionnal args for included options
# ----------------------------------------------------------------------------
proc Widget::bwinclude { class subclass subpath args } {
    upvar 0 ${subclass}::opt subclassopt

    foreach {cmd lopt} $args {
        # cmd can be
        #   include      options to include          lopt = {opt ...}
        #   remove       options to remove           lopt = {opt ...}
        #   rename       options to rename           lopt = {opt newopt ...}
        #   prefix       options to prefix           lopt = {prefix opt opt ...}
        #   initialize   set default value for options lopt = {opt value ...}
        #   readonly     set readonly flag for options lopt = {opt flag ...}
        switch -- $cmd {
            remove {
                foreach option $lopt {
                    set remove($option) 1
                }
            }

            include {
                foreach option $lopt {
                    set include($option) 1
                }
            }

            prefix {
                set prefix   [lindex $lopt 0]
                set options  [lrange $lopt 1 end]
                set doremove [string equal [lindex $options 0] "remove"]
                if {![llength $options] || $doremove} {
                    set options  [list]
                    set toremove [lrange $options 1 end]
                    foreach option [array names subclassopt] {
                        if {[lsearch -exact $toremove $option] < 0} {
                            lappend options $option
                        }
                    }
                }

                foreach option $options {
                    set rename($option) "-$prefix[string range $option 1 end]"
                }
            }

            rename - readonly - initialize {
                array set $cmd $lopt
            }

            default {
                return -code error "invalid argument \"$cmd\""
            }
        }
    }

    namespace eval $class {}
    upvar 0 ${class}::opt classopt
    upvar 0 ${class}::map classmap
    upvar 0 ${class}::map$subpath submap
    upvar 0 ${class}::optionExports exports
    upvar 0 ${subclass}::optionExports subexports
    upvar 0 ${class}::subpaths subpaths

    if {![info exists subpaths($subpath)]} { set subpaths($subpath) [list] }
    eval [list lappend subpaths($subpath)] [array get initialize]

    set path [Widget::CreateTempWidget $class]
    # create resources informations from BWidget resources
    foreach {option optdesc} [array get subclassopt] {
	set subOption $option

        if {[info exists remove($option)]} { continue }
        if {[info exists include] && ![info exists include($option)]} {continue}

        set type [lindex $optdesc 0]
        if {[string equal $type "Synonym"]} {
            # option is a synonym
            set syn [lindex $optdesc 1]
            if {![info exists remove($syn)]} {
                if {[info exists rename($syn)]} {
                    set classopt($option) [list Synonym $rename($syn)]
                } else {
                    set classopt($option) [list Synonym $syn]
                }
            }
            continue
        }

        set ro      [lindex $optdesc 2]
        set value   [lindex $optdesc 1]
        set realopt $option

        if {[info exists rename($option)]} {
            set realopt $option
            set option  $rename($option)
        }

        if {[info exists initialize($option)]} {
            set value $initialize($option)
        }

        if {[info exists readonly($option)]} {
            set ro $readonly($option)
        }

        if {![info exists initialize($option)]} {
            set conf    [_configure_option $option ""]
            set dbName  [lindex $conf 0]
            set dbClass [lindex $conf 1]

            set def [option get $path $dbName $dbClass]
            if {[string length $def]} {
                set value $def
                lappend subpaths($subpath) $option $value
            }
        }

        set classopt($option) [list $type $value $ro [lindex $optdesc 3]]

        # Add an option database entry for this option
        #foreach optionDbName $subexports($subOption) {
            #if {![string equal $subpath ":cmd"]} {
                #set optionDbName "$subpath$optionDbName"
            #}
            # Only add the option db entry if we are overriding the
            # normal widget default
            #if {[info exists initialize($option)]} {
                #option add *${class}$optionDbName $value widgetDefault
            #}
            #lappend exports($option) "$optionDbName"
        #}

        # Store the forward and backward mappings for this
        # option <-> realoption pair
        lappend classmap($option) $subpath $subclass $realopt
        set submap($realopt) $option
    }
}


# ----------------------------------------------------------------------------
#  Command Widget::declare
#    Declares new options to BWidget class.
# ----------------------------------------------------------------------------
proc Widget::declare { class optlist } {
    variable _optiontype

    namespace eval $class {}
    upvar 0 ${class}::opt classopt
    upvar 0 ${class}::optionExports exports
    upvar 0 ${class}::optionClass optionClass

    set path [Widget::CreateTempWidget $class]
    foreach optdesc $optlist {
        set option  [lindex $optdesc 0]
        set optdesc [lrange $optdesc 1 end]
        set type    [lindex $optdesc 0]

        if {![info exists _optiontype($type)]} {
            return -code error "invalid option type \"$type\""
        }

        if {[string equal $type "Synonym"]} {
            # test existence of synonym option
            set syn [lindex $optdesc 1]
            if {![info exists classopt($syn)]} {
                return -code error \
                    "unknow option \"$syn\" for Synonym \"$option\""
            }
            set classopt($option) [list Synonym $syn]
            continue
        }

        # all other resource may have default value, readonly flag and
        # optional arg depending on type
        set value [lindex $optdesc 1]
        set ro    [lindex $optdesc 2]
        set arg   [lindex $optdesc 3]

        ## Check the option database for this option.
        set conf    [_configure_option $option ""]
        set dbName  [lindex $conf 0]
        set dbClass [lindex $conf 1]
        set default [option get $path $dbName $dbClass]
        #if {[string length $default]} { set value $default }

        if {[string equal $type "BwResource"]} {
            # We don't keep BwResource. We simplify to type of sub BWidget
            set subclass    [lindex $arg 0]
            set realopt     [lindex $arg 1]
            if {![string length $realopt]} { set realopt $option }

            upvar 0 ${subclass}::opt subclassopt
            if {![info exists subclassopt($realopt)]} {
                return -code error "unknow option \"$realopt\""
            }

            set suboptdesc $subclassopt($realopt)
            if {![string length $value]} {
                # We initialize default value
                set value [lindex $suboptdesc 1]
            }

            set type [lindex $suboptdesc 0]
            set ro   [lindex $suboptdesc 2]
            set arg  [lindex $suboptdesc 3]
	    #set optionDbName ".[lindex [_configure_option $option ""] 0]"
	    #option add *${class}${optionDbName} $value widgetDefault
	    #set exports($option) $optionDbName
            set classopt($option) [list $type $value $ro $arg]
            continue
        }

        # retreive default value for TkResource
        if {[string equal $type "TkResource"]} {
            set tkwidget [lindex $arg 0]
	    set widg [Widget::CreateTempWidget $tkwidget $tkwidget]
            set realopt  [lindex $arg 1]
            if { ![string length $realopt] } {
                set realopt $option
            }
            set tkoptions [_get_tkwidget_options $tkwidget]
            if {![string length $value]} {
                # We initialize default value
		set ind [lsearch $tkoptions [list $realopt *]]
                set value [lindex [lindex $tkoptions $ind] end]
            }
	    #set optionDbName ".[lindex [_configure_option $option ""] 0]"
	    #option add *${class}${optionDbName} $value widgetDefault
	    #set exports($option) $optionDbName
            set classopt($option) [list TkResource $value $ro \
		    [list $tkwidget $realopt]]
	    set optionClass($option) [lindex [$widg configure $realopt] 1]
            continue
        }

        if {[string equal $type "Color"]} {
            if {[info exists ::BWidget::colors($value)]} {
                set value $::BWidget::colors($value)
            }
        }

	#set optionDbName ".[lindex [_configure_option $option ""] 0]"
	#option add *${class}${optionDbName} $value widgetDefault
	#set exports($option) $optionDbName

        # for any other resource type, we keep original optdesc
        set classopt($option) [list $type $value $ro $arg]
    }
}


proc Widget::define { class filename args } {
    variable _inuse
    variable ::BWidget::use

    proc ::${class}::use {} {}

    if {[set x [lsearch -exact $args "-classonly"]] > -1} {
	set args [lreplace $args $x $x]
    } else {
	interp alias {} ::${class} {} ${class}::create

        ## Define the basic cget and configure commands every
        ## widget should have.
        proc ::${class}::cget { path option } {
            return [Widget::cget $path $option]
        }

        proc ::${class}::configure { path args } {
            return [Widget::configure $path $args]
        }

        ## Bind the class to cleanup BWidget information
        ## when a BWidget is destroyed.
	bind $class <Destroy> [list Widget::destroy %W]
    }

    set _inuse($class) 0

    set use($class)      $args
    set use($class,file) $filename
    lappend use(classes) $class

    foreach class $args { ${class}::use }
}


proc Widget::create { class path {rename 1} } {
    if {$rename} { rename $path ::$path:cmd }
    set cmd "${class}::\$cmd"
    proc ::$path { cmd args } \
    	[subst {return \[eval \[linsert \$args 0 $cmd [list $path]\]\]}]
    return $path
}


# ----------------------------------------------------------------------------
#  Command Widget::addmap
# ----------------------------------------------------------------------------
proc Widget::addmap { class subclass subpath options } {
    upvar 0 ${class}::opt classopt
    upvar 0 ${class}::optionExports exports
    upvar 0 ${class}::optionClass optionClass
    upvar 0 ${class}::map classmap
    upvar 0 ${class}::map$subpath submap
    upvar 0 ${class}::subpaths subpaths

    if {![info exists subpaths($subpath)]} { set subpaths($subpath) [list] }

    foreach {option realopt} $options {
        if {![string length $realopt]} { set realopt $option }

	#set val [lindex $classopt($option) 1]
	#set optDb ".[lindex [_configure_option $realopt ""] 0]"
	#if { ![string equal $subpath ":cmd"] } {
	    #set optDb "$subpath$optDb"
	#}
	#option add *${class}${optDb} $val widgetDefault
	#lappend exports($option) $optDb

	# Store the forward and backward mappings for this
	# option <-> realoption pair
        lappend classmap($option) $subpath $subclass $realopt
	set submap($realopt) $option

        lappend subpaths($subpath) $realopt [lindex $classopt($option) 1]
    }
}


# ----------------------------------------------------------------------------
#  Command Widget::syncoptions
# ----------------------------------------------------------------------------
proc Widget::syncoptions { class subclass subpath options } {
    upvar 0 ${class}::sync classync
    upvar 0 ${class}::subpaths subpaths

    if {![info exists subpaths($subpath)]} { set subpaths($subpath) [list] }

    foreach {option realopt} $options {
        if {![string length $realopt]} { set realopt $option }
        set classync($option) [list $subpath $subclass $realopt]
    }
}


# ----------------------------------------------------------------------------
#  Command Widget::init
# ----------------------------------------------------------------------------
proc Widget::init { class path options {initFromODB 0} } {
    variable _inuse

    upvar 0 Widget::_optiontype opttype
    upvar 0 ${class}::opt classopt
    upvar 0 ${class}::map classmap
    upvar 0 ${class}::$path:opt  pathopt
    upvar 0 ${class}::$path:mod  pathmod
    upvar 0 ${class}::$path:init pathinit

    if {[info exists pathopt]} { unset pathopt }
    if {[info exists pathmod]} { unset pathmod }

    # We prefer to use the actual widget for option db queries, but if it
    # doesn't exist yet, do the next best thing:  create a widget of the
    # same class and use that.
    set fpath    $path
    set rdbclass [string map [list :: ""] $class]
    if {![winfo exists $path]} { set fpath [Widget::CreateTempWidget $class] }

    foreach {option optdesc} [array get classopt] {
        set pathmod($option) 0
	if {[info exists classmap($option)]} { continue }

        set type [lindex $optdesc 0]
        if {[string equal $type "Synonym"]} { continue }

        set alt ""
        if {[string equal $type "TkResource"]} {
            set alt [lindex [lindex $optdesc 3] 1]
        }

        set optdb [lindex [_configure_option $option $alt] 0]
        set def   [option get $fpath $optdb $rdbclass]
        if {[string length $def]} {
            set pathopt($option) $def
        } else {
            set pathopt($option) [lindex $optdesc 1]
        }
    }

    if {![info exists _inuse($class)]} { set _inuse($class) 0 }
    incr _inuse($class)

    set Widget::_class($path) $class

    if {$initFromODB} {
        array set pathopt $options
    } else {
        foreach {option value} $options {
            if {![info exists classopt($option)]} {
                unset pathopt
                unset pathmod
                return -code error "unknown option \"$option\""
            }

            set optdesc $classopt($option)
            set type    [lindex $optdesc 0]
            if {[string equal $type "Synonym"]} {
                set option  [lindex $optdesc 1]
                set optdesc $classopt($option)
                set type    [lindex $optdesc 0]
            }

            set arg [lindex $optdesc 3]
            set pathopt($option)  [$opttype($type) $option $value $arg]
            set pathinit($option) $pathopt($option)
        }
    }
}


# Widget::initFromODB --
#
#	Initialize a megawidgets options with information from the option
#	database and from the command-line arguments given.
#
# Arguments:
#	class	class of the widget.
#	path	path of the widget -- should already exist.
#	options	command-line arguments.
#
# Results:
#	None.

proc Widget::initFromODB { class path options } {
    Widget::init $class $path $options 1
}


# Bastien Chevreux (bach@mwgdna.com)
#
# copyinit performs basically the same job as init, but it uses a
#  existing template to initialize its values. So, first a perferct copy
#  from the template is made just to be altered by any existing options
#  afterwards.
# But this still saves time as the first initialization parsing block is
#  skipped.
# As additional bonus, items that differ in just a few options can be
#  initialized faster by leaving out the options that are equal.

# This function is currently used only by ListBox::multipleinsert, but other
#  calls should follow :)

# ----------------------------------------------------------------------------
#  Command Widget::copyinit
# ----------------------------------------------------------------------------
proc Widget::copyinit { class templatepath path options } {
    upvar 0 ${class}::opt classopt \
	    ${class}::$path:opt	 pathopt \
	    ${class}::$path:mod	 pathmod \
	    ${class}::$path:init pathinit \
	    ${class}::$templatepath:opt	 templatepathopt \
	    ${class}::$templatepath:mod	 templatepathmod \
	    ${class}::$templatepath:init templatepathinit

    if {[info exists pathopt]} { unset pathopt }
    if {[info exists pathmod]} { unset pathmod }

    # We use the template widget for option db copying, but it has to exist!
    array set pathmod  [array get templatepathmod]
    array set pathopt  [array get templatepathopt]
    array set pathinit [array get templatepathinit]

    set Widget::_class($path) $class
    foreach {option value} $options {
	if {![info exists classopt($option)]} {
	    unset pathopt
	    unset pathmod
	    return -code error "unknown option \"$option\""
	}

	set optdesc $classopt($option)
	set type    [lindex $optdesc 0]
	if {[string equal $type "Synonym"]} {
	    set option	[lindex $optdesc 1]
	    set optdesc $classopt($option)
	    set type	[lindex $optdesc 0]
	}

        set arg [lindex $optdesc 3]
	set pathopt($option)  [$Widget::_optiontype($type) $option $value $arg]
	set pathinit($option) $pathopt($option)
    }
}


# Widget::parseArgs --
#
#	Given a widget class and a command-line spec, cannonize and validate
#	the given options, and return a keyed list consisting of the 
#	component widget and its masked portion of the command-line spec, and
#	one extra entry consisting of the portion corresponding to the 
#	megawidget itself.
#
# Arguments:
#	class	  Widget class to parse for.
#	options	  Command-line spec.
#       errorOut  If true, an error will be thrown for invalid options.
#
# Results:
#	result	keyed list of portions of the megawidget and that segment of
#		the command line in which that portion is interested.
proc Widget::parseArgs { class options {errorOut 1} } {
    upvar 0 ${class}::opt classopt
    upvar 0 ${class}::map classmap

    foreach {option val} $options {
	if {![info exists classopt($option)]} {
            if {$errorOut} { return -code error "unknown option \"$option\"" }
            continue
	}

        set optdesc $classopt($option)
        set type    [lindex $optdesc 0]
        if {[string equal $type "Synonym"]} {
            set option  [lindex $optdesc 1]
            set optdesc $classopt($option)
            set type    [lindex $optdesc 0]
        }

	if {[string equal $type "TkResource"]} {
	    # Make sure that the widget used for this TkResource exists
	    Widget::_get_tkwidget_options [lindex [lindex $optdesc 3] 0]
	}

	set val [$Widget::_optiontype($type) $option $val [lindex $optdesc 3]]
		
	if {[info exists classmap($option)]} {
	    foreach {subpath subclass realopt} $classmap($option) {
		lappend maps($subpath) $realopt $val
	    }
	} else {
	    lappend maps($class) $option $val
	}
    }

    return [array get maps]
}


# Widget::initArgs --
#
#       Given a widget class and a command-line spec, setup the default
#       values for each subpath of the widget with the initial values we
#       stored when creating the class.  Then, parse the arguments and
#       append any further command-line arguments to overwrite the initial
#       values.  Store the results in the given arrayName.
#
# Arguments:
#	class	   Widget class to parse for.
#	options	   Command-line spec.
#       arrayName  Array to store the maps.
#
# Results:
#       Empty string

proc Widget::initArgs { class options arrayName } {
    upvar 1 $arrayName maps
    upvar 0 ${class}::subpaths subpaths

    ## Setup empty lists for each subpath.
    array set maps [list $class {} :cmd {}]
    foreach subpath [array names subpaths] {
        set maps($subpath) [list]
    }
    
    ## Setup the array with the default values for each subpath
    array set maps [array get subpaths]

    ## Parse the arguments and append them to our array.
    foreach {var val} [Widget::parseArgs $class $options] {
        eval lappend maps($var) $val
    }
}


# Widget::splitArgs --
#
#       Given multiple widget classes and a list of arguments, parse
#       the arguments and set each class with the list of arguments
#       that pertain to it.  Any argument that exists in none of the
#       given classes will simply be lost in the returned array map.
#
#       Note: This proc does not return an error for invalid arguments.
#
# Arguments: options class ?class ...?
#	options	  Command-line spec.
#	class	  Widget class to parse for.
#
# Results:
#       A map of classes to options.

proc Widget::splitArgs { options args } {
    array set maps [list :cmd {}]
    foreach class $args {
        if {![info exists maps($class)]} { set maps($class) [list] }
        array set maps [Widget::parseArgs $class $options 0]
    }

    return [array get maps]
}


# Widget::optionExists --
#
#       Determine whether a given option exists for a given class.
#
# Arguments:
#       class    Widget class.
#       option   Widget option.
#
# Results:
#       True if the option exists for the class, false otherwise.
proc Widget::optionExists { class option } {
    return [info exists ${class}::opt($option)]
}


# Widget::class --
#
#       Return the class of a given widget.
#
# Arguments:
#       path    Widget name.
#
# Results:
#       The class name of the widget.
proc Widget::class { path } {
    if {[info exists Widget::_class($path)]} { return $Widget::_class($path) }
    return -code error "unknown widget $path"
}


# ----------------------------------------------------------------------------
#  Command Widget::destroy
# ----------------------------------------------------------------------------
proc Widget::destroy { path {unsetVariables 1} } {
    variable _class
    variable _inuse

    if {[info exists _class($path)]} {
        set class $_class($path)

        if {[info exists _inuse($class)]} { incr _inuse($class) -1 }

        if {![string equal [info commands $path] ""]} { rename $path "" }

        ## Unset the variables that all widgets use.
        foreach x {opt mod init} {
            if {[info exists ${class}::$path:$x]} {
                unset ${class}::$path:$x
            }
        }

        ## Unset any other variables used in this widget.
        if {$unsetVariables} { eval unset [info vars ${class}::$path:*] }

        unset _class($path)
    }
}


# ----------------------------------------------------------------------------
#  Command Widget::configure
# ----------------------------------------------------------------------------
proc Widget::configure { path options } {
    set len [llength $options]
    if {$len < 2} { return [_get_configure $path $options] }
    if {$len % 2} { return -code error "incorrect number of arguments" }

    variable _class
    variable _optiontype

    set class $_class($path)
    upvar 0 ${class}::opt  classopt
    upvar 0 ${class}::map  classmap
    upvar 0 ${class}::$path:opt pathopt
    upvar 0 ${class}::$path:mod pathmod

    set window [_get_window $class $path]
    foreach {option value} $options {
        if {![info exists classopt($option)]} {
            return -code error "unknown option \"$option\""
        }

        set optdesc $classopt($option)
        set type    [lindex $optdesc 0]
        if {[string equal $type "Synonym"]} {
            set option  [lindex $optdesc 1]
            set optdesc $classopt($option)
            set type    [lindex $optdesc 0]
        }

        ## If the option is read-only just skip it.
        if {[lindex $optdesc 2]} { continue }

        set newval [$_optiontype($type) $option $value [lindex $optdesc 3]]

        if {[info exists classmap($option)]} {
            set window [_get_window $class $window]
            foreach {subpath subclass realopt} $classmap($option) {
                if {[string length $subclass]} {
                    set curval [${subclass}::cget $window$subpath $realopt]
                    ${subclass}::configure $window$subpath $realopt $newval
                } else {
                    set curval [$window$subpath cget $realopt]
                    $window$subpath configure $realopt $newval
                }
            }
        } else {
            set curval $pathopt($option)
            set pathopt($option) $newval
        }

        set pathmod($option) [expr {![string equal $newval $curval]}]
    }

    return
}


# ----------------------------------------------------------------------------
#  Command Widget::cget
# ----------------------------------------------------------------------------
proc Widget::cget { path option } {
    if {![info exists ::Widget::_class($path)]} {
        return -code error "unknown widget \"$path\""
    }

    set class $::Widget::_class($path)
    if {![info exists ${class}::opt($option)]} {
        return -code error "unknown option \"$option\""
    }

    set optdesc [set ${class}::opt($option)]
    set type    [lindex $optdesc 0]
    if {[string equal $type "Synonym"]} {
        set option [lindex $optdesc 1]
    }

    if {[info exists ${class}::map($option)]} {
	foreach {subpath subclass realopt} [set ${class}::map($option)] {break}
	set path "[_get_window $class $path]$subpath"
	return [$path cget $realopt]
    }
    upvar 0 ${class}::$path:opt pathopt
    set pathopt($option)
}


# ----------------------------------------------------------------------------
#  Command Widget::subcget
# ----------------------------------------------------------------------------
proc Widget::subcget { path subwidget } {
    set class $::Widget::_class($path)
    upvar 0 ${class}::$path:opt pathopt
    upvar 0 ${class}::map$subwidget submap
    upvar 0 ${class}::$path:init pathinit

    set result [list]
    foreach realopt [array names submap] {
	if {[info exists pathinit($submap($realopt))]} {
	    lappend result $realopt $pathopt($submap($realopt))
	}
    }
    return $result
}


# ----------------------------------------------------------------------------
#  Command Widget::hasChanged
# ----------------------------------------------------------------------------
proc Widget::hasChanged { path option varName } {
    upvar 1 $varName value
    Widget::getVariable $path mod pathmod

    set value   [Widget::cget $path $option]
    set result  $pathmod($option)
    set pathmod($option) 0

    return $result
}

proc Widget::hasChangedX { path option args } {
    set class $::Widget::_class($path)
    upvar 0 ${class}::$path:mod pathmod

    set result  $pathmod($option)
    set pathmod($option) 0
    foreach option $args {
	lappend result $pathmod($option)
	set pathmod($option) 0
    }

    set result
}


proc Widget::anyChangedX { path args } {
    set class $::Widget::_class($path)
    upvar 0 ${class}::$path:mod pathmod

    set result 0
    foreach option $args {
        incr result $pathmod($option)
        set pathmod($option) 0
    }
    return $result
}


# Widget::getoption --
#
#	Bypass the superfluous checks in cget and just directly peer at the
#	widget's data space.  This is much more fragile than cget, so it 
#	should only be used with great care, in places where speed is critical.
#
# Arguments:
#	path	widget to lookup options for.
#	option	option to retrieve.
#
# Results:
#	value	option value.
proc Widget::getoption { path option } {
    set class $::Widget::_class($path)
    upvar 0 ${class}::${path}:opt pathopt
    set pathopt($option)
}


# Widget::setoption --
#
#	Bypass the superfluous checks in cget and just directly poke at the
#	widget's data space.  This is much more fragile than configure, so it 
#	should only be used with great care, in places where speed is critical.
#
# Arguments:
#	path	widget to lookup options for.
#	option	option to retrieve.
#	value	option value.
#
# Results:
#	value	option value.
proc Widget::setoption { path args } {
    set class $::Widget::_class($path)
    upvar 0 ${class}::${path}:opt pathopt
    foreach [list option value] $args {
        set pathopt($option) $value
    }
}


# Widget::getMegawidgetOption -- (deprecated -- use Widget::getoption)
#
#	Bypass the superfluous checks in cget and just directly peer at the
#	widget's data space.  This is much more fragile than cget, so it 
#	should only be used with great care, in places where speed is critical.
#
# Arguments:
#	path	widget to lookup options for.
#	option	option to retrieve.
#
# Results:
#	value	option value.
proc Widget::getMegawidgetOption { path option } {
    set class $::Widget::_class($path)
    upvar 0 ${class}::${path}:opt pathopt
    set pathopt($option)
}


# Widget::setMegawidgetOption -- (deprecated -- use Widget::setoption)
#
#	Bypass the superfluous checks in cget and just directly poke at the
#	widget's data space.  This is much more fragile than configure, so it 
#	should only be used with great care, in places where speed is critical.
#
# Arguments:
#	path	widget to lookup options for.
#	option	option to retrieve.
#	value	option value.
#
# Results:
#	value	option value.
proc Widget::setMegawidgetOption { path option value } {
    set class $::Widget::_class($path)
    upvar 0 ${class}::${path}:opt pathopt
    set pathopt($option) $value
}


# ----------------------------------------------------------------------------
#  Command Widget::_get_window
#  returns the window corresponding to widget path
# ----------------------------------------------------------------------------
proc Widget::_get_window { class path } {
    set idx [expr {[string last "#" $path] + 1}]
    if {$idx && [string equal [string range $path $idx end] $class]} {
        return [string range $path 0 [expr {$idx - 2}]]
    }
    return $path
}


# ----------------------------------------------------------------------------
#  Command Widget::_get_configure
#  returns the configuration list of options
#  (as tk widget do - [$w configure ?option?])
# ----------------------------------------------------------------------------
proc Widget::_get_configure { path options } {
    variable _class

    set class $_class($path)
    upvar 0 ${class}::opt classopt
    upvar 0 ${class}::$path:opt pathopt

    if {[llength $options] == 1} {
        ## Just return the option description for the one option.
        set option  [lindex $options 0]
        if { ![info exists classopt($option)] } {
            return -code error "unknown option \"$option\""
        }
        set optdesc $classopt($option)
        set type    [lindex $optdesc 0]
        if { [string equal $type "Synonym"] } {
            set option  [lindex $optdesc 1]
            set optdesc $classopt($option)
            set type    [lindex $optdesc 0]
        }
        if { [string equal $type "TkResource"] } {
            set alt [lindex [lindex $optdesc 3] 1]
        } else {
            set alt ""
        }

        set res [list $option]
        eval lappend res [_configure_option $option $alt]
        lappend res [lindex $optdesc 1] [${class}::cget $path $option]

        return $res
    }

    ## Return a list of option descriptions for all of the
    ## options for this widget.

    set result [list]
    foreach option [lsort [array names classopt]] {
        set alt     ""
        set syn     ""
        set optdesc $classopt($option)
        set type    [lindex $optdesc 0]

        if {[string equal $type "Synonym"]} {
            set syn     $option
            set option  [lindex $optdesc 1]
            set optdesc $classopt($option)
            set type    [lindex $optdesc 0]
        }

        if {[string equal $type "TkResource"]} {
            set alt [lindex [lindex $optdesc 3] 1]
        }

        set res [_configure_option $option $alt]
        if {![string length $syn]} {
            lappend result [concat $option $res \
                    [list [lindex $optdesc 1]] [list [cget $path $option]]]
        } else {
            lappend result [list $syn [lindex $res 0]]
        }
    }

    return $result
}


# ----------------------------------------------------------------------------
#  Command Widget::_configure_option
# ----------------------------------------------------------------------------
proc Widget::_configure_option { option altopt } {
    variable _optiondb
    variable _optionclass

    if {[info exists _optiondb($option)]} {
        set optdb $_optiondb($option)
    } else {
        set optdb [string range $option 1 end]
    }

    if {[info exists _optionclass($option)]} {
        set optclass $_optionclass($option)
    } elseif {[string length $altopt]} {
        if {[info exists _optionclass($altopt)]} {
            set optclass $_optionclass($altopt)
        } else {
            set optclass [string range $altopt 1 end]
        }
    } else {
        set optclass [string range $option 1 end]
    }

    return [list $optdb $optclass]
}


# ----------------------------------------------------------------------------
#  Command Widget::_get_tkwidget_options
# ----------------------------------------------------------------------------
proc Widget::_get_tkwidget_options { tkwidget } {
    variable _tk_widget
    variable _optiondb
    variable _optionclass
    
    if {![info exists _tk_widget($tkwidget)]} {
        set widget [Widget::CreateTempWidget $tkwidget $tkwidget]

	set config [$widget configure]
	foreach optlist $config {
	    set opt [lindex $optlist 0]
	    if {[llength $optlist] == 2} {
		set refsyn [lindex $optlist 1]

		# search for class
		set idx [lsearch $config [list * $refsyn *]]
		if {$idx == -1} {
		    if {[string index $refsyn 0] == "-"} {
			# search for option (tk8.1b1 bug)
			set idx [lsearch $config [list $refsyn * *]]
		    } else {
			# last resort
                        set refsyn [string tolower $refsyn]
			set idx [lsearch $config [list -$refsyn * *]]
		    }

		    if {$idx == -1} {
			# fed up with "can't read classopt()"
			return -code error "can't find option of synonym $opt"
		    }
		}

		set syn [lindex [lindex $config $idx] 0]
		# JDC: used 4 (was 3) to get def from optiondb
		set def [lindex [lindex $config $idx] 4]
		lappend _tk_widget($tkwidget) [list $opt $syn $def]
	    } else {
		# JDC: used 4 (was 3) to get def from optiondb
		set def [lindex $optlist 4]
		lappend _tk_widget($tkwidget) [list $opt $def]
		set _optiondb($opt)    [lindex $optlist 1]
		set _optionclass($opt) [lindex $optlist 2]
	    }
	}
    }

    return $_tk_widget($tkwidget)
}


# ----------------------------------------------------------------------------
#  Command Widget::_test_tkresource
# ----------------------------------------------------------------------------
proc Widget::_test_tkresource { option value arg } {
    set tkwidget [lindex $arg 0]
    set realopt  [lindex $arg 1]
    set path     [Widget::CreateTempWidget $tkwidget $tkwidget]
    set old      [$path cget $realopt]
    $path configure $realopt $value
    set res      [$path cget $realopt]
    $path configure $realopt $old
    return $res
}


# ----------------------------------------------------------------------------
#  Command Widget::_test_bwresource
# ----------------------------------------------------------------------------
proc Widget::_test_bwresource { option value arg } {
    return -code error "bad option type BwResource in widget"
}


# ----------------------------------------------------------------------------
#  Command Widget::_test_synonym
# ----------------------------------------------------------------------------
proc Widget::_test_synonym { option value arg } {
    return -code error "bad option type Synonym in widget"
}

# ----------------------------------------------------------------------------
#  Command Widget::_test_color
# ----------------------------------------------------------------------------
proc Widget::_test_color { option value arg } {
    ## Check to see if this is a BWidget named color.
    if {[info exists ::BWidget::colors($value)]} {
        set value $::BWidget::colors($value)
    }

    if {[catch {winfo rgb . $value} color]} {
        return -code error \
            "bad $option value \"$value\": must be a colorname or #RRGGBB"
    }

    return $value
}


proc Widget::_test_color2 { option value arg } {
    if {![string length $value]} { return }

    ## Check to see if this is a BWidget named color.
    if {[info exists ::BWidget::colors($value)]} {
        set value $::BWidget::colors($value)
    }

    if {[catch {winfo rgb . $value} color]} {
        return -code error \
            "bad $option value \"$value\": must be a colorname or #RRGGBB"
    }

    return $value
}


# ----------------------------------------------------------------------------
#  Command Widget::_test_string
# ----------------------------------------------------------------------------
proc Widget::_test_string { option value arg } {
    return $value
}


# ----------------------------------------------------------------------------
#  Command Widget::_test_flag
# ----------------------------------------------------------------------------
proc Widget::_test_flag { option value arg } {
    set len [string length $value]
    set res ""
    for {set i 0} {$i < $len} {incr i} {
        set c [string index $value $i]
        if {[string first $c $arg] == -1} {
            set name [string range $option 1 end]
            return -code error [BWidget::badOptionString $name $value $arg]
        }
        if {[string first $c $res] == -1} { append res $c }
    }
    return $res
}


# -----------------------------------------------------------------------------
#  Command Widget::_test_enum
# -----------------------------------------------------------------------------
proc Widget::_test_enum { option value arg } {
    if {[lsearch -exact $arg $value] == -1} {
        set name [string range $option 1 end]
        return -code error [BWidget::badOptionString $name $value $arg]
    }
    return $value
}


# -----------------------------------------------------------------------------
#  Command Widget::_test_int
# -----------------------------------------------------------------------------
proc Widget::_test_int { option value arg } {
    set map [list %d $value]
    if {![string is int -strict $value]
        || ([string length $arg] && ![expr [string map $map $arg]])} {
        return -code error \
            "bad $option value \"$value\": must be integer ($arg)"
    }
    return $value
}


# -----------------------------------------------------------------------------
#  Command Widget::_test_boolean
# -----------------------------------------------------------------------------
proc Widget::_test_boolean { option value arg } {
    if {![string is boolean -strict $value]} {
        set name [string range $option 1 end]
        return -code error [BWidget::badOptionString $name $value boolean]
    }

    # Get the canonical form of the boolean value (1 for true, 0 for false)
    return [string is true $value]
}


# -----------------------------------------------------------------------------
#  Command Widget::_test_boolean2
#
# A Boolean2 can be either an empty string or a boolean value.
# -----------------------------------------------------------------------------
proc Widget::_test_boolean2 { option value arg } {
    if {![string is boolean $value]} {
        set name [string range $option 1 end]
        set opts [list empty boolean]
        return -code error [BWidget::badOptionString $name $value $opts]
    }

    # Get the canonical form of the boolean value (1 for true, 0 for false)
    if {[string length $value]} { return [string is true $value] }
}


# -----------------------------------------------------------------------------
#  Command Widget::_test_padding
# -----------------------------------------------------------------------------
proc Widget::_test_padding { option values arg } {
    set len [llength $values]
    if {$len < 1 || $len > 2} {
        return -code error \
            "bad pad value \"$values\": must be positive screen distance"
    }

    foreach value $values {
        set map [list %d $value]
        if {![string is int -strict $value]
            || ([string length $arg] && ![expr [string map $map $arg]])} {
            return -code error \
                "bad pad value \"$value\": must be positive screen distance"
        }
    }
    return $values
}


# Widget::_get_padding --
#
#       Return the requesting padding value for a padding option.
#
# Arguments:
#	path		Widget to get the options for.
#       option          The name of the padding option.
#	index		The index of the padding.  If the index is empty,
#                       the first padding value is returned.
#
# Results:
#	Return a numeric value that can be used for padding.
proc Widget::_get_padding { args } {
    if {[llength $args] == 2} {
        set padding [lindex $args 0]
        set index   [lindex $args 1]
    } elseif {[llength $args] == 3} {
        set path    [lindex $args 0]
        set option  [lindex $args 1]
        set index   [lindex $args 2]
        set padding [Widget::cget $path $option]
    }
    set val [lindex $padding $index]
    if {![string length $val]} { set val [lindex $padding 0] }
    return $val
}


# -----------------------------------------------------------------------------
#  Command Widget::focusNext
#  Same as tk_focusNext, but call Widget::focusOK
# -----------------------------------------------------------------------------
proc Widget::focusNext { w } {
    set cur $w
    while 1 {

	# Descend to just before the first child of the current widget.

	set parent $cur
	set children [winfo children $cur]
	set i -1

	# Look for the next sibling that isn't a top-level.

	while 1 {
	    incr i
	    if {$i < [llength $children]} {
		set cur [lindex $children $i]
		if {[winfo toplevel $cur] == $cur} {
		    continue
		} else {
		    break
		}
	    }

	    # No more siblings, so go to the current widget's parent.
	    # If it's a top-level, break out of the loop, otherwise
	    # look for its next sibling.

	    set cur $parent
	    if {[winfo toplevel $cur] == $cur} {
		break
	    }
	    set parent [winfo parent $parent]
	    set children [winfo children $parent]
	    set i [lsearch -exact $children $cur]
	}
	if {($cur == $w) || [focusOK $cur]} {
	    return $cur
	}
    }
}


# -----------------------------------------------------------------------------
#  Command Widget::focusPrev
#  Same as tk_focusPrev, but call Widget::focusOK
# -----------------------------------------------------------------------------
proc Widget::focusPrev { w } {
    set cur $w
    while 1 {

	# Collect information about the current window's position
	# among its siblings.  Also, if the window is a top-level,
	# then reposition to just after the last child of the window.
    
	if {[winfo toplevel $cur] == $cur}  {
	    set parent $cur
	    set children [winfo children $cur]
	    set i [llength $children]
	} else {
	    set parent [winfo parent $cur]
	    set children [winfo children $parent]
	    set i [lsearch -exact $children $cur]
	}

	# Go to the previous sibling, then descend to its last descendant
	# (highest in stacking order.  While doing this, ignore top-levels
	# and their descendants.  When we run out of descendants, go up
	# one level to the parent.

	while {$i > 0} {
	    incr i -1
	    set cur [lindex $children $i]
	    if {[winfo toplevel $cur] == $cur} {
		continue
	    }
	    set parent $cur
	    set children [winfo children $parent]
	    set i [llength $children]
	}
	set cur $parent
	if {($cur == $w) || [focusOK $cur]} {
	    return $cur
	}
    }
}


# ----------------------------------------------------------------------------
#  Command Widget::focusOK
#  Same as tk_focusOK, but handles -editable option and whole tags list.
# ----------------------------------------------------------------------------
proc Widget::focusOK { w } {
    set code [catch {$w cget -takefocus} value]
    if {$code == 1} { return 0 }

    if {!$code && [string length $value]} {
	if {$value == 0} {
	    return 0
	} elseif {$value == 1} {
	    return [winfo viewable $w]
	} else {
	    set value [uplevel \#0 $value $w]
            if {[string length $value]} { return $value }
        }
    }

    if {![winfo viewable $w]} { return 0 }

    set code [catch {$w cget -state} value]
    if {!$code && [string equal $value "disabled"]} { return 0 }

    set code [catch {$w cget -editable} value]
    if {!$code && $value == 0} { return 0 }

    set top [winfo toplevel $w]
    foreach tag [bindtags $w] {
        if {![string equal $tag $top]
            && ![string equal $tag "all"]
            && [string match *Key* [bind $tag]]} {
            return 1
        }
    }
    return 0
}


proc Widget::traverseTo { w } {
    set focus [focus]
    if {[string length $focus]} {
	event generate $focus <<TraverseOut>>
    }
    focus $w

    event generate $w <<TraverseIn>>
}


# Widget::varForOption --
#
#	Retrieve a fully qualified variable name for the option specified.
#	If the option is not one for which a variable exists, throw an error 
#	(ie, those options that map directly to widget options).
#
# Arguments:
#	path	megawidget to get an option var for.
#	option	option to get a var for.
#
# Results:
#	varname	name of the variable, fully qualified, suitable for tracing.

proc Widget::varForOption { path option } {
    variable _class
    variable _optiontype

    set class $_class($path)
    upvar 0 ${class}::$path:opt pathopt

    if {![info exists pathopt($option)]} {
	return -code error "unable to find variable for option \"$option\""
    }

    return ::Widget::${class}::$path:opt($option)
}


proc Widget::widgetVar { path varName } {
    set class $Widget::_class($path)
    return ::Widget::${class}::$path:$varName
}


# Widget::getVariable --
#
#       Get a variable from within the namespace of the widget.
#
# Arguments:
#	path		Megawidget to get the variable for.
#	varName		The variable name to retrieve.
#       newVarName	The variable name to refer to in the calling proc.
#
# Results:
#	Creates a reference to newVarName in the calling proc.
proc Widget::getVariable { path varName {newVarName ""} } {
    if {![string length $newVarName]} { set newVarName $varName }
    uplevel 1 [list upvar \#0 [Widget::widgetVar $path $varName] $newVarName]
}


# Widget::options --
#
#       Return a key-value list of options for a widget.  This can
#       be used to serialize the options of a widget and pass them
#       on to a new widget with the same options.
#
# Arguments:
#	path		Widget to get the options for.
#	args		A list of options.  If empty, all options are returned.
#
# Results:
#	Returns list of options as: -option value -option value ...
proc Widget::options { path args } {
    if {[llength $args]} {
        foreach option $args {
            lappend options [_get_configure $path $option]
        }
    } else {
        set options [_get_configure $path {}]
    }

    set result [list]
    foreach list $options {
        if {[llength $list] < 5} { continue }
        lappend result [lindex $list 0] [lindex $list end]
    }
    return $result
}


# Widget::getOption --
#
#	Given a list of widgets, determine which option value to use.
#	The widgets are given to the command in order of lowest to
#	highest.  Starting with the lowest widget, whichever one does
#	not match the default option value is returned as the value.
#	If all the widgets are default, we return the highest widget's
#	value.
#
# Arguments:
#	option		The option to check.
#	default		The default value.  If any widget in the list
#			does not match this default, its value is used.
#	args		A list of widgets.
#
# Results:
#	Returns the value of the given option to use.
#
proc Widget::getOption { option default args } {
    foreach widget $args {
	set value  [Widget::getoption $widget $option]
        if {$value != $default} { break }
    }
    return $value
}


proc Widget::cgetOption { option default args } {
    foreach widget $args {
	set value  [Widget::cget $widget $option]
        if {$value != $default} { break }
    }
    return $value
}


# Widget::nextIndex --
#
#       Given a widget path and a node name, substitute all occurrences
#       of #auto with the next index number for the path.
#
# Arguments:
#       path            The widget path.
#       node            The name of the node.
#
# Results:
#       Returns a string to use as the new name for the node.
#
proc Widget::nextIndex { path node } {
    Widget::getVariable $path autoIndex
    if {![info exists autoIndex]} { set autoIndex -1 }
    return [string map [list #auto [incr autoIndex]] $node]
}


# Widget::exists --
#
#       Determine if the given widget path exists in the BWidget system.
#
# Arguments:
#       path            The widget path.
#
# Results:
#       Returns boolean.
#
proc Widget::exists { path } {
    return [info exists ::Widget::_class($path)]
}


proc Widget::theme {{bool {}}} {
    # Private, *experimental* API that may change at any time - JH
    variable _theme
    if {[llength [info level 0]] == 2} {
        # set theme-ability
        if {[catch {package require tile 0.6}]
            && [catch {package require tile 1}]} {
            return -code error "BWidget's theming requires tile 0.6+"
        } else {
            catch {style default BWSlim.Toolbutton -padding 0}
        }
        set _theme [string is true -strict $bool]
    }
    return $_theme
}
Added lib/BWidget/wizard.tcl.




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
# ------------------------------------------------------------------------------
#  wizard.tcl
#
# ------------------------------------------------------------------------------
#  Index of commands:
#
#   Public commands
#     - Wizard::create
#     - Wizard::configure
#     - Wizard::cget
#
#   Private commands
#     - Wizard::_destroy
# ------------------------------------------------------------------------------

namespace eval Wizard {
    Widget::define Wizard wizard ButtonBox Separator

    namespace eval Step {
	Widget::declare Wizard::Step {
            {-background      Color2     ""       0  }
            {-backgroundimage String     ""       0  }
            {-type            String     "step"   1  }
	    {-data            String     ""       0  }
	    {-title           String     ""       0  }
	    {-default         String     "next"   0  }

	    {-text1           String     ""       0  }
	    {-text2           String     ""       0  }
	    {-text3           String     ""       0  }
	    {-text4           String     ""       0  }
	    {-text5           String     ""       0  }

	    {-icon            String     ""       0  }
	    {-image           String     ""       0  }

	    {-bitmap          String     ""       0  }
	    {-iconbitmap      String     ""       0  }

            {-createstep      Boolean2    ""      1  }
            {-appendorder     Boolean    "1"      0  }

            {-nexttext        String     ""       0  }
            {-backtext        String     ""       0  }
            {-helptext        String     ""       0  }
            {-canceltext      String     ""       0  }
            {-finishtext      String     ""       0  }
            {-separatortext   String     ""       0  }

            {-separator       Boolean2   ""       0  }

            {-command         String     ""       0  }

            {-createcommand   String     ""       0  }
            {-raisecommand    String     ""       0  }
	    {-nextcommand     String     ""       0  }
	    {-backcommand     String     ""       0  }
	    {-helpcommand     String     ""       0  }
	    {-cancelcommand   String     ""       0  }
	    {-finishcommand   String     ""       0  }

            {-compoundraise   Boolean    "1"      0  }
            {-compoundcreate  Boolean    "1"      0  }

            {-bg              Synonym    -background }
	}
    }

    namespace eval Branch {
	Widget::declare Wizard::Branch {
            {-type            String     "branch" 1  }
            {-command         String     ""       0  }
            {-action          Enum       "merge"  0  {merge terminate} }
        }
    }

    namespace eval Widget {
	Widget::declare Wizard::Widget {
            {-type            String     "widget" 1  }
            {-step            String     ""       1  }
            {-widget          String     ""       1  }
	}
    }

    namespace eval layout {}

    Widget::tkinclude Wizard frame :cmd \
    	include    { -background -foreground -cursor }

    Widget::declare Wizard {
   	{-type            Enum       "dialog" 1 {dialog frame} }
   	{-width           TkResource "0"      0 frame}
	{-height          TkResource "0"      0 frame}
   	{-minwidth        Int        "475"    0 "%d >= 0"}
	{-minheight       Int        "350"    0 "%d >= 0"}
	{-relief          TkResource "flat"   0 frame}
	{-borderwidth     TkResource "0"      0 frame}
	{-background      Color      "SystemButtonFace" 0}
	{-foreground      String     "#000000" 0      }
        {-backgroundimage String     ""       0      }
	{-title           String     "Wizard" 0      }
	{-createstep      Boolean    "0"      0      }

        {-showbuttons     Boolean    "1"      1      }
	{-autobuttons     Boolean    "1"      0      }
	{-helpbutton      Boolean    "0"      1      }
	{-finishbutton    Boolean    "0"      1      }
        {-resizable       String     "0 0"    0      }
	{-separator       Boolean    "1"      1      }
        {-parent          String     "."      1      }
        {-transient       Boolean    "1"      1      }
        {-place           Enum       "center" 1
                                     {none center left right above below} }

        {-icon            String     ""       0      }
        {-image           String     ""       0      }

	{-bitmap          String     ""       0      }
	{-iconbitmap      String     ""       0      }

        {-raisecommand    String     ""       0      }
        {-createcommand   String     ""       0      }

	{-buttonwidth     Int        "12"     0      }
        {-nexttext        String     "Next >" 0      }
        {-backtext        String     "< Back" 0      }
        {-helptext        String     "Help"   0      }
        {-canceltext      String     "Cancel" 0      }
        {-finishtext      String     "Finish" 0      }
        {-separatortext   String     ""       0      }

        {-fg              Synonym    -foreground     }
        {-bg              Synonym    -background     }
        {-bd              Synonym    -borderwidth    }
    }

    image create photo Wizard::none

    style layout ImageFrame {Label.label -sticky nesw}

    Widget::addmap Wizard "" :cmd { -background {} -relief {} -borderwidth {} }

    bind Wizard <Destroy> [list Wizard::_destroy %W]
}


# ------------------------------------------------------------------------------
#  Command Wizard::create
# ------------------------------------------------------------------------------
proc Wizard::create { path args } {
    Widget::initArgs Wizard $args maps

    Widget::initFromODB Wizard $path $maps(Wizard)

    Widget::getVariable $path data
    Widget::getVariable $path branches

    array set data {
        steps   ""
        buttons ""
        order   ""
	current ""
    }

    array set branches {
        root    ""
    }

    set frame $path

    set type [Widget::getoption $path -type]

    if {[string equal $type "dialog"]} {
        set top $path
        eval [list toplevel $path -bg $::BWidget::colors(SystemButtonFace)] \
            $maps(:cmd) -class Wizard
        wm withdraw   $path
        update idletasks
        wm protocol   $path WM_DELETE_WINDOW [list $path cancel 1]
        if {[Widget::getoption $path -transient]} {
	    wm transient  $path [Widget::getoption $path -parent]
        }
        eval wm resizable $path [Widget::getoption $path -resizable]

	set minwidth  [Widget::getoption $path -minwidth]
	set minheight [Widget::getoption $path -minheight]
	wm minsize $path $minwidth $minheight

        set width  [Widget::cget $path -width]
        set height [Widget::cget $path -height]
	if {$width > 0 && $height > 0} {
	    wm geometry $top ${width}x${height}
	}

        bind $path <Escape>         [list $path cancel]
        bind $path <<WizardFinish>> [list destroy $path]
        bind $path <<WizardCancel>> [list destroy $path]
    } else {
        set top [winfo toplevel $path]
        eval [list frame $path] $maps(:cmd) -class Wizard
    }

    wm title $top [Widget::getoption $path -title]

    grid rowconfigure    $top 0 -weight 1
    grid columnconfigure $top 0 -weight 1

    frame $path.steps
    grid  $path.steps -row 0 -column 0 -sticky news

    grid rowconfigure    $path.steps 0 -weight 1
    grid columnconfigure $path.steps 0 -weight 1

    widget $path set steps -widget $path.steps

    if {[Widget::getoption $path -separator]} {
        frame $path.separator
        grid  $path.separator -row 1 -column 0 -sticky ew -pady [list 5 0]

        grid columnconfigure $path.separator 1 -weight 1

        set text [Widget::getoption $path -separatortext]

        if {[BWidget::using ttk]} {
            ttk::label $path.separator.l -state disabled -text $text
        } else {
            label $path.separator.l -bd 0 -pady 0 -state disabled -text $text
        }

        grid  $path.separator.l -row 0 -column 0 -sticky w -padx 2

        Separator $path.separator.s -orient horizontal
        grid $path.separator.s -row 0 -column 1 -sticky ew \
            -padx [list 0 5] -pady 4

	widget $path set separator      -widget $path.separator.s
	widget $path set separatortext  -widget $path.separator.l
	widget $path set separatorframe -widget $path.separator
    }

    if {[Widget::getoption $path -showbuttons]} {
        ButtonBox $path.buttons -spacing 2 -homogeneous 1
        grid $path.buttons -row 2 -column 0 -sticky e -padx 5 -pady {10 5}

        widget $path set buttons -widget $path.buttons

        Wizard::insert $path button end back -text "< Back" \
            -command [list $path back 1] \
            -width [Widget::getoption $path -buttonwidth]
        Wizard::insert $path button end next -text "Next >" \
            -command [list $path next 1]
        if {[Widget::getoption $path -finishbutton]} {
            Wizard::insert $path button end finish -text "Finish" \
                -command [list $path finish 1]
        }
        Wizard::insert $path button end cancel -text "Cancel" \
            -command [list $path cancel 1] -spacing 10

        if {[Widget::getoption $path -helpbutton]} {
            Wizard::insert $path button 0 help -text "Help" \
                -command [list $path help 1] -spacing 10
        }
    }

    return [Widget::create Wizard $path]
}


# ------------------------------------------------------------------------------
#  Command Wizard::configure
# ------------------------------------------------------------------------------
proc Wizard::configure { path args } {
    set res [Widget::configure $path $args]

    if {[Widget::hasChanged $path -title title]} {
	wm title [winfo toplevel $path] $title
    }

    if {[Widget::hasChanged $path -resizable resize]} {
	eval wm resizable [winfo toplevel $path] $resize
    }

    if {[Widget::getoption $path -separator]
        && [Widget::hasChanged $path -separatortext text]} {
        set text [Wizard::getoption $path [Wizard::raise $path] -separatortext]
        Wizard::itemconfigure $path separatortext -text $text
    }

    if {[Widget::anyChangedX $path -width -height -minwidth -minheight]} {
        set type    [Widget::getoption $path -type]
        set width   [Widget::cget $path -width]
        set height  [Widget::cget $path -height]
	set mwidth  [Widget::getoption $path -minwidth]
	set mheight [Widget::getoption $path -minheight]

        if {[string equal $type "dialog"]} {
	    wm minsize $path $mwidth $mheight

	    if {$width > 0 && $height > 0} {
		wm geometry $top ${width}x${height}
	    }

        } else {
            $path:cmd configure -width $width -height $height
        }
    }

    return $res
}


# ------------------------------------------------------------------------------
#  Command Wizard::cget
# ------------------------------------------------------------------------------
proc Wizard::cget { path option } {
    return [Widget::cget $path $option]
}


proc Wizard::itemcget { path item option } {
    Widget::getVariable $path items
    Widget::getVariable $path steps
    Widget::getVariable $path buttons
    Widget::getVariable $path widgets

    if {[Wizard::_is_step $path $item]} {
        ## It's a step.
        return [Widget::cget $items($item) $option]
    }

    if {[Wizard::_is_branch $path $item]} {
        ## It's a branch.
        return [Widget::cget $items($item) $option]
    }

    if {[Wizard::_is_button $path $item]} {
        ## It's a button.
        return [$path.buttons itemcget $items($item) $option]
    }

    if {[Wizard::_is_widget $path $item]} {
	## It's a widget.
	return [eval [$path widget get $item] cget $option] 
    }

    return -code error "item \"$item\" does not exist"
}


proc Wizard::itemconfigure { path item args } {
    Widget::getVariable $path items
    Widget::getVariable $path steps
    Widget::getVariable $path buttons

    if {[Wizard::_is_step $path $item]} {
        ## It's a step.
        set i $items($item)
        set res [Widget::configure $i $args]

	## Do some more configuration if the step we're configuring
	## is the step that is currently raised.
	if {$item eq [Wizard::step $path current]} {
	    if {[Widget::hasChanged $i -title title]} {
		set title [Wizard::getoption $path $item -title]
		wm title [winfo toplevel $path] $title
	    }

            if {[winfo exists $path.separator]} {
                if {[Widget::getoption $path -separator]
                    && [Widget::hasChanged $i -separator separator]} {
                    if {[Wizard::getoption $path $item -separator]} {
                        grid $path.separator.s
                    } else {
                        grid remove $path.separator.s
                    }
                }

                if {[Widget::getoption $path -separator]
                    && [Widget::hasChanged $i -separatortext text]} {
                    set text [Wizard::getoption $path $item -separatortext]
                    Wizard::itemconfigure $path separatortext -text $text
                }
            }

	    set x [list -nexttext -backtext -canceltext -helptext -finishtext]
            if {[eval [list Widget::anyChangedX $path] $x]} {
                Wizard::adjustbuttons $path
            }
	}

	return $res
    }

    if {[Wizard::_is_branch $path $item]} {
        ## It's a branch.
        return [Widget::configure $items($item) $args]
    }

    if {[Wizard::_is_button $path $item]} {
        ## It's a button.
        return [eval $path.buttons itemconfigure [list $items($item)] $args]
    }

    if {[Wizard::_is_widget $path $item]} {
        ## It's a widget.
	return [eval [Wizard::widget $path get $item] configure $args] 
    }

    return -code error "item \"$item\" does not exist"
}


proc Wizard::show { path } {
    wm deiconify [winfo toplevel $path]
}


proc Wizard::hide { path } {
    wm withdraw [winfo toplevel $path]
}


proc Wizard::invoke { path button } {
    Widget::getVariable $path buttons
    if {![info exists buttons($button)]} {
        return -code error "button \"$button\" does not exist"
    }
    [Wizard::widget $path get $button] invoke
}


proc Wizard::insert { path type idx args } {
    switch -- $type {
        "button" {
            set node [lindex $args 0]
            set node [Widget::nextIndex $path $node]
            set args [lreplace $args 0 0 $node]
        }

        "step" - "branch" {
            set node   [lindex $args 1]
            set branch [lindex $args 0]
            set node   [Widget::nextIndex $path $node]
            set args   [lreplace $args 1 1 $node]

            if {![Wizard::_is_branch $path $branch]} {
                return -code error "branch \"$branch\" does not exist"
            }
	}

	default {
	    set types [list button branch step]
	    set err [BWidget::badOptionString option $type $types]
	    return -code error $err
	}
    }

    if {[Wizard::exists $path $node]} {
        return -code error "item \"$node\" already exists"
    }

    eval _insert_$type $path $idx $args

    return $node
}


proc Wizard::delete { path args } {
    Widget::getVariable $path data
    Widget::getVariable $path items
    Widget::getVariable $path steps
    Widget::getVariable $path buttons
    Widget::getVariable $path widgets
    Widget::getVariable $path branches

    set step [Wizard::step $path current]
    foreach item $args {
        set item [Wizard::step $path $item]
        if {![string length $item]} { continue }

        if {[Wizard::_is_step $path $item]} {
            ## It's a step

            set branch [Wizard::branch $path $item]
            set x [lsearch -exact $branches($branch) $item]
            set branches($branch) [lreplace $branches($branch) $x $x]

            destroy $widgets($item)

            Widget::destroy $items($item) 0

            unset steps($item)
            unset data($item,branch)
            unset items($item)
            unset widgets($item)

            if {[info exists data($item,realized)]} {
                unset data($item,realized)
            }

            if {$item eq $step} { set data(current) "" }
        }

        if {[Wizard::_is_branch $path $item]} {
            ## It's a branch

            set branch [Wizard::branch $path $item]
            set x [lsearch -exact $branches($branch) $item]
            set branches($branch) [lreplace $branches($branch) $x $x]

            Widget::destroy $items($item) 0

            unset branches($item)
            unset data($item,branch)
            unset items($item)
        }

        if {[info exists buttons($item)]} {
            ## It's a button

            set x [$path.buttons index $widgets($item)]
            $path.buttons delete $x

            unset items($item)
            unset buttons($item)
            unset widgets($item)
        }
    }
}


proc Wizard::back { path {generateEvent 0} {executeCommand 1} } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    set step [Wizard::raise $path]

    if {$executeCommand && [string length $step]} {
        set cmd [Widget::getoption $items($step) -backcommand]
        if {![_eval_command $path $cmd]} { return }
    }

    ## The -backcommand could have decided to move us
    ## somewhere else in the wizard.  If we're not on
    ## the same step we were before the command, stop.
    if {$step ne [Wizard::raise $path]} { return }

    set idx [lsearch -exact $data(order) $step]
    if {$idx < 0} {
        set item [lindex $data(order) end]
    } else {
        set item [lindex $data(order) [expr {$idx - 1}]]
        set data(order) [lreplace $data(order) $idx end]
    }

    Wizard::raise $path $item $generateEvent

    if {$generateEvent} { event generate $path <<WizardBack>> }

    return $item
}


proc Wizard::next { path {generateEvent 0} {executeCommand 1} } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    set step [Wizard::raise $path]

    if {$executeCommand && [string length $step]} {
        set cmd [Widget::getoption $items($step) -nextcommand]
        if {![_eval_command $path $cmd]} { return }
    }

    ## The -nextcommand could have decided to move us
    ## somewhere else in the wizard.  If we're not on
    ## the same step we were before the command, stop.
    if {$step ne [Wizard::raise $path]} { return }

    set item [Wizard::step $path next]
    if {![string length $item]} { return }

    if {[Widget::getoption $items($item) -appendorder]} {
	lappend data(order) $item
    }

    Wizard::raise $path $item $generateEvent

    if {$generateEvent} { event generate $path <<WizardNext>> }

    return $item
}


proc Wizard::cancel { path {generateEvent 0} {executeCommand 1} } {
    Widget::getVariable $path items

    set step [Wizard::raise $path]

    if {$executeCommand && [string length $step]} {
        set cmd [Widget::getoption $items($step) -cancelcommand]
        if {![_eval_command $path $cmd]} { return }
    }

    if {$generateEvent} { event generate $path <<WizardCancel>> }
}


proc Wizard::finish { path {generateEvent 0} {executeCommand 1} } {
    Widget::getVariable $path items

    set step [Wizard::raise $path]

    if {$executeCommand && [string length $step]} {
        set cmd [Widget::getoption $items($step) -finishcommand]
        if {![_eval_command $path $cmd]} { return }
    }
        
    if {$generateEvent} { event generate $path <<WizardFinish>> }
}


proc Wizard::help { path {generateEvent 0} {executeCommand 1} } {
    Widget::getVariable $path items

    set step [Wizard::raise $path]

    if {$executeCommand && [string length $step]} {
        set cmd [Widget::getoption $items($step) -helpcommand]
        if {![_eval_command $path $cmd]} { return }
    }
        
    if {$generateEvent} { event generate $path <<WizardHelp>> }
}


proc Wizard::order { path args } {
    Widget::getVariable $path data
    if {[llength $args] > 1} {
        set err [BWidget::wrongNumArgsString "$path order ?neworder?"]
        return -code error $err
    }
    if {[llength $args]} { set data(order) [lindex $args 0] }
    return $data(order)
}


proc Wizard::step { path node {start ""} {traverse 1} } {
    Widget::getVariable $path data
    Widget::getVariable $path items
    Widget::getVariable $path branches

    if {[string length $start] && ![info exists items($start)]} {
        return -code error "item \"$start\" does not exist"
    }

    switch -- $node {
        "current" {
            set item [Wizard::raise $path]
        }

        "end" - "last" {
            ## Keep looping through 'next' until we hit the end.
            set item [Wizard::step $path next]
            while {[string length $item]} {
                set last $item
                set item [Wizard::step $path next $item] 
            }
            set item $last
        }

        "back" - "previous" {
            if {![string length $start]} { set start [Wizard::raise $path] }

            set idx [lsearch -exact $data(order) $start]
            if {$idx < 0} {
                set item [lindex $data(order) end]
            } else {
                incr idx -1
                if {$idx < 0} { return }
                set item [lindex $data(order) $idx]
            }
        }

        "next" {
            if {[string length $start]} {
                set step $start
            } else {
                set step [Wizard::raise $path]
            }

            set branch [Wizard::branch $path $step]
            if {$traverse && [Wizard::_is_branch $path $step]} {
                ## This step is a branch.  Let's figure out where to go next.
                if {[Wizard::traverse $path $step]} {
                    ## It's ok to traverse into this branch.
                    set branch $step
                }
            }

            set idx [expr {[lsearch -exact $branches($branch) $step] + 1}]

            if {$idx >= [llength $branches($branch)]} {
                ## We've reached the end of this branch.
                ## If it's the root branch or this branch terminates we return.
                if {$branch eq "root"
                    || [Widget::getoption $items($branch) -action]
                        eq "terminate"} {
                    return
                }

                ## We want to merge back with our parent branch.
                set item [Wizard::step $path next $branch 0]
            } else {
                set item [lindex $branches($branch) $idx]

                ## If this step is a branch, find the next step after it.
                if {[Wizard::_is_branch $path $item]} {
                    if {$traverse} {
                        set item [Wizard::step $path next $item]
                    }
                } else {
                    ## Check the -command of this step and see if
                    ## we want to display it.  If not skip ahead.
                    if {![Wizard::traverse $path $item]} {
                        set item [Wizard::step $path next $item]
                    }
                }
            }
        }

        default {
            set item ""

            ## If this node is a branch, we want to keep
            ## looking util we find the next available step.
            if {[Wizard::_is_branch $path $node]} {
                return [Wizard::step $path next $node]
            }

            if {[Wizard::_is_step $path $node]} { set item $node }
        }
    }

    return $item
}


proc Wizard::nodes { path branch {first ""} {last ""} } {
    Widget::getVariable $path data
    Widget::getVariable $path branches
    if {![string length $first]} { return $branches($branch) }
    if {![string length $last]}  { return [lindex $branches($branch) $first] }
    return [lrange $branches($branch) $first $last]
}


proc Wizard::index { path item } {
    Widget::getVariable $path branches
    set item   [$path step $item]
    set branch [$path branch $item]
    return [lsearch -exact $branches($branch) $item]
}


proc Wizard::raise { path {item ""} {generateEvent 0} } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    set steps   $path.steps
    set buttons $path.buttons

    if {[string equal $item ""]} { return $data(current) }

    set x $item
    set curr $data(current)
    set item [Wizard::step $path $item]

    if {![string length $item]} {
        return -code error "step \"$x\" does not exist"
    }

    if {[string equal $item $data(current)]} { return }

    Wizard::createstep $path $item

    ## Eval the global raisecommand.
    if {[Widget::getoption $items($item) -compoundraise]} {
        set cmd [Widget::getoption $path -raisecommand]
        Wizard::_eval_command $path $cmd $item
    }

    ## If the $data(current) does not equal $curr, it means
    ## that the -raisecommand has moved us to another pane
    ## before finishing this action.  We need to stop.
    if {$data(current) ne $curr} { return $data(current) }

    ## Eval this item's raisecommand.
    set cmd [Widget::getoption $items($item) -raisecommand]
    Wizard::_eval_command $path $cmd $item

    ## If the $data(current) does not equal $curr, it means
    ## that the -raisecommand has moved us to another pane
    ## before finishing this action.  We need to stop.
    if {$data(current) ne $curr} { return $data(current) }

    wm title [winfo toplevel $path] [Wizard::getoption $path $item -title]

    if {[winfo exists $path.separator]} {
        if {[Wizard::getoption $path $item -separator]} {
            grid $path.separator.s
            set text [Wizard::getoption $path $item -separatortext]
            $path itemconfigure separatortext -text $text
        } else {
            grid remove $path.separator.s
            $path itemconfigure separatortext -text ""
        }
    }

    if {[winfo exists $path.buttons]} {
        set default [Widget::getoption $items($item) -default]
        set button  [lsearch -exact $data(buttons) $default]
        $buttons setfocus $button
    }

    if {[string length $data(current)]} {
        grid remove $steps.f$data(current)
    }

    set data(current) $item

    grid $steps.f$data(current) -row 0 -column 0 -sticky news

    set back [Wizard::step $path back]
    set next [Wizard::step $path next]

    if {[Widget::getoption $path -autobuttons]} { Wizard::adjustbuttons $path }

    set bgimage [Wizard::getoption $path $item -backgroundimage]
    if {$bgimage ne ""} {
        $steps.f$item configure -image $bgimage
    }

    if {$generateEvent} {
        if {$back eq ""} { event generate $path <<WizardFirstStep>> }
        if {$next eq ""} { event generate $path <<WizardLastStep>> }
        event generate $path <<WizardStep>>
    }

    return $item
}


proc Wizard::adjustbuttons { path } {
    Widget::getVariable $path items

    if {![Widget::getoption $path -showbuttons]} { return }

    set item [Wizard::step $path current]
    if {[string equal $item ""]} { return }

    set back [Wizard::step $path back]
    set next [Wizard::step $path next]

    foreach x [list back next cancel] {
        set text [Wizard::getoption $path $item -${x}text]
        $path itemconfigure $x -text $text -state normal
    }

    if {[Widget::getoption $path -helpbutton]} {
        set text [Wizard::getoption $path $item -helptext]
	$path itemconfigure help -text $text
    }

    if {[Widget::getoption $path -finishbutton]} {
        set text [Wizard::getoption $path $item -finishtext]
	$path itemconfigure finish -text $text -state disabled
    }

    if {[string equal $back ""]} {
	$path itemconfigure back -state disabled
    }

    if {[string equal $next ""]} {
	if {[Widget::getoption $path -finishbutton]} {
	    $path itemconfigure next   -state disabled
	    $path itemconfigure finish -state normal
	} else {
            set text [Wizard::getoption $path $item -finishtext]
	    $path itemconfigure next -text $text -command [list $path finish 1]
	}
	$path itemconfigure back   -state disabled
	$path itemconfigure cancel -state disabled
    } else {
        set text [Wizard::getoption $path $item -nexttext]
	$path itemconfigure next -text $text -command [list $path next 1]
    }
}


proc Wizard::widget { path command args } {
    return [eval [list Wizard::widgets $path $command] $args]
}


proc Wizard::widgets { path command args } {
    Widget::getVariable $path items
    Widget::getVariable $path widgets
    Widget::getVariable $path stepWidgets

    switch -- $command {
	"set" {
	    set node [lindex $args 0]
	    if {[string equal $node ""]} {
                set str "$path widget set <name> ?option ..?"
		set err [BWidget::wrongNumArgsString $str]
		return -code error $err
	    }
	    set args [lreplace $args 0 0]
	    set item $path.#widget#$node

	    Widget::init Wizard::Widget $item $args
	    set step   [Widget::getoption $item -step]
	    set widget [Widget::getoption $item -widget]
            set items($node) $item
	    if {[string equal $step ""]} {
		set widgets($node) $widget
	    } else {
		set stepWidgets($step,$node) $widget
	    }
	    return $widget
	}

	"get" {
	    set widget [lindex $args 0]
            if {[string equal [string index $widget 0] "-"]} {
                set widget ""
            } else {
                set args [lreplace $args 0 0]
            }

	    array set map  [list Wizard::Widget {}]
	    array set map  [Widget::parseArgs Wizard::Widget $args]
	    array set data $map(Wizard::Widget)

	    if {[info exists data(-step)]} {
	    	set step $data(-step)

                ## If we weren't given a widget, just return a
                ## list of all the widgets in this step.
                if {[string equal $widget ""]} {
                    set list [list]
                    foreach name [array names stepWidgets $step,*] {
                        set x [lrange [split $name ,] 1 end]
                        lappend list [eval join $x ,]
                    }
                    return $list
                }
	    } else {
                ## If we weren't given a widget, just return all
                ## of the global widgets.
                if {[string equal $widget ""]} {
                    return [array names widgets]
                }

		set step [$path step current]
	    }

	    ## If a widget exists for this step, return it.
	    if {[info exists stepWidgets($step,$widget)]} {
		return $stepWidgets($step,$widget)
	    }

	    ## See if a widget exists on the global level.
	    if {![info exists widgets($widget)]} {
		return -code error "item \"$widget\" does not exist"
	    }

	    return $widgets($widget)
	}

	default {
	    set err [BWidget::badOptionString option $command [list get set]]
	    return -code error $err
	}
    }
}


proc Wizard::variable { path step option } {
    set item [step $path $step]
    if {[string equal $item ""]} {
        return -code error "item \"$step\" does not exist"
    }
    set item $path.$item
    return [Widget::varForOption $item $option]
}


proc Wizard::branch { path {node "current"} } {
    Widget::getVariable $path data

    if {[_is_branch $path $node]} { return $data($node,branch) }

    set node [$path step $node]
    if {[string equal $node ""]} { return "root" }
    if {[info exists data($node,branch)]} { return $data($node,branch) }
    return -code error "item \"$node\" does not exist"
}


proc Wizard::traverse { path node } {
    Widget::getVariable $path items

    if {$node eq "root"} { return 1 }

    if {![info exists items($node)]} {
        return -code error "node \"$node\" does not exist"
    }

    set cmd [Widget::getoption $items($node) -command]
    return [_eval_command $path $cmd]
}


proc Wizard::exists { path item } {
    Widget::getVariable $path items
    return [info exists items($item)]
}


proc Wizard::createstep { path item {delete 0} } {
    Widget::getVariable $path data
    Widget::getVariable $path items

    set item [Wizard::step $path $item]

    if {![Wizard::_is_step $path $item]} { return }

    if {$delete} {
        if {[winfo exists $path.f$item]} {
            destroy $path.f$item
        }
        if {[info exists data($item,realized)]} {
            unset data($item,realized)
        }
    }

    if {![info exists data($item,realized)]} {
        set data($item,realized) 1

        if {[Widget::getoption $items($item) -compoundcreate]} {
            ## Eval the global createcommand.
            set cmd [Widget::getoption $path -createcommand]
            _eval_command $path $cmd $item
        }

        ## Eval this item's createcommand.
        set cmd [Widget::getoption $items($item) -createcommand]
        _eval_command $path $cmd $item
    }

    return $item
}


proc Wizard::getoption { path item option } {
    Widget::getVariable $path items
    set step [Wizard::step $path $item]
    if {![string length $step]} {
        return -code error "item \"$item\" does not exist"
    }
    return [Widget::cgetOption $option "" $items($step) $path]
}


proc Wizard::reorder { path parent nodes } {
    Widget::getVariable $path branches
    set branches($parent) $nodes
    if {[Widget::getoption $path -autobuttons]} { Wizard::adjustbuttons $path }
}


proc Wizard::_insert_button { path idx node args } {
    Widget::getVariable $path data
    Widget::getVariable $path items
    Widget::getVariable $path buttons
    Widget::getVariable $path widgets

    set buttons($node) 1
    set widgets($node) [eval $path.buttons insert $idx $args]
    set item   [string map [list $path.buttons.b {}] $widgets($node)]
    set items($node) $item
    return $widgets($node)
}


proc Wizard::_insert_step { path idx branch node args } {
    Widget::getVariable $path data
    Widget::getVariable $path steps
    Widget::getVariable $path items
    Widget::getVariable $path widgets
    Widget::getVariable $path branches

    set steps($node) 1
    set data($node,branch) $branch
    if {$idx eq "end"} {
        lappend branches($branch) $node
    } else {
	set branches($branch) [linsert $branches($branch) $idx $node]
    }

    Widget::init Wizard::Step $path.$node $args

    set items($node) $path.$node
    set bgcolor [Wizard::getoption $path $node -background]

    set widgets($node) $path.steps.f$node
    ttk::label $widgets($node) -background $bgcolor -style ImageFrame

    if {[getoption $path $node -createstep]} { Wizard::createstep $path $node }

    if {[Widget::getoption $path -autobuttons]} { Wizard::adjustbuttons $path }

    return $widgets($node)
}


proc Wizard::_insert_branch { path idx branch node args } {
    Widget::getVariable $path data
    Widget::getVariable $path items
    Widget::getVariable $path branches

    set branches($node)    [list]
    set data($node,branch) $branch
    if {$idx eq "end"} {
        lappend branches($branch) $node
    } else {
        set branches($branch) [linsert $branches($branch) $idx $node]
    }

    Widget::init Wizard::Branch $path.$node $args

    if {[Widget::getoption $path -autobuttons]} { Wizard::adjustbuttons $path }

    set items($node) $path.$node

    return $items($node)
}


proc Wizard::_is_step { path node } {
    Widget::getVariable $path steps
    return [info exists steps($node)]
}


proc Wizard::_is_branch { path node } {
    Widget::getVariable $path branches
    return [info exists branches($node)]
}


proc Wizard::_is_button { path node } {
    Widget::getVariable $path buttons
    return [info exists buttons($node)]
}


proc Wizard::_is_widget { path node } {
    Widget::getVariable $path widgets
    return [info exists widgets($node)]
}


proc Wizard::_eval_command { path command {step ""} } {
    if {![string length $command]} { return 1 }

    if {![string length $step]} { set step [Wizard::raise $path] }

    set map [list %W $path %S $step]

    if {![Wizard::_is_branch $path $step]} {
        if {[string match "*%B*" $command]} {
            lappend map %B [Wizard::branch $path $step]
        }

        if {[string match "*%n*" $command]} {
            lappend map %n [Wizard::step $path next $step]
        }

        if {[string match "*%b*" $command]} {
            lappend map %b [Wizard::step $path back $step]
        }
    }

    return [uplevel #0 [string map $map $command]]
}


# ------------------------------------------------------------------------------
#  Command Wizard::_destroy
# ------------------------------------------------------------------------------
proc Wizard::_destroy { path } {
    Widget::getVariable $path items

    foreach item [array names items] {
        Widget::destroy $items($item) 0
    }

    Widget::destroy $path
}


proc SimpleWizard { path args } {
    option add *WizLayoutSimple*Label.padX                5    interactive
    option add *WizLayoutSimple*Label.anchor              nw   interactive
    option add *WizLayoutSimple*Label.justify             left interactive
    option add *WizLayoutSimple*Label.borderWidth         0    interactive
    option add *WizLayoutSimple*Label.highlightThickness  0    interactive

    set args [linsert $args 0 -createstep 1]
    lappend args -createcommand [list Wizard::layout::simple %W %S]

    return [eval [list Wizard $path] $args]
}


proc ClassicWizard { path args } {
    option add *WizLayoutClassic*Label.padX                5    interactive
    option add *WizLayoutClassic*Label.anchor              nw   interactive
    option add *WizLayoutClassic*Label.justify             left interactive
    option add *WizLayoutClassic*Label.borderWidth         0    interactive
    option add *WizLayoutClassic*Label.highlightThickness  0    interactive

    set args [linsert $args 0 -createstep 1]
    lappend args -createcommand [list Wizard::layout::classic %W %S]

    return [eval [list Wizard $path] $args]
}


proc Wizard::layout::simple { wizard step } {
    set frame [$wizard widget get $step]

    set layout [$wizard widget set layout -widget $frame.layout -step $step]

    foreach w [list titleframe pretext posttext clientArea] {
	set $w [$wizard widget set $w -widget $layout.$w -step $step]
    }

    foreach w [list title subtitle icon] {
	set $w [$wizard widget set $w -widget $titleframe.$w -step $step]
    }

    frame $layout -class WizLayoutSimple

    pack $layout -expand 1 -fill both

    # Client area. This is where the caller places its widgets.
    frame $clientArea -bd 8 -relief flat

    Separator $layout.sep1 -relief groove -orient horizontal

    # title and subtitle and icon
    frame $titleframe -bd 4 -relief flat -background #FFFFFF

    label $title -background #FFFFFF \
        -textvariable [$wizard variable $step -text1]

    label $subtitle -height 2 -background #FFFFFF -padx 15 -width 40 \
    	-textvariable [$wizard variable $step -text2]

    label $icon -borderwidth 0 -background #FFFFFF -anchor c
    set iconImage [$wizard getoption $step -icon]
    if {$iconImage ne ""} { $icon configure -image $iconImage }

    set labelfont [font actual [$title cget -font]]
    $title configure -font [concat $labelfont -weight bold]

    # put the title, subtitle and icon inside the frame we've built for them
    grid $title    -in $titleframe -row 0 -column 0 -sticky nsew
    grid $subtitle -in $titleframe -row 1 -column 0 -sticky nsew
    grid $icon     -in $titleframe -row 0 -column 1 -rowspan 2 -padx 8
    grid columnconfigure $titleframe 0 -weight 1
    grid columnconfigure $titleframe 1 -weight 0

    set label label
    if {[BWidget::using ttk]} { set label ttk::label }

    # pre and post text.
    $label $pretext  -anchor w -justify left \
        -textvariable [$wizard variable $step -text3]
    $label $posttext -anchor w -justify left \
        -textvariable [$wizard variable $step -text4]

    # when our label widgets change size we want to reset the
    # wraplength to that same size.
    foreach widget [list title subtitle pretext posttext] {
	bind [set $widget] <Configure> {
            # yeah, I know this looks weird having two after idle's, but
            # it helps prevent the geometry manager getting into a tight
            # loop under certain circumstances
            #
            # note that subtracting 10 is just a somewhat arbitrary number
            # to provide a little padding...
            after idle {after idle {%W configure -wraplength [expr {%w -10}]}}
        }
    }

    grid $titleframe  -row 0 -column 0 -sticky nsew -padx 0
    grid $layout.sep1 -row 1 -sticky ew 
    grid $pretext     -row 2 -sticky nsew -padx 8 -pady 8
    grid $clientArea  -row 3 -sticky nsew -padx 8 -pady 8
    grid $posttext    -row 4 -sticky nsew -padx 8 -pady 8

    grid columnconfigure $layout 0 -weight 1
    grid rowconfigure    $layout 0 -weight 0
    grid rowconfigure    $layout 1 -weight 0
    grid rowconfigure    $layout 2 -weight 0
    grid rowconfigure    $layout 3 -weight 1
    grid rowconfigure    $layout 4 -weight 0
}

proc Wizard::layout::classic { wizard step } {
    set frame [$wizard widget get $step]

    set layout [$wizard widget set layout -widget $frame.layout -step $step]
    foreach w [list title subtitle icon pretext posttext clientArea] {
	set $w [$wizard widget set $w -widget $layout.$w -step $step]
    }

    frame $layout -class WizLayoutClassic

    pack $layout -expand 1 -fill both

    # Client area. This is where the caller places its widgets.
    frame $clientArea -bd 8 -relief flat
    
    Separator $layout.sep1 -relief groove -orient vertical

    # title and subtitle
    label $title    -textvariable [$wizard variable $step -text1]
    label $subtitle -textvariable [$wizard variable $step -text2] -height 2

    array set labelfont [font actual [$title cget -font]]
    incr labelfont(-size) 6
    set  labelfont(-weight) bold
    $title configure -font [array get labelfont]

    set label label
    if {[BWidget::using ttk]} { set label ttk::label }

    # pre and post text. 
    $label $pretext  -anchor w -justify left \
        -textvariable [$wizard variable $step -text3]
    $label $posttext -anchor w -justify left \
        -textvariable [$wizard variable $step -text4]

    # when our label widgets change size we want to reset the
    # wraplength to that same size.
    foreach widget [list title subtitle pretext posttext] {
        bind [set $widget] <Configure> {
            # yeah, I know this looks weird having two after idle's, but
            # it helps prevent the geometry manager getting into a tight
            # loop under certain circumstances
            #
            # note that subtracting 10 is just a somewhat arbitrary number
            # to provide a little padding...
            after idle {after idle {%W configure -wraplength [expr {%w -10}]}}
        }
    }

    label $icon -borderwidth 1 -relief sunken -background #FFFFFF \
        -anchor c -width 96 -image Wizard::none
    set iconImage [$wizard getoption $step -icon]
    if {[string length $iconImage]} { $icon configure -image $iconImage }

    grid $icon       -row 0 -column 0 -sticky nsew -padx 8 -pady 8 -rowspan 5
    grid $title      -row 0 -column 1 -sticky ew   -padx 8 -pady 8
    grid $subtitle   -row 1 -column 1 -sticky ew   -padx 8 -pady 8
    grid $pretext    -row 2 -column 1 -sticky ew   -padx 8
    grid $clientArea -row 3 -column 1 -sticky nsew -padx 8
    grid $posttext   -row 4 -column 1 -sticky ew   -padx 8 -pady 24

    grid columnconfigure $layout 0 -weight 0
    grid columnconfigure $layout 1 -weight 1

    grid rowconfigure    $layout 0 -weight 0
    grid rowconfigure    $layout 1 -weight 0
    grid rowconfigure    $layout 2 -weight 0
    grid rowconfigure    $layout 3 -weight 1
    grid rowconfigure    $layout 4 -weight 0
}
Added lib/BWidget/xpm2image.tcl.






































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# ----------------------------------------------------------------------------
#  xpm2image.tcl
#  Slightly modified xpm-to-image command
#  $Id: xpm2image.tcl,v 1.4 2003/10/20 21:23:53 damonc Exp $
# ------------------------------------------------------------------------------
#
#  Copyright 1996 by Roger E. Critchlow Jr., San Francisco, California
#  All rights reserved, fair use permitted, caveat emptor.
#  rec@elf.org
# 
# ----------------------------------------------------------------------------

proc xpm-to-image { file } {
    set f [open $file]
    set string [read $f]
    close $f

    #
    # parse the strings in the xpm data
    #
    set xpm {}
    foreach line [split $string "\n"] {
        if {[regexp {^"([^\"]*)"} $line all meat]} {
            if {[string first XPMEXT $meat] == 0} {
                break
            }
            lappend xpm $meat
        }
    }
    #
    # extract the sizes in the xpm data
    #
    set sizes  [lindex $xpm 0]
    set nsizes [llength $sizes]
    if { $nsizes == 4 || $nsizes == 6 || $nsizes == 7 } {
        set data(width)   [lindex $sizes 0]
        set data(height)  [lindex $sizes 1]
        set data(ncolors) [lindex $sizes 2]
        set data(chars_per_pixel) [lindex $sizes 3]
        set data(x_hotspot) 0
        set data(y_hotspot) 0
        if {[llength $sizes] >= 6} {
            set data(x_hotspot) [lindex $sizes 4]
            set data(y_hotspot) [lindex $sizes 5]
        }
    } else {
	    error "size line {$sizes} in $file did not compute"
    }

    #
    # extract the color definitions in the xpm data
    #
    foreach line [lrange $xpm 1 $data(ncolors)] {
        set colors [split $line \t]
        set cname  [lindex $colors 0]
        lappend data(cnames) $cname
        if { [string length $cname] != $data(chars_per_pixel) } {
            error "color definition {$line} in file $file has a bad size color name"
        }
        foreach record [lrange $colors 1 end] {
            set key [lindex $record 0]
            set color [string tolower [join [lrange $record 1 end] { }]]
            set data(color-$key-$cname) $color
            if { [string equal -nocase $color "none"] } {
                set data(transparent) $cname
            }
        }
        foreach key {c g g4 m} {
            if {[info exists data(color-$key-$cname)]} {
                set color $data(color-$key-$cname)
                set data(color-$cname) $color
                set data(cname-$color) $cname
                lappend data(colors) $color
                break
            }
        }
        if { ![info exists data(color-$cname)] } {
            error "color definition {$line} in $file failed to define a color"
        }
    }

    #
    # extract the image data in the xpm data
    #
    set image [image create photo -width $data(width) -height $data(height)]
    set y 0
    foreach line [lrange $xpm [expr {1+$data(ncolors)}] [expr {1+$data(ncolors)+$data(height)}]] {
        set x 0
        set pixels {}
        while { [string length $line] > 0 } {
            set pixel [string range $line 0 [expr {$data(chars_per_pixel)-1}]]
            set c $data(color-$pixel)
            if { [string equal $c none] } {
                if { [string length $pixels] } {
                    $image put [list $pixels] -to [expr {$x-[llength $pixels]}] $y
                    set pixels {}
                }
            } else {
                lappend pixels $c
            }
            set line [string range $line $data(chars_per_pixel) end]
            incr x
        }
        if { [llength $pixels] } {
            $image put [list $pixels] -to [expr {$x-[llength $pixels]}] $y
        }
        incr y
    }

    #
    # return the image
    #
    return $image
}

Added lib/Conditions/FileConditions/DirectoryTestCondition.condition.












































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition DirectoryTestCondition

Property Directory installedfile "Directory"
Help Directory "The path of the directory to be tested"

Property Test choice "Test" "exists" \
    {"exists" "does not exist"
     "is empty" "is not empty"
     "is readable" "is not readable"
     "is writable" "is not writable"
     "can be created" "cannot be created"}
Help Test "This property specifies what to test the directory for.\
    Please see the documentation for more information about what each test
    does."

proc ::InstallJammer::conditions::DirectoryTestCondition { obj } {
    global conf
    global info

    $obj properties props -subst 1

    debug "Checking to see if $props(Directory) $props(Test)"

    set res   0
    set dir   $props(Directory)
    set isdir [file isdirectory $dir]
    switch -glob -- $props(Test) {
        "*exist*" {
            set res $isdir
        }

        "is*empty" {
            set res [expr {$isdir && [::InstallJammer::DirIsEmpty $dir]}]
        }

        "is*readable" {
            set res [expr {$isdir && [file readable $dir]}]
        }

        "is*writable" {
            set res [expr {$isdir && [::InstallJammer::DirIsWritable $dir]}]
        }

        "can*created" {
            set info(Dir) [file nativename $dir]
            while {[llength [file split $info(Dir)]]} {
                if {[file isdirectory $info(Dir)]} {
                    set res [::InstallJammer::DirIsWritable $info(Dir)]
                    break
                }

                set dir [file dirname $info(Dir)]

                if {$dir eq $info(Dir)} { break }

                set info(Dir) $dir
            }
        }
    }

    if {[string match "*not*" $props(Test)]} { set res [expr {!$res}] }
    return $res
}
Added lib/Conditions/FileConditions/FileExistsCondition.condition.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition FileExistsCondition

Property Filename installedfile "Filename" ""
Property Operator choice        "Operator" "exists" {exists "does not exist"}

proc ::InstallJammer::conditions::FileExistsCondition { obj } {
    $obj properties props
    
    debug "Checking to see if $props(Filename) $props(Operator)"
    
    set file [::InstallJammer::SubstText $props(Filename)]

    if {$props(Operator) eq "exists"} {
        return [file exists $file]
    } else {
        return [expr {![file exists $file]}]
    }
}
Added lib/Conditions/FileConditions/FileNameTestCondition.condition.


























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition FileNameTestCondition

Property Filename installedfile "Filename" ""
Property Operator choice        "Operator" "name is valid" \
  {"name is valid" "name is not valid" "path is valid" "path is not valid"}

proc ::InstallJammer::conditions::FileNameTestCondition { obj } {
    $obj properties props -subst {Filename}
    
    debug "Checking to see if $props(Filename) $props(Operator)"
    
    if {[string match "path*" $props(Operator)]} {
        set valid [::InstallJammer::IsValidPath $props(Filename)]
    } else {
        set valid [::InstallJammer::IsValidFilename $props(Filename)]
    }

    if {[string match "* not *" $props(Operator)]} {
        return [expr {!$valid}]
    }
    return $valid
}
Added lib/Conditions/FileConditions/FilePermissionCondition.condition.


















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition FilePermissionCondition

Property Filename installedfile "Filename"
Property Permission choice "Permission" "is readable" \
    {"can create" "cannot create" "is readable" "is writable"
     "is not readable" "is not writable"}

proc ::InstallJammer::conditions::FilePermissionCondition { obj } {
    global conf
    global info

    $obj properties props

    if {[string match "can*create" $props(Permission)]} {
        debug "Checking to see if we $props(Permission) $props(Filename)"
    } else {
        debug "Checking to see if $props(Filename) $props(Permission)"
    }

    set res  0
    set file [::InstallJammer::SubstText $props(Filename)]
    switch -glob -- $props(Permission) {
        "is*readable" {
            set res [file readable $file]
        }

        "is*writable" {
            set res [::InstallJammer::DirIsWritable $file]
        }

        "can*create" {
            set info(Dir) [file nativename $file]
            while {[llength [file split $info(Dir)]]} {
                if {[file exists $info(Dir)]} {
                    set res [::InstallJammer::DirIsWritable $info(Dir)]
                    break
                }

                set dir [file dirname $info(Dir)]

                if {$dir eq $info(Dir)} { break }

                set info(Dir) $dir
            }
        }
    }

    if {[string match "*not*" $props(Permission)]} { set res [expr {!$res}] }
    return $res
}
Added lib/Conditions/GeneralConditions/CommandLineTestCondition.condition.






















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition CommandLineTestCondition

Property Operator choice "Operator" "exists" {"exists" "does not exist" "was passed on the command line" "was not passed on the command line"}

Property Option short "Option"
Help Option "The command line option to check"

proc ::InstallJammer::conditions::CommandLineTestCondition { obj } {
    variable ::InstallJammer::CommandLineOptions
    variable ::InstallJammer::PassedCommandLineOptions

    $obj properties props -subst 1

    debug "Checking to see if $props(Option) $props(Operator)"

    set passed [::InstallAPI::CommandLineAPI -do check  -option $props(Option)]
    set exists [::InstallAPI::CommandLineAPI -do exists -option $props(Option)]

    switch -- $props(Operator) {
        "exists" {
            return $exists
        }

        "does not exist" {
            return [expr {!$exists}]
        }

        "was passed on the command line" {
            return $passed
        }

        "was not passed on the command line" {
            return [expr {!$passed}]
        }
    }
}
Added lib/Conditions/GeneralConditions/ExecuteScriptCondition.condition.
























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition ExecuteScriptCondition

Property ResultVirtualText short "Result Virtual Text" ScriptResult

Property Script text "Script"

proc ::InstallJammer::conditions::ExecuteScriptCondition { obj } {
    $obj properties props -subst {ResultVirtualText}

    set varName result
    if {$props(ResultVirtualText) ne ""} {
        set varName ::info($props(ResultVirtualText))
    }

    set script [::InstallJammer::SubstForEval $props(Script)]
    if {[uplevel #0 [list catch $script $varName]] == 1} {
        return -code error [set $varName]
    }

    return [string is true -strict [set $varName]]
}
Added lib/Conditions/GeneralConditions/ObjectTestCondition.condition.






































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition ObjectTestCondition

Property ObjectID short "Object ID"
Help ObjectID "The alias or ID of an object"

Property Operator choice "Operator" "is active" \
  {"does not exist" "exists" "is active" "is not active"}

proc ::InstallJammer::conditions::ObjectTestCondition { obj } {
    $obj properties props

    $obj get ObjectID oid
    set id [::InstallJammer::ID [::InstallJammer::SubstText $oid]]

    if {$id eq ""} {
        return -code error "Object is Active condition failed:\
                            invalid object '$oid'"
    }

    debug "Checking to see if object $oid $props(Operator)"

    set exists [::InstallJammer::ObjExists $id]
    
    if {$props(Operator) eq "exists"} {
        return $exists
    }

    if {$props(Operator) eq "does not exist"} {
        return [expr {!$exists}]
    }

    if {!$exists} {
        debug "Object $oid does not exist.  Cannot check if it $props(Operator)"
        return 0 
    }

    if {$props(Operator) eq "is active"} {
        return [$id active]
    }

    if {$props(Operator) eq "is not active"} {
        return [expr {![$id active]}]
    }
}
Added lib/Conditions/GeneralConditions/PasswordTestCondition.condition.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition PasswordTestCondition

Property EncryptedPassword short "Encrypted Password"

Property UnencryptedPassword short "Unencrypted Password"

proc ::InstallJammer::conditions::PasswordTestCondition { obj } {
    $obj properties props -subst 1

    debug "Checking to see if $props(UnencryptedPassword) matches the encrypted\
        password $props(EncryptedPassword)"

    set enc [sha1 -string $props(UnencryptedPassword)]

    debug "Encrypted form of $props(UnencryptedPassword) is $enc"

    if {$enc eq $props(EncryptedPassword)} {
        debug "$enc matches $props(EncryptedPassword)"
        return 1
    } else {
        debug "$enc does not match $props(EncryptedPassword)"
        return 0
    }
}
Added lib/Conditions/GeneralConditions/ScriptCondition.condition.




























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition ScriptCondition "Script Condition"

Property Script text "Script"

proc ::InstallJammer::conditions::ScriptCondition { obj } {
    return [::InstallJammer::EvalCondition [$obj get Script]]
}
Added lib/Conditions/GeneralConditions/VirtualTextTestCondition.condition.














































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition VirtualTextTestCondition

Property Language language "Language" "None"

Property Operator choice "Operator" "exists" {"does not exist" "exists" "was set from the command line"}

Property VirtualText short "Virtual Text"
Help VirtualText "The virtual text variable to check for existence"

proc ::InstallJammer::conditions::VirtualTextTestCondition { obj } {
    $obj properties props -subst 1

    debug "Checking to see if virtual text $props(VirtualText) $props(Operator)"

    set operator    $props(Operator)
    set virtualtext $props(VirtualText)

    if {$operator eq "was set from the command line"} {
        variable ::InstallJammer::VirtualTextSetByCommandLine
        set exists   [info exists VirtualTextSetByCommandLine($virtualtext)]
        set operator "exists"
    } else {
        set exists [::InstallAPI::VirtualTextExists \
            -virtualtext $virtualtext -language $props(Language)]
    }

    if {$operator eq "exists"} {
        return $exists
    } else {
        return [expr {!$exists}]
    }
}
Added lib/Conditions/PlatformConditions/PlatformCondition.condition.












































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition PlatformCondition "Platform Condition"

Property Operator choice "Operator" "is" \
  {"is" "is not" "matches" "does not match"}
Property Platform platform "Platform" ""

proc ::InstallJammer::conditions::PlatformCondition { obj } {
    global info

    $obj properties props -subst 1

    debug "Checking to see if <%Platform%> $props(Operator) $props(Platform)"

    switch -- $props(Operator) {
        "is" {
            return [expr {$info(Platform) eq $props(Platform)}]
        }

        "is not" {
            return [expr {$info(Platform) ne $props(Platform)}]
        }

        "matches" {
            return [string match $props(Platform) $info(Platform)]
        }

        "does not match" {
            return [expr {![string match $props(Platform) $info(Platform)]}]
        }
    }
}
Added lib/Conditions/StringConditions/StringEqualCondition.condition.


































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition StringEqualCondition "String Equal Condition"

Property MatchCase boolean "Match Case" "Yes"
Property Operator  choice  "Operator"   "equals" {equals "does not equal"}

Property String1   text    "String 1"
Property String2   text    "String 2"

proc ::InstallJammer::conditions::StringEqualCondition { obj } {
    $obj properties props

    debug "Checking to see if $props(String1) $props(Operator) $props(String2)"

    set string1 [::InstallJammer::SubstText $props(String1)]
    set string2 [::InstallJammer::SubstText $props(String2)]

    set cmd [list string equal]
    if {!$props(MatchCase)} { lappend cmd -nocase }
    lappend cmd $string1 $string2

    if {$props(Operator) eq "equals"} {
        return [eval $cmd]
    } else {
        return [expr {![eval $cmd]}]
    }
}
Added lib/Conditions/StringConditions/StringIsCondition.condition.






















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition StringIsCondition "String Is Condition"

Property Operator choice "Operator" "true" {empty false "not empty" true}
Property String   text   "String"   ""

proc ::InstallJammer::conditions::StringIsCondition { obj } {
    $obj properties props

    debug "Checking to see if $props(String) is $props(Operator)"

    set string [::InstallJammer::SubstText $props(String)]

    if {$props(Operator) eq "empty"} {
        return [expr {[string trim $string] eq ""}]
    } elseif {$props(Operator) eq "not empty"} {
        return [expr {[string trim $string] ne ""}]
    } else {
        return [string is $props(Operator) -strict $string]
    }
}
Added lib/Conditions/StringConditions/StringMatchCondition.condition.
































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition StringMatchCondition "String Match Condition"

Property MatchCase boolean "Match Case" "Yes"
Property Operator  choice  "Operator"   "matches" {matches "does not match"}
Property String    text    "String"
Property Pattern   text    "Pattern"

proc ::InstallJammer::conditions::StringMatchCondition { obj } {
    $obj properties props

    debug "Checking to see if $props(String) $props(Operator) $props(Pattern)"

    set string  [::InstallJammer::SubstText $props(String)]
    set pattern [::InstallJammer::SubstText $props(Pattern)]

    set cmd [list string match]
    if {!$props(MatchCase)} { lappend cmd -nocase }
    lappend cmd $pattern $string

    if {$props(Operator) eq "matches"} {
        return [eval $cmd]
    } else {
        return [expr {![eval $cmd]}]
    }
}
Added lib/Conditions/SystemConditions/EnvVariableTestCondition.condition.




















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition EnvVariableTestCondition

Property Operator choice "Operator" "exists" {"exists" "does not exist"}
Property Variable short  "Variable"

proc ::InstallJammer::conditions::EnvVariableTestCondition { obj } {
    $obj properties props -subst 1

    debug "Checking to see if environment variable $props(Variable)\
                $props(Operator)"

    set exists [info exists ::env($props(Variable))]

    if {$props(Operator) eq "exists"} {
        return $exists
    } else {
        return [expr !$exists]
    }
}
Added lib/Conditions/SystemConditions/PackageTestCondition.condition.






































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition PackageTestCondition

Property Operator choice "Operator" "is installed" \
  {"is installed" "is not installed"}
Property Package  short  "Package"

proc ::InstallJammer::conditions::PackageTestCondition { obj } {
    $obj properties props -subst 1

    set package $props(Package)

    set rpm  [auto_execok rpm]
    set dpkg [auto_execok dpkg]

    if {$rpm ne ""} {
        debug "Checking RPM database to see if $package $props(Operator)"
        set result [catch { exec rpm -q $package }]
    } elseif {$dpkg ne ""} {
        debug "Checking DPKG database to see if $package $props(Operator)"
        set result [catch { exec dpkg -s $package }]
    }

    if {$props(Operator) eq "is not installed"} {
        return $result
    } else {
        return [expr !$result]
    }
}
Added lib/Conditions/SystemConditions/PortTestCondition.condition.






















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition PortTestCondition

Property Operator choice "Operator" "can bind" {"can bind" "cannot bind"}
Property Port short "Port"

proc ::InstallJammer::conditions::PortTestCondition { obj } {
    $obj properties props -subst 1

    debug "Checking to see if port $props(Port) $props(Operator)"

    if {![set result [catch { socket 127.0.0.1 $props(Port) } sock]]} {
        catch { close $sock }
    }

    if {$props(Operator) eq "can bind"} {
        return $result
    } elseif {$props(Operator) eq "cannot bind"} {
        return [expr !$result]
    }
}
Added lib/Conditions/UserInputConditions/AskYesOrNo.condition.








































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition AskYesOrNo "Ask Yes or No"

Include ConsoleAskYesOrNo

Property Icon choice "Icon" "info" {error info question warning}
Help Icon "The icon to display on the message box"

Property DefaultButton choice "Default Button" "Yes" {Yes No}
Help DefaultButton "Which button will have focus by default"

Property ResultVirtualText short "Result Virtual Text" "Answer"
Help ResultVirtualText "A virtual text variable to hold the user's answer"

Property TrueValue choice "True Value" "Yes" {Yes No}
Help TrueValue "Which answer will return a true result for this condition"

Text Title
Text Message

proc ::InstallJammer::conditions::AskYesOrNo { obj } {
    global info

    $obj properties props

    if {$info(SilentMode)} {
        debug "Ask Yes or No condition not valid in Silent mode."
        debug "Skipping condition and returning $props(TrueValue)."
        return $props(TrueValue)
    }

    set id [$obj id]

    if {$info(ConsoleMode)} {
        debug "Using Console Ask Yes or No action in place of\
                Ask Yes or No condition for console install."

        $obj set Default     $props(DefaultButton)
        $obj set Prompt      [::InstallJammer::GetText $id Message -subst 0]
        $obj set VirtualText $props(ResultVirtualText)

        set result [::InstallJammer::actions::ConsoleAskYesOrNo $obj]
        return [string equal -nocase $result $props(TrueValue)]
    }

    set title   [::InstallJammer::GetText $id Title]
    set message [::InstallJammer::GetText $id Message]

    set args [list -type yesno -title $title -message $message]
    lappend args -icon $props(Icon)
    lappend args -default [string tolower $props(DefaultButton)]
    lappend args -parent [::InstallJammer::TransientParent]

    set result [eval ::InstallJammer::MessageBox $args]

    if {[string length $props(ResultVirtualText)]} {
        global info
        set info($props(ResultVirtualText)) $result
    }

    return [string equal -nocase $result $props(TrueValue)]
}
Added lib/Conditions/WindowsConditions/FileExtensionTestCondition.condition.




















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition FileExtensionTestCondition

Property FileExtension short "File Extension"
Property Operator choice "Operator" "exists" {"exists" "does not exist"}

proc ::InstallJammer::conditions::FileExtensionTestCondition { obj } {
    $obj properties props -subst 1

    set ext    $props(FileExtension)
    set exists [::installkit::Windows::FileExtension exists $ext]

    debug "Checking to see if file extension $ext $props(Operator)"

    if {$props(Operator) eq "exists"} {
        return $exists
    } else {
        return [expr {!$exists}]
    }
}
Added lib/Conditions/WindowsConditions/FileTypeTestCondition.condition.






















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition FileTypeTestCondition

Property FileType short "File Type"

Property Operator choice "Operator" "exists" {"exists" "does not exist"}

proc ::InstallJammer::conditions::FileTypeTestCondition { obj } {
    $obj properties props -subst 1

    set type   $props(FileType)
    set exists [::installkit::Windows::FileType exists $type]

    debug "Checking to see if file type $type $props(Operator)"

    if {$props(Operator) eq "exists"} {
        return $exists
    } else {
        return [expr {!$exists}]
    }
}
Added lib/Conditions/WindowsConditions/RegistryTestCondition.condition.






































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition RegistryTestCondition

Property Operator choice "Operator" "exists" {"exists" "does not exist"}

Property RegistryKey short "Registry Key"

Property RegistryValue short "Registry Value"

proc ::InstallJammer::conditions::RegistryTestCondition { obj } {
    $obj properties props -subst 1

    set key $props(RegistryKey)
    set val $props(RegistryValue)

    if {![string length $val]} {
        debug "Checking to see if registry key $key $props(Operator)"
        set exists [expr {[catch { registry values $key }] == 0}]
    } else {
        debug "Checking to see if registry value $key:$val $props(Operator)"
        set exists [expr {[catch { registry get $key $val }] == 0}]
    }

    if {$props(Operator) eq "exists"} {
        return $exists
    } else {
        return [expr {!$exists}]
    }
}
Added lib/Conditions/WindowsConditions/WindowsServiceTestCondition.condition.
























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

Condition WindowsServiceTestCondition

Property Database short "Database"
Property ServiceName short "Service Name"
Property System short "System"
Property Operator choice "Operator" "exists" \
  {"exists" "does not exist" "is paused" "is running" "is stopped"}

proc ::InstallJammer::conditions::WindowsServiceTestCondition { obj } {
    $obj properties props -subst 1

    set service $props(ServiceName)
    if {[catch { twapi::get_service_internal_name $service } service]} {
    	if {$props(Operator) eq "does not exist"} { return 1 }
	return 0
    }

    set opts [list]
    if {$props(System) ne ""} { lappend opts -system $props(System) }
    if {$props(Database) ne ""} { lappend opts -database $props(Database) }

    switch -- $props(Operator) {
        "exists" - "does not exist" {
            set exists [eval [list twapi::service_exists $service] $opts]
            if {$props(Operator) eq "exists"} {
                return $exists
            } else {
                return [expr {!$exists}]
            }
        }

        "is paused" - "is running" - "is stopped" {
            array set s [eval [list twapi::get_service_status $service] $opts]
            return [string equal $s(state) [lindex $props(Operator) 1]]
        }
    }
}
Added lib/Icons/InstallJammer.crystal.dialog.png.tkico.








>
>
>
>
1
2
3
4
dialogquestion:act:actions:32:data:iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAYlSURBVHjaYvz//z/DQAKAAGIBEYyMjERrOMbAoACkFP4xMDgAMQPI+f8g+ACQ/cAFiIk1C+R5gABiBBMEHHCKgUEAaHgC0JJ4IG0AtRBuORp9AYgXAtkLvBgYPhByAEAAEXQA0PIGoGH5QEMFQMHFB8RcQMyhr8/Axc8PVvMNhA8dYvgIpN8C8XeIQz4A8UQ/oH58DgAIIJwOOA3x9X6Qj0EWi4JwRAQDi7c3A4uvL1YD/126xPBnyxaGx8uXM9x//BjsMFCIAM1wDMISGiC7AQIIqwOAlhtALRcQAfIlXV0Z2OvrGZhkZcHyfz99Yvh48iTDn2/fGNgVFBj+//nDwMLJycCjpQU341dfH8PN+fMZ7gDVQkPDMQzoGHQHAAQQhgOgPr8PslyKl5dBvKSEgTUgAGLos2cMn27eZGCWl2cQhIohg3e7dzNwsrMzcAoIQELkxg2Gu7W1DBdu3QKlD5AjFCORQgJkN0AAYTgAGOfnQcEuCWRLz57NwKSqConnu3cZPr9/zyBeXEw4eQMtZHj+HGLJ588MtwsKGM4B9YOiI5qBwRDZAQABxIQlwRmAgl0iJ4eBSQTIAlr698kThs/v3hFnOQioqTEwAKMEpJcRGD0qWVkMqtzcoFAwWIyWKAECCB4CJ4FBDuTfZwbSWgYGDJx5eXBFby5eZBCZMAHTl6eATv79m4EBaDiDszMDg7AwQv7LFwaG1avh3N9HjjBsmjePASj6AegQxUQQDbQbIIDgIQDN5wJiQDa7FzAHA30Mw8wqKqiWfwRmuM2bGRhevoSoAaX4adMYfn9ASug8PMB4+wY3gxWYQDUFBUH2gMsUmDKAAEJ2QDw4u+npMTCB0gQw+GCYGeRDZLBnD4o8GL96xfDhwgVUdRwcYLk/wJD6uWYNgzzQx5yQrBkPUwIQQCyw4hUoaMALEpCSgrgaCXCJiiI4IF8dA+r4/h1FzX1gaGg7OKCI/QCGyp+rVxn+//wJFwMl7ptAu2ZCivQHAAHEAvW9AqgYBfmTmYsL4iPkCuPECUhcy8kxMBw+DEwUb1Dkb//6xSANzG7I4O+BAwy/z53DSJ8gr9yA2glyAEAAgR0AqlhADmBnYWFgBCUebACYx7GB26ysDApLljCwQvM+2EPAtPAjMRGrem5E5QUKrgMAAQQLAbAgNyjroAU/PnABGFraK1diWP7N0ZHh3wPslaIgUsUFAgABBAsBiAAomIl0ADATMmgDQwWr5eiJEb0OgNoJAgABhOKAr8DEwvX2LVH1OAOwUEKxHOjjH4GBwGC5wMCER+9btBAACCBYFBwACtb/AhkMLDrxWfwHZACQFrCzQ5H7DbScEWg5MwHHf0M44ACIDxBAsBB4AHIRqD6X+PcPtXYEWvYfycUgGWYkPlgJyNcEfA4DzxHBD04kAAEE1uMK5IAqildQAUZILQXBUDFmNMz68CGiPN+4EUMeF74HcfyFIqgDAAKIBd6YADajgMFj8BSYrWSYmQn6RKiigoHh2jVgiQ4sfhctYmAElXoEwLW/fxk+AhM60AELYWIAAcSClDIXgNLBjb9/BWSgTS184DIQCwPbC/+BWERdnYH96VPCDVpgDvsHaQ8sgIkBBBBKe2ATsKoEOUId6AANQUHcKRlUtG7bxiAMrDXBANjqYbCxwZuAjwNL16PASgzo0cYyaJUMshsggDAaJOugDRJjYJ0gj8MRz75+ZZC6fx9VEFTynT6NVf1VoOXbga0pUNyXoTVIAAKIBUsh4QgMhfsnnz0T+AdsXimKiWEYyAtMJ+D6HlTlwgAoLSDzYZYDa0mo5aB2gCO6PEAAYW2UroQ2SkHtAx1go1NXWRnTW6A2QlwcxNK1axkYjh7FDHZgM+wosICCWV6OpVEKEEA4m+XLgJb/gzbLuYB1hB4woamAakMiwLVHjxiOARuvH4BV9n9os7wcR7McIIAIdkwWQRImuGPCDWyYyElLM0gAo4UX6HNhISFIkw2Yuj8Bo+QxMLjvAHPDR2Aa+Qfx9cQyAh0TgAAiqms2D6lr9g8SPQxo/ULk7hm8a1ZGRNcMIICIcgAymAFpvMA7pzDL/0M7p0Ukdk4BAohxoLvnAAEGABadteqVSIbNAAAAAElFTkSuQmCC
dialoginfo:act:actions:32:data:iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAY8SURBVHjaYvz//z/DQAKAAGJiGGAAEEAsMAYjIyNehcqxOwUY/v5P+Pfvnz3D338O//7+Ffj/9x/D/79/Gf7/+ccA5H8A8g/8//P34P9//xa8PJLwAZ95sJAHCCBGOAOHA1QT9gj8//e/H2hoAsiyvwzMDN+5BBl+cvAyMPz7DzEISLN8esfA+uY5A8OPHxBH/f274P/f/4VvzqZ9wOcAgADC6wDVxL0BQMPng3z7nVOAgUFSnsHRWJzBTpaBQZ4fokYBSD/4yMDw8ScDw6FHDAw7T75geHPyHAPLy6ewUEl8fzl7Ay4HAAQQTgeoJe0D+brgFxMbww8FbYYYKyGGdEMGBn52wvG6/BoDw8Qtzxje7drLwPjpIyg0Jny8WVCIzQEAAYTVAWrJQMv//iv4wcrNwGtowjDZi4VBhhehWQDoCDFuCPvHHwaGG89/MHBxc6A44hMwRNoO/GTYPXktA9PrlwxAz0z4fK+kEN0BAAGE4QCgzwOAYut/sHAx6DuaMNTas6AYzM7MwKAvjurjyYuPMyjoaDKIiwtghMaWaz8ZeitXMTC9es4ATMCB355UbkB2AEAAoWRD1aS9AkCJ+b+Bwc6uZ8KQYMjC8P4HAwr+9RczyIX4OBg2bj+PoRaErZXYGdwKwxj+cvOCcst8DrFmFFcCBBBqOfCfART0Ap9ltRlyzVkYfgMte/8dFd99z8Dw7geqA5ZtusDAKSCAoRaGw/XZGSQCvEDRAMq6/ch6AQIIHgVqCUDfM/x//41DgMEAGPTeyrgTGRswGvj/fGB4cu06w9zlxxlktDQZ/KI88SbMW0CHTytbyMD44B4wUf4T/PWpGZw9AQKIBSlRJABdyPBNQonBQAzoy+/4U/oLBmBIKlkyRFRbgvn41L/8BsmqrKbmDL/v3gGFRAJQeAJIDiCAEA4AlnCgQkZKSojhGzBlgzBGuSAEwTAgxcPAwMnKwLDvygeGC+84GFg5ETnh8y8GhguvGBjuvIeUEWCgqMHAwsrO8P/bV3uYAwACCNkBDt95hBmk2HH7hgWYYqxkGBi4WVHFV14+z3DqJgODppMjwyugby8CLX7+FbsZ/2TlGRiuXXaA8QECCOEAYOL7yc4LKlUZ3uJwwKZbwGx1/gNDf6AAg7IgcuL9w/DuGyPDtnsMDG8IRN1/MQkGhssX4TkBIICQHQBKCODgwltDMwow7H/AgOKA/39/MjwCxvHv74RLSVjdAQMAAYTiAJAkqAT7/Qe/Id/R5P//BebLv0TWv2ieAwgg5DQAdtlHoFlfCbQSvv3GdMD/v4wYhhMDAAIIOQQ+sHx6L/AJaDgjPsf/h5T/KOL/gA74A9T1jwgbnz0FkfAqGiCAmBAO+HuA7T2w0gAGJSgw/kPxPxj+ywCWA4lh+BSYBv7/+QlxACF8/y5IxwGYVoAAQnLAv4OMv34wcLx6Ao7P/1DMAMPIhvzHkgb+/CBs+bUrwOADp9SDML0AAYScBhaAymnuJ9cYGMVl8McbE3oU/AQWYczgmhIf+HnyECyWFsDEAAIIbtSzPVGg1ssC5jfPGLg/vWDgYWPAiQ0lUQ329/NhEBPiw6uH7cldhn8P7kIt74OnAYAAQmkPiFnPB9VW9xk4uAS4PIIYmNjYUCzSFGVg2BqD24d+1RsZLvE4MTBx8KImke/fGZ719jH8efcOZLEiyAEwewECCKNBImI6OwDoiPXMAoIMoj5+DEzsiDYYL9A98t+vMnx/cB4Y7MDC/t9vYNnxB1JyMTIxXLp6l4HNOoOBXUIVrufPt+8M9ydOY/jx5BmIGwi0HKVBAhBAWJtkQvrTwE0yNiEhBvnQIAZmDnYGcgDI8qs90xi+PQZb3gi0vAG9SQYQQDgbpQJak/qBLZgCVl5uBiVfdwZ+RVmSLH97/S7DtTkrGH68eYdhObIDAAIIb7OcT6UvANi0ng90iICAgjSDnI0Jg4SeOl6Ln56+wnB3+yGwA6AFTiIs2LE5ACCACHZMuOU6wc0oYEGVAOoBsbCzMgiryDEIyEjAi2+QGe/vP2V4de0uw6+v8BoJlNUKkVM8NgcABBBBB8AAh0iTALR3ZP/vzz+H/8hdM0jt9gFawh1Ez2r4HAAQQIwD3TsGCKAB7x0DBBgAzPMp3/mFRxcAAAAASUVORK5CYII=
dialogerror:app:apps:32:data:iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAXJSURBVHjaYvz//z/DQAKAAGIBEYyMjEQpPs7AEAB0rgEQ2/9jYBAAsYE0A5C+AKQ/APFBENuNgWEDMeaBPA8QQIxgAo8DTkEsKgDieKAFCqDwAqnmgFgMx1+A+DcQQx30AEgvBNITfIAOw+cAgADC6wCg5QFAaj7It6CgEgBifnl5Bh5bWwYmII1i2IcPDJ8OH2Z4fekSwwsg/zvEMR+Ajkj0xxEiILsBAginA04zMPSDfA6SEQFiibAwBtbISAZmGxu8wfrv0SOGP8uXM9ybNYvh3qdPDL8gDpkQzMBQiM0BAAGE1QFAy+cDLU9gA7LlNTQYeGtqGJgtLEhKXP8/fmT4UFbGcGbvXoZPEEcsCAOGBroDAAIIwwHAYO8HUgV8QELazo6Bu7GRgZGXl+xU/m3pUoYL/f0MT6AhEYkUEiC7AQIIxQHQOF8P8rmylRUDT1MTwiQ+oJM+fSLOVjS133fsYNjf08PwEeKIwBhomgDZDRBAcAdAU/t9JiCtLCrKINDdzcDIzQ0xQVGRgcHYmIEBGL8Mp07ht9zMjIFBTo6B4exZoGn34cLvpkxh2HPwIChNgLKrYjwogQLtBgggJnhwQLKaACjB8cXFMTD+Aip9/56BQUwMYjkIgAw2MICIY8MgOZAaEADpAemFygkGBjKoc3IyQMuPApi9AAGE7IB4UFYTU1JiYBYXB7oPmH3ZgJEBTAcoQEWFgQEYPWB5ZAwSA8khA5BekBlAeZCHtHx8GDgh0RAPUwIQQCywEg5UyAgB2WyGhhBXgwCIBgUlLARgQFubgQEUQqtXQ/ihoRAxdADU+x9YLvx9/Jjhz61bDH9fvmQAhc8VoF2zIeltA0AAsUB9DypeGXiArmURAUbCu3cIQ2YDlf78CfEhMgA5FCQOY6OBv2vXMvyurWX4ff06irgUEF+GhIIByAEAAQR2AJBjD4oLbgEBhO+RwcSJEMscHVHFcZQNvxcsYPiRmIhVTgAa7EDT7EF8gACChYAAqGxn4eHB7gAQaG+HBLu7O95MgM9yGOAH4hcQtzAABBAsBMC1GsOPH6jBjw6qqyEh4edHtuVQD8OigAEggGAhAMYM37/jDgEY+POH4jYA1AFgABBAsBC4AEqIYAfga6BMn87AEBSEU5o1IQFM/yIQClAPXwCxAQII5oAPX0EMUPCC4hkbmDePgSEigqDvQI4AJejfeBzxBuIAcDsBIICYoC46CLL2K9D3/7Dg/yDL4+Mxq15gnIMwOmAGOoJt/nwGZhAbDYMi+AfE0wdBagECCFwh7AQWCjuA7rgFxP/Q8fz5/7ECoDhMzX8cav4hqYHhY0DcB8S9oOYd0G6AAGKANUq3AauOfSDD2NkR2NQUu+WLF6OqA2GQGDYAMgNJ3RygHT1Au2CeBwggeF0AasOB0sE9JqAQqBYE4bt3GRhyc1HDd8UKBob8fIQaGAaJgeSQAUgvyAyomnNAsz9AonwhTAlAAMGr483AggHoiPssTEwCDsDKiIuFBWEQqKzvBQbamjUMDEVF+FNhHzCAQ0IYGIqLEXUFEHwCZt9FwLrg+79/IDcolkGrY4AAQmmQbIBUSuv52NkZ7ICNTlYmJoTBmpoMDGjlOk6Apvbnv38MKx8+ZHgJqTsCy5AaJAABhNEkWwNtjMoLCTEYAOt2VuSQIAP8BPp8P7AhcxlYwoKa6eVoTTKAAMLaKF0JbZTyA+PNFljNcnNykmX5J2DBtuHqVYaXX7+CLF9QjqVRChBAOJvly6AhwQIMAV1VVQZNULOMBHAO2Bw7dvs2w3dgCKD7HNkBAAGEt2OyGJImQKEhwMXFxaACTBdyMjIMwoKCWNW/BtYjd588YbgKjO8P376BS1igcGIZno4JQAAR7JotgLbh/iF1zViBDRchoCP+IVVkr4CW/wAW49CKBtw1AzInlBHomgEEEEEHIINZDAwOQAsc/uHonP6Hdk6LSeicAgQQ40B3zwECDADHffpXRiyNMwAAAABJRU5ErkJggg==
dialogwarning:app:apps:32:data:iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAYuSURBVHjaYvz//z/DQAKAACIbnfZhUDzmyaAEZDIBMSO55gAEEBM5mi74MjSyMzHc42FluAt0RBtQiINcswACiJkcn7MyMawT1GVg4BRnYPj3hsGGl5Vh69FXDG+A0n9JNQ8ggEh2NRsTw3xmoH8lXSAYxA6QZZgElOIlx0MAAcREYtAHAiPbHmYxzCHAqDCZZ80QAlTCSWp6AAggkhzAyMjQzwEMdkFLPQYGs9NgDGKDxHQFGWqASviAmJUUMwECiImUhAf0mryUK1CLQi0wyYlBMJANEgMmSsktzgxVQKVcpJgLEEDMxCY8FmDcCwE9K+IdzsAgHg8U/Q/BbFIMbFzPGH4/u8rA+o5Bg4uFYdfx1wyviU2QAAFElAOy1RkmsHIymMuG8TIwa09kOH7qOcOWLacZzpy5w/Dnzz8GWTUrBg7WtQwfL/xil2JjEF50l2EHUNtPqCvxAoAAIuiA874MjszAuBezY2Lgcy5lePfHlGHv3gvA9MDIwMTExPD06RsGAWEZBjE5QYb/748w/H/CoKElwHBp+1OGO0DtfwiZDxBABOOKCWg5myADg5iXCgODUCDDjx9fwOKgIvzfv39g9ocPH8ByYl7KDCC1ZiIMtdAEyULIfIAAYiKQ8BKBCU9f0gdISuQA8x0bAxvbf7DlMAeAsLAwG1iOQTKDAaSWk5lBfZkdQwI0W+K1AyCAcEpe8mMQAPq+j1sZ6BVLO2BmNwaK/mAQEWFlYGb+D4z7P3AsIwNK+N/AavjMTRlAerT4GSr9ZBlkCWVLgADC6YB//xkagJSATDTQcNE4YCHwH+wAEJaX52X49esXGAsIsDKws/8Gin8HqgEmfLEYBpkoNlDU8WZpMFQAJbjxpTWAAGLCle2ABuSL2ANzmYI7kAB55CvEEiCWkmIFpoUfDD9//gSzIXIg/JmBgV2SgU3elgGkV4qTISZXg0EHKMGOq4QECCAmnOU9MPbE/IQZGPjdkCwA4S8MsrJMDN+/f2f49u0bg4oKG8Rihk9QDGQL2jOI+fIwgMyIVGToBQry4AoFgABiwlnehwJ1SDgD0zEvwmAw/sIgKPgTiP8zfP36lUFZ+T+SPIh+D9TDCdRrzgAyg1A9ARBALFjLe1mQJySAsWcCFHmHxa3/gAnvL8Pfv6Bs+AFa6IEwKC38gmR/bi0GQbvTDG/2f2LQ/QeuJzZCC6dfyPYBBBAzenkPjHt/uQxgNCh6AH0iBI33H1D8HZLagWxFRUYGbW0WBm7uH/CogdDfIGxGoF3MTAwcwo8ZPh9j4PWWYeBYdp/hMNQB8BISIICYkbMdMIBWCNmAyns5YJViADXsJzzxQfjfwRaxsX3HYjkyGxglLOwMbAJvGH6//sHA+pxB4/E3hjW3PzF8RC4hAQKICSnbTWDhYuAXCwZGE5cqNOjfQjEy+y3Dtm0PGdzdLzJYWJxjmD37Hg61HyCYS4JBLBhYGHAz8BZpMTSjZ0uAAGJGKe/9QIWOJFC1MFrQf0PCXxmSkl4wvH37A1wOHDv2kSEg4B8DHx9CHhFaQMz0D5gbfjH8B6r9f5tBQ0eA4eK2pwx3YaEAEEAs0PK+nk2UgUHYB5in2UA55g3Ubdhy6X9g9vsCzAH/gInwL7go/v//LzRa/4ITKAQjsdmBVaQPE8P7Q/8YDH4zFAEF90HTwm+AAGIGlfegQkcmF5hPlICWMzMi+fwHUkgg0oCg4C+GzZt/gYvh4ODfDOHhP+GJExMD5Rh/MTCx/mdgE/vH8P04g5S9OMPbNQ8ZLoAcABBAjBf9GB7w6DDIK7WAfMcPVMwCza7I+D+U/gcPBQT+h8ZmgPr+Pyr+DwmRe8AM+e4Sw3PTLQxmQIFXAAHEAmpmMQOTxderQCuYYMHGCC4QoCUDSvBD62I4+z88yJHF0S1HqAfZBWq+QVvRHwACiOXHX4ZpDCcZsj6dBFrFDAwyJma45YzIDkHqwv1HdggMg9QhWcQArbJRGkVQ5v0vDKuhCYwJIIBApnOU6TAYirAzaP76x8ACzI5kd7OIAVc/MDxb+YDhIaTMZngNEECMUJewQ8tqVkr6eUSC/9AyG5SqfwIEEHJEM5LbvyMDwFMuQAAxDnT3HCDAAN6sBt/v91SLAAAAAElFTkSuQmCC
Added lib/Icons/InstallJammer.crystal.png.tkico.






























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
actcontents16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAPpSURBVHjaYpSsf85lyvzymw7TO4ZfDEwMyOD/f4YgVlbmoH9//8Z8/8vEsPLyX4a3b34wMDL8h6sBCCCmf/8Y2v7+Y1AFsjmRNf/8/ZdXR1280dZczu3Pn3/yjIwgE8GGMiKrAwggJn4uJg0pfqZtf/79nw3ks4AE//37z8DPy5Hu5ayoY6IrJsrPy+7188cfj/+MjKuZWBhj/oOMAJkIxAABxPKPkWkNKw/XbLYfrCp/GRjP//z9p/fP3/+a1ibSlaKCbAxA1zHoa0u0GTExMrOIfObdcOaz6NMbz1czsDL/AFkGEEBMHz/+3PWcgeeWoAgvg4IMf/Hf//8tpSR4C+zNZYRACpiBwSIixCmgLCPAa6HIySAlyGIP9IQa2GSg/wECiJnXpuDjt7+M+hIMX4w0ZLh5JUT5HLXVReyU5HiZQQb8/s3AwMrCwvDy7VcG5n9/GN7+ZGC4cvfz53+fv+1hAHoVIICY/v/4xfDy+det79j5v794/YVBU11EiZ+PnQ0SFsDA/PmPgZeLmeHL118M4mK8DCpCjAwiwhyBwFAWZvj5iwEggJj+Ag34++v31kuv/j16+vY7w9/fvxjevPkK1vz793+GP3/+Mnz//odBSICL4fuvvwziXAwMehqiygy/fjszfP/BABBATP///WVg+Pv399OXv1Z95eRnuHP3PYOwEA/DnQefgYHMCDTkH9CQfww8QFe8+/CDQUVWgEFBhJGJRYDHm+H3XyaAAGL6/e0Hw98f3xm+fvm14sabf78fPv/MwMb6n+HFq89A+X9As/8A4/4/w+t3Pxg4OVgYJEU5GWR4GRlU1CWcGL7/lAcIIKZ/QH/8+/mb4cfHL7cevvu359N/VoZHTz4zCAlyMjx9+okB5MBfQFe8ff+dQUGKj4EDGDxqklwM8pLsMoxcnA4AAcTMrBTL8P8P2Bv/Pn35wykuwunH9fMrAxcXCwMLMyODAB8nw52H7xkkhLkYhIGGPgeGz/0Hbxk4hfkYrt39LAwQQMwsagngJAny758fv66+/PJPR06ETYPx+xcGXj52YGAyMnz59ouBi5ON4ciZxwynL79kePHlH8OX/5wMV2+/ZwAIIEYO/0OIhA1074/331R0tIX3xJuyyfOx/GaQlxdheAkMj+dvvjG8/cXKcOfFb4ZbD37cunbq7rb/7z8tAgggRibrTcj5j+HfL2DK+fM/xMtDfkWYGScz4+8fDO9+sTPsOfOR4eKZ55efvPq6AJiqNgL9dxeUTAECiJHBYCVKFgZnkr9/GVjYmftUNEVzRYW4GK6evH/m3ZP3bQyfvp5kEOJ9xQBMOwzAqAXlS4AAAwBL74x8VYLyagAAAABJRU5ErkJggg==
actinfo16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAALpSURBVHjaYmRAAypxuxP+//kb/+/3H4dfTGwMQJqB8fNHhn+/fh8A4oWvjicvQFYPEECMMIZa8n6F/3//rv/BwmXgaS3L4GwszsDHzQpR9PsXw64jjxjWrr/M8PnJiwtAQwM/XMt7AJIDCCCwAWopIM3/zouqKAi0xSgxyPIyMPBzMDDwsjEwvHz/g+E3MwfYoI8/GRhqJ55iOLz26Id/v/8afnlQ+gAggJhAEkDN6wUUFQQqw5TACh9/ZmAAWc7GzMAgK8LBMHXJcbDYp18MDKWZZgx2fuYC/37/Xg9SCxBAzKqJexN+sHJlJIfoMjAzQmwBYSYg+/enDwxLN55neMcswMAlLAqXU9CSZTiw54bE/19GDwECiAUUYAracgzfgKY/+IUInAcfgH7/ysAgKKPJIAg0AMQHgZ9/GRgefWJgELU2ZXhw91E8QACx/Pvz14FDVBSuAAQClX4w+GiD/C0A5ttVHmeQMrNkuPiKgeHGO6giEQ0G5t+/HQACiOU3MKpe/2Jl+I1kQO85DoYfwNAJ0YTwLz3+wHCYDy2+OTgY/vHwMQAEEMgFDM+/MDC8/44q/+QTgv31+2cGbOD/v/8MAAHEwvTlE8Pbj78Z/rOyQkUh1KefSAp/Ak37i6b7O9DG9+8YAAKICZgoDrC9fMzw9zcDBP+B4P//kAz49QViADK+dgUkdQAggFj+/fqzkOvBVQdWGSUUC0S5EWwxATaG76yoDvh84hAD0I6FAAEETomi5nPPs2rpG3DpG4Mlg7UYGLx4LjMAMwDD//9/wQk2fO4LBl4DX7D82x27GN7v2HmBgaHPECCAwAYIG81UAHrlvKCxkYC4tQUDPvBw4y6GZ1t2guLMEGjAA4AAgmcmAc1JCn9//l7PJSJkIG1pxCCuq8bAygnJA7++fWd4dvoKw/0dhxg+P3p2AZRUQJpBcgABxIhuA5dkWwIwnccDDXPg5OcFZ+cvL9+CAwyIFwI1omRngAADABJiJoABh/rDAAAAAElFTkSuQmCC
acttooloptions16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAACAElEQVR42mL8//8/AyUAIIBYQATjrC+LgVQMw58/DBD8C4h/MzD8/o2gfwHFfiNhY6sl/9N4YgECiBHkAsaZn/+f9uFleP+DgeHtNwaGN98Q9JuvQPZ3BoZ3QPwBKP/5JxAD9X+/sYbh/9IQRoAAYgK7A2gLIyOQBvmGEYzggBHKh9FwD//6AaYAAgjsBZCTTJY+hjr5F4T+/QvhdJDYr59IbCgGAoAAJIzBCQAgAALtjPbr03xt1iRBVo/jENF/kLDGFlThpopjywGuiUPs2xXU+nzTI4DgLmBiYmXY8HAjw+Xnlxluvb7JsDZ8LVgTMxNCM8gwEJsRiBn+/QVrBQggqAt+AhVwAP34nyEmLJqhbmodWHFWVhbWqFu6ZAncAIAAghjwE2gAIzNEctUScEiBnD179myI7XDnA21mBLkAGJz//oHVAwQQ1As/wRoiNCIZorVjIP6E+RuGGSGamYDRAYIwFwAEEMIFQA0rri8Hh8HN17cYtiVuA2tCGADUBsVgAHUBQABBDfgBthUU09FhMQz1U+rA/MTERKxhsHz5crgBAAHEAksUIFv+A+GS1UvBqQbkz8WLFoFDHMQGewEZQA0ACCC4C0DxnmyUDA0wYNwzIjTCnY0MoJkQIIDg0cgfuZKB4e8fhOkg/B9G/0fQ/5FoIAAIIEZKszNAgAEAjw3NPZJiHw8AAAAASUVORK5CYII=
actwizard16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAABAElEQVR4nK3SMU7DMBTG8b8Rp8jqN1QsqBJLp7DlCh3gAs0hKJeI2GHoFbLRqUulqEvF8Lz6GmZIQkvbNA7Ek/We/dP3LBtVZYx1M/SCLSXYUsKfoK7Lx3XTN5otJbBIYOOhAhZJ3Sg8TIFZAoXvhw7YM3AP3DXVPbCD4h2XqYmCfrApMNvWhc0DVOAyNVGjjZYo9o1u+9K85vCCB2CdQ9rsXabGlhKoPC5TcxX6EAmPADmsgU8gPeq37wN0J2qRlAPypGpcx/mLH7ILuZb+DBKxgxE4GU3EBpbwNgkwN9HIL6hF5hNYfcGKgKqLQqAZ7RRhySAEwED4N1InGgEB+Aa87ozLxt8G1gAAAABJRU5ErkJggg==
appdisplay16:app:apps:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAAutJREFUeJxdkztvXFUUhb/zunPnznhMpJAIiFwg20gQiqSgsCwUCAUFAqVwgSIapNAgaMwv8C/AVAgJKb+A0i3I7qwUiMYydmJ7LD/kMTGea899nXM2xdgSsKq1i72099prq/n5+Y+Xl5ef3rp5o+N9EwAkgiAgjKFAXVFBsNbZF7v9l0+efPWFffz486/v3b9/+9dne7SyV7DWYK3CWoPWGhEhhIj3Ad8E6jqgY+DBgw86jx599qXNsiw7Hgz59qctbr5xm16vxUQvpdNNSRJDiJHisiG/KMmHBWdnI0xZ8NvdOySJy6xSWhLnSDsZ3gtNA2UloBrKKiJRqOtAXQm+AR807TTl4uKC0ASx1hgE+OtkyA3l0BpCCFSFRRuFiOCbSFU2jIqa4rIiNAVFUQBgjdEYrTkd5JyPhNdenyTLElxi0VoBgveRqvLk5wUHB2e82h17A2CV1mijaaUJVRM4e3lJXTUkLTcWEKFpAkXRkA8LqtKjJlKC92MBjcZow0SvTVtZut2EVsvhnEGp8QrWBpRW4xpNK9X4EECD1WZ8W5NYlG2RdlLaWUIrGXsQo1DXHjVqCJSYKqKdIsZwNYFxKnGGD+/dAuvodBLStsO5sQcxRpraUxQNo1FNnld0XRynDaPs8+cvDloWfvzmLnUdKMuCy9EI7z0x+HGAvCfEiNEWpRwSI0ZFBoPBuZqcnHxzYWHhu04n7TaV9zMzM+89/OjhO9oYmromxgjA6emprK6uPtvd2f2j1W638jwvV1ZWvudfmFheXn66vb092tvbk+PjYxkMBjIYDGRnZ0e2trZkY2Pj78XFxR+ANv/H3Nzcp03TiIhInudyeHgoR0dH0u/3ZXNzU46OjkREZDgcyvT09CfXfeaa7O/vH56cnNzp9XpvO+dMmqYYY3DOkaYpZVmyvr5eLS0t/bK2tvYzcHn1qP+BybLs3dnZ2fenpqbeyrJsUimlhsPhsN/v/7mxsbHmvf8d8NcN/wBonYwccTr1JAAAAABJRU5ErkJggg==
appwinprops16:app:apps:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAAnRJREFUeJylk09vVGUUxn/nfe/MtNOZtoy0pi3QNJHAQkwKRNCNuCJuSGBj3LkwIWHDJzDu3GCiiZ/AlW78AIbACmVhNEaNYpCQDDBAhcIwk7lz733POS5u+RPjxvhsTnKS8+T8Tp4D/1OytnnhwvFjr3/gliQpJBVUQRWS7dQEas97poG8NO//+tnH2cGNXe+ce3djcTwpyQuYFrJToahgOoW8gKKEfCrkFVRVYHtk3Lu5+lbWXWgWayst1JqYgRkgQgTK5LgJ0+SoBcwcNcE9UGrGrd9jyhqNwOpKh+58+xnX/ccV3/Yrjq63mFTO4eUMcHDD3QEoq8jCnJAB7PQAuHJjyg8D5aEKl65t0ZyZ4Y31Nq8tCfuXA2VluNd4SbU2eFGXfxuy1erQ3H7Igz/63Bomrq7t48iBl/n0RMQF1LxGdSW8OLw9VvpFiz0vzXLm2DJffvgmn587zGrLuTJQPvk+oUnBHVPD7R8GQeDyzwOuXn9E3mgRxDnySpvzJ/eye1eHm0NDk2FWG5hbbSAiACy0I1+8t4deI/DnGC7eDvQfOXNzgQNLgjUytsZeb+AOpmQBIcZYp0qgN9/g2mDIjQcTjm50ebJ/nlHhzIeC767fJR7ajartHN7qI4ZYk7g7670m7x+aAVXuFDltm+Gbn7ZYXOzy0ds9em2YVoaZAEoWsyit5tMNhM5s4OyJJTDlqx/HhGnJqYNdhnlic+8sZkYWnRACEkSy4aiS7ZEQI2iqk2iqmDvHV9o1pwTcI8NRwswQgUleMB5NosTOq6dX922eCWJi9jRRhgEBMK3AFUxxEnhCUMqq5K/BL1//t9/9F/0NKrFMKr3z3WMAAAAASUVORK5CYII=
folder16:folder:filesystems:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAB/ElEQVR42mL8//8/AyUAIICYGCgEAAHEqKZt7ReXkLERm+S0ye1uTx9e3Y3PAIAAYmzpXvy/uiQGQ+Ln7/8MPROXYtXU21mh++71kysgNkAAscAEHz99w8DMxMTAxMwEpBkZmJmZGbAZDAKfv//fwsjIbv7//8+XAAEEN4CLnZGBlRmkEYSBhjAzMPz68Z3BvOgZFiOs5A0yr73glnXxBwggFmRh++p3GEpnFckxMDKzMrz7AoktJkZGho+ffvx78+H/hxkMMzcCBBDcAJe6DwwLqxQZvv38z/DnLwPDXyAGqmU4cY+J4frTfww//wD5/5kY2IA6btz8/Hf/iR+3DLQZLAACCMUF/4Eajtz9z/DtBwPD95+MYPztx38GkN3MDIxACHTBPyAbaDjD7//gJAAQQCgG/PzFANEMxD9+MTL8+s0A1gwyGawdpBGEgXIM3yF6AAIIxYDffxnBBvz4ycTwA6gZ5BWY5v9/QAqAXLSECxBAKAZoSjAyCFozA21lhFoN8jcDhA3CQOf/+/uP4eNHTpYEVw71nu0vGQACCMUAIR4QZiSQeP8y/P/LxKipwszfs52BASCAUAz4AXTm+0/AsAAG+a/fQPzrDzA2/kLcDUR///2H8v8xvP3MBtYDEECMYhJKllKBu46Rk5EuzncwAgggRkqzM0CAAQDWqbzmpJES5AAAAABJRU5ErkJggg==
mimeunknown16:mime:mimetypes:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAABl0lEQVR42mJcsWLFfwYKAEAAsYAIbuVwhvcfGRi+/wTiX1AaiL9B6Z+/UDX9A1opLsrAoM++kgEggMAG2OswMHz5xsDwHyjx9x8U//3P8AeE//xj+AfUAcL///8DYiAbiHl5uBjOH2VgAAggsAG8HBCMCoCmATWA8L//f4EUUOPff2DN/4BibGzfGc4DVQEEEAs2f4FtAWr4+xdi4///jFD+f4Tcv79gtQABxIRdM0wjKobJ//79G64eIICY0DUjK4RhZANBmkF8ZmZmsDqAAGLB5gJs+O/fv2AMYoM0wwwACCAWfBph4iCNf/78AfNhGhkZGcE0QACBDfj16xfDz58/GZiYmHA6HyQH0wT2O1QtQADBXQBSCMLoAKQJphhmGLILAAKIBeYsmNOwAZDib9++Mezbtw9DDiCAmGAGgGzBhUHyMNeFh4czBAYGMuzfv39SREQEB0AAsaD7CRtA9v/r168Z8vLyWoGZsA7kK4AAghvAwcGBN9fx8fGB6bCwsJwDBw5MhYkDBBAjqdkZ6AVG5NgACDAA4TMV4APib38AAAAASUVORK5CYII=
filenew16:file:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJnSURBVHjaYjx66tobAT4e9n///zPAwD8g88ePnwy/f/1mePPuI9Of3//ef/78xYOZheUKExMTw+1bNxkaqjPAagECiIWdjY1bU02GgwEJ/Aca9uPXP4a/fxgY7t5/zMDDzcl198Hz/U+evQxlZ2c/gKwWIICYGLAARkZGBqBFDIxM/xiYmJkYJCRFGBysdUXUVeV3srKwhPxDOJYBIIBYsBkAkmcEYjY2Fob7Dx4zvHr5koGLm4Phz++/bJ8+flj979+/IqB0P0gtQABhdQHYFUxAVwBNERURYvj1+z/DyxfvGe7cfcLAxsHG8OXLhzaYOoAAwuoCkO1MQG8AA49BT1ed4eeP3wzv3n8EBugHBlZWNoZTJ47C1QIEEHYvAAPx799/DH8Y/jJ8+PANaOMPhp8/fzGwsbICDWBhYGZmhqsFCCCsBvwBhtLnL78Y/vz5w/Dv739gWLACvQSM3n//GFhZgGxGhFqAAMIw4DfQ5u/ffzMAKbBnmJgZGVgYmICa2ICu+gN0ASvUkxAAEEAsMPaP33/BzN9//kJjgAloOwPY5j+M/xgYwSYCnc/CAo5mGAAIIBZYNPz58w/uNEagrQx//gMNYoSkCSD+D/Q2MFkwMDPCIhoCAAKI6R9yyIMTESgtoyYzUGJiBHuDEWo7wgUAAYQzHRALAAKICWbC/3+QTARyHZhCSq7/YWn3PySKkb0AEEAsMDkeblZEbgRicJj9B4UNME0AFf35+5fhHzCgWYAJCTkQAQKI5eOnT1/bOif/YWJigVryD+zf/0An/Qe7BpIzwDYDMSMwWr58+vwTZgBAgAEASRjbgDafxqkAAAAASUVORK5CYII=
fileopen16:file:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAPKSURBVHjaYvz//z8DJQAggFhU4q8xWJuIMHz9/p/hL9CsYydeMliLf2SQ4fvD8PMnA8P3X38FuLlYm7g4WH2ePP1kCVTy8tN3BgYWJgaGQ5d+MwAEEAsuk/8BXfb9+287VWWRDh8PFUs+PnaGutYjdW/efcvedZaRgQFoOAPzPwaAAGL59+/fvF+//7P//g1xwe9f/77+/fuviJmROdvNWaHKzVGOj5ODmeHXr38MjnYKsctWX1nJwsJ06M8/RrBFAAHEoqHKm5gYL8Lw9hMDw9c/DAzaGuwMP68/9EkKlJPU1hRk+PaNgeHLl79AJzEwONvK8B469aLz78U34UDrH4EMAAggJjZWhi+CAkwMnBwMDL8efmDQ/v+eoSlfR1JXW5Dh928Ghj9AQ5mA/v377y/Dqw9/GHS0RCwkxf4GMPz4Iwz0pzBAALH8ARkOdPqLC28Y9Hn/MFiFKMLDgZ2dgYEN6NJ/QC9Uzn7McOn+HwYpcW4GBX2VZlFVRr+bl57/BQggFqDBDMxAG36wczKsOvOG4dz7Twy/f/5m+PP3L8NfoAtAAXPl9keG+x+YGeR05Rme/WBlEDSR4Xtz/KXDn69PzwIEEMvf//8YWIC2HLj4jUH0PyuDqAArww9mdoYP3/8xfPz8j+H9l/8M3HI8DDqa3AyXgL7+DhR/f+f9v8f7rzIx/PuxFyAAAEEAvv8E/v3/APD0AADp4vQAi3shAPb5/AAFFwUA1OMBAO7a/wDq6f8A4+j/AOvn+ADv5O0A8dvmAPnl8uYABfoKAAf+zAKIhQVo/bGz3xk05XkY2IWZGE5cZ2B4++Afw4PnzAx37/5jePLoB8Ozp78YPjx8y/Dr3XuQE4AhxviPgen3I4b/f68BBBATA9D5Fy6+Y7Az5mS4AZR//J2N4SrQgPcf/zH8/vOP4cev/wyf3n5n+AVKOGycwCQIjC7GvwLAFHOV4S/DHYAAYnn46CeDpiobg6QYBwM/UI0WHwODkAwzw8d3vxmkmP8wCP78xiDB/JfhNzD5/gUmlJ9f/zA+efyP5/Wzv5cZGBn/AAQQy/07nxmcjfkZ3ICGgFzDADT7hyQDOAF9+/qP4acFC8M3YMB9+fofyOcBpkgOhpb537+/fvTvLAMzIwNAALH8/vKTwVWfG6IZBIA0BzcTAzMzC8P/f7+BGoDR+QdEA73x6wfD1x+/Ga7d+PwMKHkcmMQYAAKIkcVw/3tTMxEebnYmBmDUA1PNX7Dff//4BfQ3CP9k+AXU9AfI/vMLlEP/MLy6/2cRwx+GZJBlAAEGAJ2gomER8m2dAAAAAElFTkSuQmCC
filesave16:file:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAALYSURBVHjaYvz//z8DJQAggFhAxJKlR+5xcrEJff/6i+Hf3z8MX75+Z/jw4QvDly/fGL5+/cHw7dt3IP7B8P37T4Z3778wXLx49eOH9/eT//+/vgcggBhALli3/vTXTz/+/f/379//acuO/g/Jnv3/xMVHYD46vnrv7f/i2hX/2dnMn4H0AgQQE8gFnz//+P3h82+G778ZGE6cv8Pw4Mkrhr9/sXvt9bvPDF9//2Hg4OTiBfEBAgjsha9fvzF8BjqVk/U/g6eDPoOdpTaDtqoUVgN+/PjB8OThY4bfv3/9BfEBAghiwDeQP38xPPv1i8HGRBVo+1+G1++/Mjx7/QfM/gd0ze9//xi+fP7KcPL0dYZPnz4xAL0DNhAgAIdzjAMgCARR9N//lhRUhsWYjbCjIa4Uk9+9zAbcB6GXUs/ExJjBPf8q4eByx46ONUMhntxa+wCfAIIYAAz1z0BD/gMhHw87AysrIwMzIwPDf6CLvv/7xcD48ycDO9N/BiFeLoZXQLFPnz/BDQAIILAB30DR9vk7g5IMH4OptjRYAuhyYOD+BUcfCH/58gMo+p9h4eo9DNcuXYEbABBA0ECExPHPH38ZXr38CXQR0GZglHwHaQaKgwz4+vUnAwvQWV+BBv349o0BlgABAgjigu8/GD4CA+jjJ3aGP38YQdEKTzgwF4DCgpkJaMDXrww/fwK9+x/iAoAAgrrgO8ObN+8YhLjYgd75BuZ//w7RBDPo+/fvDEyMTED+V2BAfgPqgsQCQABBY+EbMOkCE4gQP9AVwFD/9B2sGWQIDIMMAhsANOzPn59wAwACCGLApy+sH16+YXjJzszwU0Wc4devT0AMjFpg6P8ARumvXz+AGKjpPyPDh9evGf59/wTUxcgK0gsQQIygwODn97jHxPhfiIHxNwM3Nwc4kfz9+w9sCyhJg9TAEs7Xrx+BqfAzkMX6DpiZlAACiJHS7AwQYACwk94yqAwVDQAAAABJRU5ErkJggg==
filesaveas16:file:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAPiSURBVHjaYpw/fz/Dhw+fGT5+/AqmP336CmR/AePX738y6PBdYJhsfYCBQUlq3SeOeON7mzcu+3D9ei8T8/83DEAAEEBM//8z8P3585f/16/f/L9//wHjnz9/8f/48ZOf4c83/kP35Ph3v+R3FrB6ESBncV/OLie2QkhOOOK/AD8Dg5AAA0AAsbCysVxQVJYSkvj6i+Hf3z8MX75+B7rkC8OXL9+A7J8M79/9ZWDTPMLJwPCRkeHMCoaP53cz5B/kZL7+WQxo/z8GgABiWLf+9NdPP/79//fv3/9py47+D8me/f/ExUdgPhi/PfP/3zW2//8OMf//N5v3/+YEw/9MrNYPGBg0uRkYtBkAAojp8+cfvz98/s3w/TcDw4nzdxgePHnF8PfvfwYY+Pt2GpAE8r8KMvx6zcdwls2egYubTxhoOytIHCCAWL5+/cbw+esPBk7W/wyeDvoMdpbaDNqqUhDdn+4yMPzez8DwS4KB4TsHw7l3ogwXv0kz/Pt19i8DA+N/kBcAAojl67cfDN++/WJ49usXg42JKtD2v8DQ/8rw+CUDg+iH2QxigkCLPggw/P/EwrDrow7Dmy/AsPr3B+q+XwwAAcTy5ct3hp+//jA8fPqB4SvQoO8/fjJ8+f6PgeHbM4Zo09NARUDX/GdlOH79J8PRN6IMv768BxrwD6QZ6II/jAABxAIK9c9AQ/4DIR8POwMrKyPDP6CUIscJBnFpHgaG92wM/97/ZTj6XprhFwsvw5fPr4AGAAOM4Q8wHhmZAQKI5Rso2j5/Z1CS4WMw1ZaGOOzLJwaGp++BLAlwTL1++4vBPjSL4fHeqwxrz54CGvCXESgJjAWG7wABBAzEHwzfv/9k+PnjL8Orl0DnfwPGyPtXDCqsigwMzFwMDD+fMJx5ysDwHOjvty9eAtV+Zfj/HxiGDIxgywACiOnb9x8MHz8Dky8wCf/5w8jw+fMvcLL++VMGKG3NcOzgP4ab/3QYPr5/Dwyjrwy/fv2AGsAACsmvAAEEdMF3hjdv3jEIcbEzfANGKYj/BRjS+48eY+DkusVw8YsOww8WHgbmr5/BLv0DjC1IwmB8C/Tfd4AAYgElWVAm+irED3TFT2Bm+g6O1jevGRneiWgx/GbhZPgB1MzOxgYO3D//fkH0M3D+AzkCIIBYvnz6wvrh5RuGl+zMDD9VxBl+/fzE8Pv/HwYW/QAGnu9/GL5/+8Lwnx1oH+Mfhk/v3wHt/AjyPzBxsDGAMEAAMfLxud9jYvwvxMD4m4GbmwOYof4x/AVZBQx+UHz/B2ZXCA308NePDL9/fwbKsb5jYGDSBzI+AwQYABSR7Xb1rpT/AAAAAElFTkSuQmCC
fileclose16:file:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAOVSURBVHjaYtTUdGdAA4K/fv3U+Pv3rw+QLfT//3+Gf//+vWNiYtjCwsJyAyj2HiT2//8/sGKAAGJB1gkU9Pj581eNnJyctaamMgM/Py8DIyMDw+fPXxlu3rxfdfPmjaPMzIwtTEzMO2B6AAKIBaH5fw4LC1tHeHgQt7u7PYOOjhIDNzcb2IBfv/4x3LjxiGHr1n3WK1duXPPx45sKJiamKSB9AAHECPIC0GZ3ZmbWzQkJkazu7rYMLCyMDD9//gYZCzWcgYGVlRUozsxw9Oh5hv7+Gb8/fXrnC+TvBAggZhERZb7fv3/PdnCwV7C3twT69w+DlpYcw5s3HxkeP34FdP53IPsDg6qqNAMXFxvQIA4GoGXMFy9eVgK6eg1AADH9/ftbW0hIxEpFRQms0MBAlYGDg51BQ0OegZ2dneH58zdAMRUGKSlhBnFxQYY7dx4CvfSHQVBQyAqkFyCAmIWEFDOlpaVtgQHH8O7dB4aXLz8wqKjIMHBysoE1SUqKMCgoSIC90te3lGHNmu0MDx8+Yfjx4xvQmz9eAgQQCzAwhBiBIfX69RugwC+GR4+eAl3yliEx0Y+Bl5eDQU5ODBwG3d0LGdau3QH0AjMwLFiBruQEBjCTEEAAsYBC+du3HwxPnjxnAMY90JCfoLBlePXqLdAAabDNX778AHvl37+/QP9DYubfP0haAAggJlAi+fr1M8Pbt2+Bml4z8PBwMxQURDMoK0uDbf78+QfYJY2N2Qy2thZA//8CGsIMtOg70MI/7wACiAkYkluAfmH48+cPMOHwMbS1FTJoaspB/bwYqHE6w4cP3xn4+DgYWltzgAGqywCMNbABQBdsAQggJmAsX/3+/esxkPNAoX7jxgNQomKYMWMtw65dRxkuXLjGMHHiEobv338x3Lv3DEhDLAO6+hjQq1cBAohRWdkOqOGvOwcHz2Z1dU1WcXEJBgkJYYbbtx+AExIogH/9+s2gra0KDOgPwLTxmOHKlfO/v3z55AtM0jsBAggYjfKg0Lz769eP958/f7FnZ2djAyYUBhERQWBUcgLDhItBWFiY4f37j8AYeshw/frVr1++fCwFal4O8iZAAIENAKdpRoZTwLg99/Llc8VPnz7JffnyFWQwMAa+Mdy/fw+YmW4w3Lp1/eiPH19zgJqXwfIQQACBvQDNiaBsC/K/IDCQNICKfNjYWIVAYQNMH++AIb4FGPrg7IycgwECDADIUZC5UWvTuwAAAABJRU5ErkJggg==
actexit16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALiAAAC4gB5Y4pSQAAAAd0SU1FB9EMHwAdGDQ8O6gAAALvSURBVHicTZJfaNZlFMc/55zn+e337n3f2eZ6l272blQUG27lGoQW2YV0lXfhRXrXBhZEkFdhXQRFBUWQRcyorCDCbqIUjAIp+rNESxNdNGnpmHM2W25ue3/b73m6eMfocA6cm8+XL+d8BeBQWzoYs3y4ua+HsFQjApLn5ESIAfIIBEIOmghzYxP4xoah3ZPzB+VQWzrY1NU13PvcE1z5+hiSpogB6lCDiGBOCKpgivOehsp6zrzwIfncjSH5oNnH+z96jXOvvkRycwXxhjmPOKVyzzZUjaujJ1HzqDMwQ52nfEeVk/vexN3U283fP31P0tqKFQsUyi30791P2rOV/9f86eOc//w9VrJFxIx8YYF0Qysu1jLi8gqSeArlFrYdOApAbXSEiRPHaWhaR8eDOyn1bWeg+15Ovf40y1mNiBBrGRoB8YI5T//e/QBc+uwAP7/9PJXNAxQrHfzw8pNMHn0ffInbduxCnEdFIUZU8hzUUWq/lbRnK7XREca//QJxjnLnXTR39yPOcXHkGMxdYd2WHYgpUZUQApoTUYPixirAGixmIAIIYoaYMfPbCADltg7EeQgBJQYigqrVr6W2BoDU2wxxCaICgC81I+pWBfKIOWHx2hQA7QMPrQIOBBCpw6a09NY/szhzGa9GHnIUAkGVhZlpmJ2k1LedSs8AYsbytWmuXziLmFK972FoXE/252nUp+SrDlzIWQ2H8eu7L3L3vre4fc+zVMfPMHV2BFFhy+5nsPZuIGP8uyPgHOa0LqCJooA4x+LsNKdeeZzNu57Cd/ayqbN3LUhh6g/GvjrMcp6RFJvIV5ZAwc2NXaLQcQvZP/N121mNXz55g6RUpqV6JzjP9YkLqE/BOXxjiWK1i4tffkq+BPZoS+Pk1R/PP7Jp5wNY4rBCAz5NwAm1xX+p3ZjFOyOYYE6xxhKXvznC7+8cJmkqDwnAxxvLgytLS8PphlZiLYMYCSHA6uQhX9sjgZApSVNx6LG/Zg/+B3yOCy8hh4B0AAAAAElFTkSuQmCC
edit16:edit:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAANESURBVHjaYjxx5tZzXh4OHgYk8O3nb4YfP/8zfHhwjkH3aTHD97+WP8+sP7Pw7d173UxMDC+Q1QIEEAsfH6eAhoo0B7Lgr9//GH7+Z2L4+KafQcrgMQPTX2keaVa1onU9924wMjLMZmBEqAUIIJb///7/YUADzKxMDP+fvWQQZN/EwPQaKHDxBMOni0xfPrJwX//99y8D43+EWoAAYmHAAkAWML9ZxsDB8JiB4T0DGJ/nMOb+kJHX9vXzu3hGBsb7rGxsDKwsbAwAAYTVgL+fPjMwf1jEwPwbyPnOxPDsKSPDV4swRnYedttH9587cXJxzb1x5hrD7ZuXGQACCKsBDB/3MzD/ucjA8ION4f/LvwwvpK0YZF2CGb7dvs5w6fvnn2/fvGTYs2MNUOEfBoAAYsKm///DyQysvJwMDF84GN5/5GP4ouHHICQjxcDM8JeBhYWV4cqlK0BV/4CYjQEggDBc8PfFCQZmjltAzcCY/cTA8I5HjUHQIZSB8/9PBj4eXoYjBw8x3LtzHqiSlQ0UYQABhOoCYAj/ezaPgYkDKPwTaPMHHob3Mp4MglLSDCzABMDIzMjw5vVLTpBuIBYBYm6AAGKBRelPUNS8uMjAwv6QgfGPIJDDzvDqOzuDaFAsw68vHxh+//rJ8OnjJwYmRiZgmmGEuZwXIIDgXvgH8tLfH0CGNAMDBy/Dl+dPGd4IWzNw/GNm+Pn6DVAjI8M/oAtBQQQLKlAoAgQQE3Lc//nNCExELgx//7gyXLwmyPBb1YHhDzCd/f33n4GFlQWohhGkC6wRiD8A8VuAAIK7gJWZgeHhy28Ml/YdYZDm5GZgtM1i4FbSZPjz4xvYMmYWJgYubm4GJiamr0Bn/oZgJgaAAGJCdtOP738Ynt96zsBq7M8grGsODOMfDGzAaBMU5GMQExMHuoKZwcbe8begkCwDIyM4EhgAAoiFCQjBSReINY3NGVQMTBmYBYSANv9m+C3Ay8DKzgb0+38GNjZmBmZmFgYuLk6m8KhYhlu3bjLcv3OdASCAWO7eefhh1Yo1PCAnMjIDYwcUWH9+AZ3FDHTZX4b/IE8Dw4CJiZHhAzAWgGHx68vXLwwKCooMqqrqDAABBgD54A4xrMo1ZAAAAABJRU5ErkJggg==
editcopy16:edit:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKbSURBVHjaYjx69NZ7QUEelv///zH8+fOP4d+//wxMTMwMV6/e47l48UYSKyvLfAYg+P37D4ODgymIyXDgwGkGoDiYDRBALJycLDwaGhIQHlghA8OXLz8Z2NiYQdx5V67cEmFiYur+//8/AzYAEEBM6ALMQH1sbGwMt28/ZXjz5j0DBwd7158/f2tZWJiBLmPEMAAggDAMYASq+fv3D4OengqDmZk2g6amElCMUdHS0oCBl5eHAd0lAAHEgs0AZqAzPn36xvD9+y8GPj5uBktLPTtRUYFZwHDgBCrhBhqy/d+/f7OBXmMACCAMA75+ZWB4//4LMBy+MBgZKQFtZQMJKwPFlT9//goMo79ANT8CgWHDDzSwByCAUAz48YOB4du3H+BYALmCnR0hzc3NAIwhTobXrz8wfP78GRg2HN0/f34WAwggeBiAvPbr128GFhYmoCQLyN8M6AHPwsIIDGBWBklJUQYVFTkGLi6OQoAAghvw6xfI/8zgMMAFQLHAzs7KIC4uzCAtLQI0kJUBIIBYQAGBbAMTEwswFkCKMSII6L1fwLD5Bk5snJzsYFcCBBDL58/fgX76DcQ/wBLA0AUa8B/ooj9gBTDw+fM/YOD9BHqLERgenOAwYgEGEUAAsezceXwZEKNY9/37z++6uqpOFhZKyrDA/fPnN9D/LGCXgbwCcSEjA0AAgYI5HlkzyGYJCWEQngd0jDJI3d+//4A2MgEN+Q+mQRgUXiAAEEAo0QjKMKAQNjHRAIcDyCt//jCCbYIkc0awN5EBQADBDQDZoqwsy6CvrwZOrv///wZrZGVlAIfFv3+sQPofEP+BplgmsDhAALEgJ2FgCmM4evQ8NF38/3nz5gMQ8wuUD3YVhP0XrP7Ll+9/AAIMAI729YDbYvpsAAAAAElFTkSuQmCC
editcut16:edit:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAPqSURBVHjaYvz//z/Dqg1nGf79/sHw/9dXBgYmJgYY+PePgYGbmz1ASkps/YcPn3yYmBi3Pn78iuHXr18M4uIiDAEBNgwAAQRW/WF/HQPTi0MM/JKKDDwCAgw8PFxgzMvLySApKTJLVlaU4dOnbwwfPnxnuHHjHtAORhGgxXkgvQABBDbg8+XtDH9P9zAwbvNl4P39kIFXSJyBj48TiEGGcIh+/fqN4f37jwxHj54DKRcUERFaoKGhMBHEAQggsAHMnNwMf3/9YPj16h7Dnx2pDJ/u7mF4+YGR4c2bDwzv3n1m+Pz5B9Dm+/9fv34vqKoqt9bf38b7/fvPb0F6AQII6uH/DIxAvzOysjMw/P3BIHymmOHXg50Mz9/+BRryCej0jwxXr95WMzXVWh0R4e54/vydv/v3nwJ7ASCAWBjQASMLA9u/bwzcL7cz3ORWY+Bg+sXw9u17Bmtr4/bAQHuOLVuOfNuz50SapKToMpBygABCMeDvXwbBPwwMit8Yuf6p/j5+988Xps97H7oyqKgpMLi4WHAsWLjj45Gj5+IkJcQ2sbCygvUABBDYgH//GUFRFqiq8b9ZWo9ZmYWP+dfLM8wn9Z4fnXdb3O4/C7sQ48SpG548un0pRliY7yAX608Glv9fwAYABBDYACbG/0HWBr/XcvKzfPp6798ZURVGBWUnZtff/wScLR8dYzy2+TLDv4cvW2sNbhzk4fjL8OsvIwPTW0agzlwGgABiBCWkTfFsz7Vk//EdvMEVqiXPsI2ThSFSP4p5GYMMG8PXC78ZONj+AWPo343P35ieP7ryd8WPL/9nMQKD32byFwaAAAK7QIn7t8Tdh8wXz9xjOPfp638BG4P/UQzv/jNc2Pz3gpgKkz63GwsjJw+DBicrgwaHMKPj8Q1/Pvz6w7AKpBcggMAGPHrD+MNW8a/+x1/fNoqLMArKijKp7lvPuu/5C4Y4aYW/T74c+vf56SmGbDYOBhFpfYY+YSmGyDvXGTYBtf4ACCCwATvvcKb/+fujxVDmr9mLP8wvdhxnrv35h3GistT/z99f/mN4c5/h4JWHLMu+/fjPoc/wr4qN7b/s+2/MXCADAAIIbMDXX4yLTzxl3/Lz/y+eR1/YvjKwML0V4fnP8PbjPwbOh3/fSgj8NT54ncWMC5jOLDV/iTx/xXTp4zfm3yC9AAEEjQWG/5ws/9+xMTO8Y2cDGvuXgeH5ewaGL9+ZGB6/ZJyWYPqrNtroy1pmJgYhgd//GTbc5N7y5///zyC9AAHEhJ4QgYYxfP8BzKHAnA3MzQyvvjJ2zDrGMZeH8b8Y45///+ac4Oh78Ylh1tcfEPUAAQYAZbWKZF50obcAAAAASUVORK5CYII=
editdelete16:edit:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAMOSURBVHjaYjx66tobAT4e9n///zPAwD8g88ePnwy/f/1mePPuI9Of3//ef/78xYOZheUKExMTw+1bNxkaqjPAagECiIWdjY1bU02GgwEJ/Aca9uPXP4a/fxgY7t5/zMDDzcl198Hz/U+evQxlZ2c/gKwWIICYGLAARkZGBqBFDIxM/xiYmJkYJCRFGBysdUXUVeV3srKwhPxDOJYBIIBYsBkAkmcEYjY2Fob7Dx4zvHr5koGLm4Phz++/bJ8+flj979+/IqB0P0gtQABhdQHYFUxAVwBNERURYvj1j5Hh5YuPDHfuPmZg42Bj+PLlQxtMHUAAYXUByHYmoDf+/P7DoGugwfDrBzAwP/9kePf8OQMrKxvDqRNH4WoBAgjhgn9/GRiun2JguHmW4R+Q+wfojz+srAxf7t1jYOoqYmDdu46BlYsb6C1WBmZmZrg2gABCuODJLQaG4zsYGL5+YPj/6B7DV5sQhv8PbzIITqpiYN+7g4FT7hjDb20zBiYxaWAgI1wLEEAIAySVGRjk1RkY9qxjYL45n4H7zFEGpjt3GFgPH2T4LaXE8D6nkYFZRJyBlfEf1JMQABBALDD2DyYg0y6EgfHbTwbWFTMY2K9uZmB49Z7ht5YBw7u6qQy/FTUYmL98YQAmJnA0wwBAALHAAuEPMAgYWZkZWJg4GBifvmJgePaageHzDwaGp28ZGIGxwAjyO1AfMyMsoiEAIICY/sFC/vcvBrbFkxnYOysYGF5/ZPhrZMHwj1uYgfXsDQZhH1cG9m1AF3FyQW1HuAAggOCxwHJkBwPr1A4GhhdvGH5FJjN8XriT4WvvLIb/fPwMzK9eMQgU5zIwvXrB8B8YjcgAIIAQXjBzYmB08mP4L6PC8CulEJwffvv6MnxYvZGBq6yA4Wt6FsM/XqBhwLSB7AWAAGKBpWtuQT4GhvbpYClWIP77F5SpgLSLHcOv8+eAXvzPwP31FwMLCytKIAIEEMvHT5++tnVO/sPExALNB/+APmQCav4HNuA/NGf8B3P+AzUzMXz5BEyWUAAQYABehgBuH0rveAAAAABJRU5ErkJggg==
editpaste16:edit:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAADW0lEQVR42mI8UyvNwMnyl+HoO22G098dLGVkJBqkpUQEGYDg7dtPv+7cez5BheXUGg/R4wzffzIyfP/NwMDIyAAHAAHEwvD/v8DfX389/v7+LSEqKpyVmBigKiMtzAAx4APDjFmbNf4++qPz//ffu//+Mx8Ean/E9P8v3ACAAGL5x8mzXMbF2OPffmEGMw19Bi5ODoZHj16DbWFnZ2ewtzMRPrbvWr24Cw/DyzOXLn2/+9z3D6fwIwYGJrABAAHEwiItZiFotoxB5H4Jw527t4GaHwKF/wIN+M/AzPyT4e9fZgYhiZ8M4paSDF9f3dd79k1N/Bpr+KM/f/8zMDL8ZwAIIJavP/6BTXK2/Mpw/dYRhj+/gRqZ/jL8/M3H8OStNQPQiwwqijYM926xMHzg1WRgNzLo+X/l0dp//35MYmZiYgAIIJZPH3+DDeBn/85gbQr1GOMvhi9fmRiUf7gwKCgIMvwCKvn6hYGBQ+A/g+ivL3Z/GBjsrl27J/7z559qgABi+fzlF1jPr89AFZ+BHgciJqAB3759ZfjL8RvoFUYGdjZgeAiBTQZiPobTp76Dwqfq+/dfXAABxPLl2x+wAX9/fAO5FuxkJoZfDH9+8QKthDjoP1DsLzDgvwPj8NOn7wwiIvwMbGysDH/+/E0ACCCWf78hUfLn02egC4Bu/Q408M8Phv+MrAwMAoj4ZmYGYWYGFhYmBkFBfgYODjaGZ89eMQAEEMv/v1AXPHrHwPDzH9iV//8BQ5/lOwMyALng58/fDF+//mT49+8/0AtsYO8BBBDL/1+QMPjz4Qs8iTGCDGD9CfEyVPO3b6Bw+Q70zj8GTk52sDgTEzMDQACx/P/6CxoGP+C2Mf37xfDv7w8GmAm/fv0D4t9gLwDTFtAeiLdB9gEEEAvDb0g0Mv1EGMD49xdQEmgblP/nzx8gnwmcuEA0C8s/SIADLQAIIJan7xjuny7kNgSmCbgGht9/GH7z/WEQg3vhP9i/jMi5CAoAAojl+Qfm0EUnufL42f//+gc14e8vxl88IiySMcxMiSA+OzsrMOD+gg1gAtoEcvS/f6AwYGAACCAWoNhdFkaGfGDsMPyFpQOgR1nVfDUPHrwccZKN4f/fv8Bw/w9JDxAanPzZPn788hUgwAAU8lj2lXLEnwAAAABJRU5ErkJggg==
editshred16:edit:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsSAAALEgHS3X78AAAAB3RJTUUH0gYREho76kO2PwAAAZtJREFUeJx9kj1vE0EQhp/ZvTOCH4As/gUFFJZAEAkh0VDQ0PAjItGloUkXRIPo6CighI4K64oTIKWgoEEpgiKlQSExjuOP3ZmlsM+czz5GWu3O7s6jd3ZfSSkB8P5jOV+0RL8o6Xa78vL5M652r7H/uQAgq196sHWTEBVV5WI8IQTldDDEew/06BdlOjo8kOs3essaVweICE4Ws3M478jzfHl+b+sW2zt7qVK9pgDA0j+Yd/NhNm+hirv3HyVANgIqunMOM8N7T4jKk8cPOfk94ORsyJev+5tbqEur2hARMu8Y/BlxfjEh8yslqwrMrCkIcUJUYxYinTzD/gdIKWFmhKjEGAlROT0bMguRK5c7qOaoajsgRCVEXa5HozEpJTLvSHmOc4r30g4AyLxjMp0xHk8BuNTJMTNEBHWC2qrf1nzwqfzGdBb4/uMnIsLB4TEiwtHxL0QEEWkH1N+iCa7PrYDqF+pmWitobG32QVrNm4rqsXzEflHSL0ru3O4tTAqvXr+d54t48+7DGkCa9O2dveXGi92n0sybgL92SsIBMEhlGQAAAABJRU5ErkJggg==
edittrash16:edit:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAANrSURBVHjaYvz//z8DCLC57GT4/++/1P+//6KYObg8WTg5tZnZGP+xMP39z8Twn/nPtx/Xvrz+tOfvt5+LGBgZn/y/EAbWBxBALAxQ8O/vP30mNval3Ary6syC4q/EpLm/iIsxsPJyMDBzglT9/G345+M7x3MHbyY8vPIyHChyHqQPIIDgBnBwcSwW0dGX+y0geI2XjYFPQohBkJ2RgenvDwbGr0BHcrAz/5XXFH+lpyagNL3nwAKgFn2QPoAAYoIZYKovrGZmIfiK4Q8DjxAngwALIwMzyHcQxPD/7+8/TO/f/WLnFWT/JCTKowHTBxBAcBdwszH8TDNmEHr2kuHPr18MTD//MPxjhCpgA1rDysrIqCDKzMwHNOz1q58/YPoAAghuwOsvv57ayjI8XZ3AYHL0PgPbzbcMf9/8ZGBg+s/wn5+dgUGck4Hx6avvP2sWv3/z9tk3YZg+gACCG/DnD8P/S8CAEWZlYA3SYFB+A9T74BMD07UHv/8fuvz9z6RDb7+/ffnrD9BN/xgYGeAAIIDgBjAy/GUEirP8+s/w7z0Dw9c7Pxl+7XvEwHD4zC+GC5c/Mb778JeRgY2RCegxRob/CAMAAghuwP9//0Di/0AYaBAr838GVo7//xi5WX4zcLL+YWBm+vP7zx8gBxSo/xEmAAQQ3IC///7/4WRgEORiYlBm+Mcg+e83UM/fX4xs/74wcPz/zMDO9OMXIyPz998MfG8Z/iNMAAggRDpgYhQWZWDwBfpFFCT7D0wA45KJlYGFBRgwzN85Gf/94Pz/l4Hnzz9gPEEBQADBDRDhZhFjA4bBC2Cq4WNmZPjzG5JMGEEGsHIwsLIzMfxh/M/A//cp2zf2t/D0AxBAcAN+fP7KIAB0OzMHEzA4gYEANICZhZmBiQloCCMzg7jgfwZ5nrcM8ZbsDP0LReFhABBAYO+AsID1qm/7jt79/+frV2B4/v3/7fff/4++/v1//sWf/9efff7/6MUboPjX/68//vkvbrL8G0wfQADBDWBQXZgq6bj6XWnvyf9bDzz4//rlx////v4BavoHxtfuffo/cdmd/3IOa94xiExMhekDCCBGWIAyai5mZPj+Sx/o7Rh+YS4XMSEOZS6gd5iA0f79x1+Gly+/3H3/9MMeht9/lzCws1z8/yIHrBEgwAA0o2eMBLJBMwAAAABJRU5ErkJggg==
actconfigure16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAOxSURBVHjaYuzpWcQgLS3OwMDwX5Cdne2EpqaS9L9/f/+/ffvxxbNnryZ+/vx9/u/ff74yMjLAwY8fvxlMTbUYrKz0GAACiOnHj18MDx48Zfj589eXb99+zvv+/TuXpqYij42NgYqJidZkFhbmXqDhrIxAE0CGwDAMAAQAQQC+/wNERFAF9/f4/vHx8/4HBwXF3Nzl7/39/DwbGxUHExMQAAICADTW1t/W+Pj61Pn5/AD7+/sA8vL1ABcXEgAjIxwAAogJaMhyoJmmnz9/Zbh69Q7D06cvJp05c+3khw+fwTbIyUkx8PBwev748YP5169fDN++/2RgY2NjkJISA8sDBBCTjIx4sKys+Mpfv37r/v37l4GDg73a2trQhpeXG+it32BFQG/Ivv/0k/vr1+8Mnz5+YeDl5WTQ0VECywEEEAsbG/M3V1dbRWCgrXjx4s1BZ2ezTHV1BYaPH78CNbIwvHv3geHxs/fPhf7c/OTMu4vhE9AFHF+1gVrDwQYABBDLzZsPH1hZ6Wt5e9tqvX79TktFRZbh/fuPQKl/wMBiZnj9+j3Dl2//xD059+oIM3248o/xDwMbw2d4IAIEELOYmOaf//8ZfDU05BlERAQYvn37xfDv339gYP1lePToBcOHLwwM8px3lCQYj/v+/fXvz/fv/08xcgkxyNoms4KCACAAAEEAvv8DKCg5zdjY3v3q6u86//8ABPb2+ADq6u0A9/f4AAYJEAAD7MYAGeWRABn45Q8AEQdJ8/YG9PLp6cfx6Nj/AQQJ/wKIMTS0lOHLly9ADT+9OTk57Hl5uTS+fv35QkhM0jDMQcBE5tUkBqnf9xhEgNZ942RleMTI++fubebir19/TPr87S8DQACxgPzByMjEwMrKshUYyls/ffrG+Y+R6bvYv73m/y/e3Kak9VGIl50L7F/u/wwMykw/WP7+5+y7cpWNgY2dYRJAADFra1uDE8e/f/8YgF5g+M/I9keC8wNDkOzpp18+//vGxsPmKqHGyszAz87AAKSY//5nEOX6xfSPidnj+WvGlwABxMKAA/xnYGT49ZdpypEzDGy//jP0mLqxMjK8+8HA8OALA+Of/wy6wr8ZHwtyNwIEEE4DwFHEzMAATFt9+44w/Pn5/UefjepfZgYOYOJ9/5uBCZjIuJn+CgEEEF4DYIYAvTZp1xEGhp/P/vc5W7EwM7D/Z3j/koHhyiPmSwABRNAAcHoHWvqPEWjILU6Gey9/1AnxMLDfe89+/e0PphyAAAMA72F4qGAYYSYAAAAASUVORK5CYII=
build16:package:apps:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAO3SURBVHjaYvw3jwEV/GZgYmBliGRQFCldufbt6gMX/7dOT2Pw/PyJyev+3X9l374wfGf4xsDw5j0DQ8h2BgaAAGKBa/wDJj0YZKVrGPTMrBmkRBnMP28XY/z6+DWDjmU7t6SKkMjKNaoPzn+PZWJgeA3TBhBAUAMYrRlEJcoY9Hz8GBS1gfy3DAzfrzAoCP2VVHAXmPlfzYaBifMrg2S4qfufb6d3P77wPfw/A8NNkE6AAGJi+MfA8J+DO4HBfTJQcwQDw9+PDAw3djMwHD/K8J+Hl+E/LxPDty2LGP6+uMHAyMHEIOshqy+rybYLaLMtyACAAABBAL7/A39RAEsA9vrcAAT1TAH85QYAyqEAAPLqAAAdGgABGRcAAf77AAMA+gDyz+YAAfX5AAUK+wAPCPkPzsz7JqrbAKcCiOXXbwYXVnnNNMavj1gZrm9jYJAUYmAQl2Bg4OVhYODiAtL8DMy83Az8sswMb0+/YPh16wPD+SPf7zQfYajzFGP4DhBAzEWuDDufv/7GzG9i5MggxML07+MXBiYZMQYGAQGgAfIMDExAP/KyMjDwcDP8ePub4e3lDwxMLEw/Tdn+quhzMPwBCABBAL7/AgQDAADz8PaD6rKzm//5+QD9AwcA+N7tAAAECQD5ztcA9c3XAPLX7wDnt+AAAggBABlAGAD+/gADrd0A21/OANcCiIWVkZFBDWghkHr69+Zjht+MbAy/3r5heHf8KcOf178Y/vIKMvA7aTHwGv5n+HHmEsO1TU9/BK/9F/nqL8M+UCACBBDLbwYWoOb/DEzMTCysiqIMTD//AqOMjeHPc6Dm/+wMbKJiDD+ev2D4cuYeg7jCbwZWMZb/r/7+ug9LBwABxPLrByMwHhkZGFmYWDlFRRiYOZgZOP/9Z+BkZWdgAMr9fwd0ybdvDKyqwDARZWVgOvOCkYnhF+s/qAEAAcTy5dkvSEL8zbD9465nKQrRBmIMXMBY/gM0+AfQaxz/GFiZgWw2YPoDuvT/99csyCkfIICYgNEMDuhHHxmOtEx/5fV41tm7/7/xMzBwqzAwCAIDR1qKgUFMjOHXpe8MW3Ou3q1a+q4SqPwlzACAAAIGADgAGf6D8hEzw9mrB996PLm7Y7VxZaoBm6Iqw78z+xiOzLv0bMq6Vwu3vGKYD3TUbWQXAAQQqnOABrFyMtw5e/a9+6fC6ask5MVNpm64s2TlY4YZnxkYLjJA7EEBAAHEgi4Acg07B8Orw1c/+87b8lnrxT+Gc+BMjgMABBgAAPY/UCNn0RUAAAAASUVORK5CYII=
quickbuild16:app:apps:16x16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAEEUlEQVR42mL8v46BgeE/EP9jgIA/DHwMnOxBDLIyBQf2PlvB8v17h40ek9/PX9zWzP8/H2TmYPL6/ZuJ+dfXf6x/v/1bBBBALAww8BeImRn8GGR08xjULZ0ZREUZtL9tFvh64fpHBk3vOmY+GYm/5xalsxiz87PycTD8PvL2198r35YABBAL0HZGBkZWGwYx9XwGVV9vBmlNDgbGjwwM3y4ziHL9kueTF5/6T9aCkYX5NQOzBDM/gwQXw/+vfxm+3v+56t8fhoMAAcQCdPr//zxikYzm3cEMXJIMDL+OMDA83cnA8PoGAwO/CAOb4E/GnycWMzDzszMwCwHtAjrz39UPDDfP/b3BCrQeIIBYGFgY/Ri+vDz0//6acEZ+SSGGR2uAfvnKwCCpxMAgJA7U8I+B6fk7hm9PnjDw63GA/fr96S8GUQnm9L+//okABABBAL7/BPz8AjoBFzZiA/jfDQDgpgAAERMAABYfAAAMDwAABwkAAA0SAAT9BgAG+/cA+df4AP8G9gAKRBEAICX6He6q7iMCiOnHz3+1Lx8/mPZbROEHg6opw9//wHDl4gUawMfAwAE0iE+CgUlejYFJu4zh4w1zhl/3PjMwczAyfL7wjeH8+X/7AAIAQQC+/wICAwH7+e7mgPHAo6b/+PcA/gEJAPnm6gD/AgcA+tbTAPfT0QD04OcA89vLAAQI9wALJgQA+8z1AL+w9r6V0wDHAoiFGRgoksLMIL8+/fvgJsNfZm6GX++eMnw8e4fh75tPDP94ZRm4zXUZGBh/MbD8OcPAzMzK8Onxz/+aikzKVbz/PAACiOXffzZISmJlYWOWlWVg/AlMEKzsDP/e/GT4+Z+LgUVYluHPh7cMfx6dZ/j/+zfD1xuMDIJ6bIxfn/7h+/3q10mAAGL5+Z2J4f+/f0DnMbNyCEswMLOzMTD//c3AwcQFjNL/DH8/PmX4+/0+A5OEDMO768BY+X6N4ctFoPjtXxNl+Bl2AAQQy/fXX8Eu+P372443/x7HKAaYSDNwsgKTNBPYAGagOczMQO5vHoYf518yCP/7ybD/IO+FrWf+TVQU+sMAEEDgpMzMxMjw/uf/A8fX3Yrw/PlnlkSItyaToDQDA+d7oCwwKv/9Zvh+8g0D25tzDN8Y+P7NvyTeuOzcyw8MDJ8YAQKICZYVgLHBwMrGcOTW3nshl3q2nvj9kBHoMEWG/1c+MByuOnj74n7Wq3/e//o/5bDg/P33Pu1mYPjCC3I6QAAhMhMQMAL1MLIxXLty7F7Y11eT5wjJShstXHt+7YorvyZMS/pSuOX5r2dNOx6W//jLALL4J0gPQAChGAAzhI2T4fHxc09ilix9onrxO8NpYOZjZv30/N/xhwzTgZrfgpRBCwEGgAADADnEhHWBcajFAAAAAElFTkSuQmCC
actrun16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAPsSURBVHjaYuTz2swAA////Wf4z8lqAqT1GD/93Pv/399XDD9+a/5jYbr8n4nx979ffxgY/v5l+P//P1wPQAAxwRiMf/+pMf78o/6Hj3/e9yijuX/URZb+5Wdf+9NV/cA/Qc5ahp9Azf/+MaADgABiAZP//hv91JNczvj1F+dvdQmBf/piDH9Y2axZ3v5gYNAUZvjHwlzJuPM60GqGGwy//x4D6njMwAgxACCAWEDOZvjL7PFDSluNwYmTgeHTbwaBhfcYeJ6/Z2BkY2RgPvuK4a8UL8tnP5OGjwy/GZh3XlnF+P5rFNCzf0EGAAQQE8hZQL/KMp99z8DwlYGB+9hbBpHvn59xSLKsZxdmOcYixPCb+8cXBjl2NgYxRWmGf7wcyv++f2f/9+sXw7+fvxkAAojp/39Gh98aEnH/zYHB8ek/A9e3Xzc5hDldmNhZwhk5mNw5pHlt2VUE9jEJ/mNQ/PObgc9EQ++vmNAyoBecQd4ACCCm/4wsWr8UlLn+aUgwMPxmBPqGnf/PC+ZX/z6z/+Zk4/oCDJ+TTGzMoZyqgge4FFgZxK2UWRlSfP3/y0r2Mvz+Iw4QQEz///75w3j5NwPDHqCHnjMwfBbnl2DgZy3gF+RiEBAUYhCUFGXg1RV+xyHDU8Yiy/2Ti+M/A+PHPwz/3359+p+R4QtAAABBAL7/AwYgVP8C9e8o//H2Cv8OEgv+EgcA/QIDOxYG/vsICALSBQgH+RD9BQABCQLmCAMBR+voAR7q0uoAANPWwAD8+8ACAEEAvv8DBiJZ5wH796AC9eoU/BsbPAAHCgD4AAYC8QAEQwYEADcPCAETCQUBDAz6Aknk6QFG1uAAEfwMDgAABQczAOPj2wKI5e93YFz/+8vyV1rcjkFciIHhF9ArwNj8/Imd4fIPdqc7X/878XAwfPn+k5HnK0gpKO4UQWpYQanyBUAAsYCT5d//fP+Z/7EzKACl73xkYOAABq+SIMP/CwwM394zMnxjYeBhAKpnACZGht9AUw5eZWA4dnktw5+/xwECiJlZMgCYjhm+M374eofhyQsPpgs3VjKdun3pvzSrPgOXCCMDMHkwqAKxNRAzgwIaaOHWXU8YPn30Y2BhfgsQQCwMsIzxn2Ef87Wnev8YmV79//aTEZh02f+nq0cy/AbG0Oxt1xm0eQQZsuwkGPZdB3rzZz8DM/NrkDaAAGKB5wqgq/+zsb76D8ptzEDj3n57w3D/BgPDg3dfGB48jGV4wabD8PJrKcP1Z3MY/v6ewMAMyYcAAcTIZrIIJTv/BSbR/7+ByZyFSRHI12f4BUx+TIxbGf7+YWX48UeSgZX5EZAP1wMQYACFGXIs7PEZIwAAAABJRU5ErkJggg==
acthelp16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAN3SURBVHjaYtzLwMDAyAAHbP8YGCz+MDAkszIwODNwcIgD+Qw/fv58+fX//71A8bl/GRhO/GRg+AXEDL+BGCCAGJEMEANKdvEyM8eL2NoyCBkZMfzn5WX4/+8fw/9v3xheXL7M8ODoUYaXX78uBBpaBjTgFcgAgABigdosARRcJCUs7KpUVcXAZmzM8IOLi4FZTAxoOiMDm4QEg/DjxwxKe/YwnJ88Of7i1atSQD1xQPwCIICY4xkY2IGa+yUEBII1yssZmJSUGL5zcDCwa2gwsAI1MvPzMzAwMzP8B4qxcnIySCsqMny/dk352bt3wv8ZGHYABBATULMZNyNjorKfHwMT0NZvz58zcDs4QDRu3crAsHgxw/8bNxgYgJoZxMUZmH7/ZjDx9GQQZWdPBHrBDCCAQAakigIlOID+Zbh2jYER5GwQ2AsMnY0bGf7v2MHwcflyhn/AsGAAuugf0Bucly4xyLOxgVSlAgQQCzMDg5MQOzsDw7NnDAxfvzJwgYS/f2dg2L+fgeHBA4aXQBvZ09IYmJmYGP7u2sXwbf16BoY/fxgkgcqAupwAAogF6A8JNqAihtu3GRj+/mVgevSIgeHAATD7M9A1PJMmMXCDYuTdO4bvBQUMf4GagZYycAAxSC9AALEAo46B6f17sO0M//9DnA+kvwMN/dPSwiAI1Pzv4kWGb2FhDH9AlkABExCD0ghAADFsZmB48gao5R8U/4XiJ0JC/3+8efP/358//3/o6/8HGf8NioFp4P9DIG4D6gUIIBagxL5XDAyxQgyoQOjTJwa2w4eByfAHAyvQBaxIcqCEdx+IPwH1AgQQyy8GhtkPgAYoAAOSAxhQjFBv/P/1i+ERMPR5+fgYBDk4kHQzMnwBxsilnz9BSXk2QACxAP1y6ikDw/zzDAyJFsC4ZwQqANn6xcyMQWzOHAZ2UAy9Arrx0CFwWvgPtGAfMMzuAfUAI/IUQACBDPgJTM9V537+lPn79aurCTCuOYSEGIRBMXLhAjgVggNYWprhK9BVe1+8YNj/8+duoLFVQKt+AgQQ4zKgq35CsBgwgLrE2NnjVYSFGZQFBBg4gNEI8tC3ly8Zrn/8yHD57VuGBz9/LgRaWAYUfgUKC4AAQjYAhNmAhlgAmckczMzOQPeCs/NPRsaXn/7+3QsMr7lAzSeAQr9ggQkQYABbmj+kxAjisAAAAABJRU5ErkJggg==
filefind16:file:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAARZSURBVHjaAEEAvv8BdXWOABMRDAIICw1Q9AgVc/MIFC4ABQYADwDz9gb07LQA8u2L+Pf32Pn+/wDsARcA8ff9APPx9P3i4+iWOTkvlQIAQQC+/wQCAf8D9PwEeuEIKn8DHyEDDxQHAAcFAAD3/wIM/fr2YgHa00b93dRjB//9uv/y5wDk6wUAAgD9bQ8PDczo5+yKAgBBAL7/BPn9AUvsEC2BEi8sASMe/gALCAAA9/gAAO/w+wAGDgsABxk3HOv18Zbs0s4+/gcS5hsdFhIHBAJM19fdD9bV3XgCiOkTE28eu4o6o4L0fwY1cSYGPQEmBh5mBgZ5aaA3eP8ziEowM0ha6Sj/ZmL2+/HtO8OvX78n3b37xPPj+09tf/78FgEIAEEAvv8E9gYRMxcWCwAKCP4AEgEBAAf6/wAFBQEAEwoBAPgMAQAGAf8ADigbANEHBUfp4+yY6OYBAPn29QD18/MA/Pr4BwKI5Q8bLzsX2z+GDx//Mpz78Y+Bi4uJQYqPiQFIMXAxMDCw/WdgYGFmYvj3j4Xn3pUDDLfvnqmW0k/W/POXZdv/f38OAwQQy+/3z38wsjJz/v31l+EfUBcXJ9AVQC8wATUKgwwA4l9/gRa8ffuBjZWLgZmZ+eGfv7+NGRhZGRiBLgYIIKa3ty4d/fbuE8NvBmaGn78ZGP4xAZ0I1AQMSwZeIJYFKrp6+BzDvVv3NvMKyDII8wsBDf/B8Oc/O8NfoPEAAcTMwyz0iJGJNVLTyYCVk50JHIU8LAwMnEDNwkDNr99/Ypg7ZTnDz++/J9mJXX0QJHWfQZTpJcOLH1wMnP/eMQAEELOIiPLj93dvPfj56Y+LtKYCu4AIB9B2RgZuoOYbV+8xzOxdwMDMxMGgI/NX1uDbZoVvf1iuMf3++U36720GgR/3GAACAEEAvv8EPVdiB9zb473IqadI483MXBkhGEMKCwgK9evu8OTa364dHR7KGRL0YyP/xFIiIQ5D9tbvNOT9Bl75/wHw/AAAAAIAQQC+/wLx+ARC8/oD5+nq1P7/DCDE0s7mSere4h7i2d8u8O3xgA0I/7YD16e1IyEEACxaWwAyLxFNEQf6pPz9ABQAAAAAAgBBAL7/Ayw5UvX6+vzR6NzF6wYRJ7jt7vnH/gEE1QwG+wD5+f4AIg/zAAzryNra2+4LFyIdOClAOAAM8Nom3+H1KOr1A7wCiNk1JPP47z8MFl9+C5xS1VDvFBUX+fHpB+OL/9wSoAhhkOf7zsD1+ebvFx/+7Tx15Ba/tIq8hb67OYPE9zvqV+58VQcIAEEAvv8DFCREleLh5hgAAQUzHh4Z3Ofn7LPz8fKe+fr88PoDDwAG+ugAGvnYAPkABADo7v2+ysXYCyUtIzkQGRgAxdL4KAIAQQC+/wMLGjpo8vDxAPPt7e3o6O2B9fP1ufTz8Nb7+Pf89fX6AP336gArBt0A9fwCAPj8Av7w9P3Az8bXK87hCB3a+y7JAgwAIri9AzRUJO8AAAAASUVORK5CYII=
buttoncancel16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAANVSURBVHjaVMcxEYAwEADBjQlM0GAB5ahAAR0OknzypOVmtrjyHChk2JY90lUbrdI7I/xaf2a65/TG4BNATGDNPxmEWARYlrMq8e7794shkwEHAGrO5BVl3sfOybj8718GIZAYQAAxAW2VYhFmWykYF+oklpPFwKEtNOXvD4ZskMHI4M9vhmwhWbYpmo6KDMpGIk6cHAwr//9jkAIIICaGPwxqjLxsLqzScgxM7BIMkmGBTLya/BP+/WDIQNKcISzLPkHJQo6J+R8zAy8HEwMLC6ML0AA1gAAAQQC+/wNxGwDh9ub66fng2EcKHhICAwgRAAwcEAL35uNM9en75vz8ADMSHQaZJTkeAgT/AgD77PEA18rs/O7u/mwCAwCtAoi5UALot/8MZ748+P7u59N7nkDNjMysPAz8kpwM31+89uXkZfZVtpRjgGj+wHDj9Jv/r17/y2dmYpgG8iZAAIEN+AcM6X8MDKe/PPn56vvTx968UlwMLMycDAJiHAzCEtwMLH8ZwZqvn3nD8PrVv2xmZqBmBkjsAQQQC8N/REAxsjBMf3v969+/30/PVHZQY2AGReHvfwx/P3xhuHH2LUhzOlDzLOTABQgglmdPgSSSIaC4/Q/UxPD1O1AzUOLLDyAGJoo/QIMYIK4Fqf8H1QMQQEwomn8zZIICTMlCloEZqPrv+09A278yMP/4y6AuysoA9NFMoDBKOgEIIBaUeJZjm6xsIcfA+p8Z6Of3DDfOvAXbrAHUzPb9H4M2B9DmHwxTX/1nYAJ6fypIH0AAgQxgBKawDGE5UDzLMrKCQ/s9w/XT4ABLAzn779dfs0CaWT8zMOj+ZWC8zMAw4SXQLCYGhhkAAcQC1GwPTJ7TVC1lGJjANoOi6u0foOZcYIDNZgQGx4tvDMxAmycDNbOwAg3UZWBgAWaXae8ZGK4DBBDQEIZbPz7/3/PpySeG32+Bms+8/vfq9d8CoOYZMO8xMzLMePmPoQBo8z9g/mIAOoQBGLR7gN64BRBAjMcEGBh+AjMTOxvDajZWRqf3H/5nARPJdJhmYK5j+AvEwBwISnCZgkCbgZr3fWVgCAX6/x1AAIENAGXZX7+B2fkvgzYTE8N+5FBGNgCEgUodmRkYrgJtfwWSBwgwAM2zU6m+NiFjAAAAAElFTkSuQmCC
buttonok16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAInSURBVHjaYvz//z8DJQAggJgYKAQAAcTCOIFRluEPw2OGr0DeNyD+DsR/QDJAzAbErEhsFiifjUGZjZ0hmZmZQRcggFgY/jJsBGqoBgpvx2sVyKf/GKSAZBJQfdqvPww/GFkYQgECiInpL9NvVg7WxQy/GRxxavzFIAwkywVkBPZJykg2A135iOEngxNQ7CJAADH9//R/lbCWsDCHHMcihh8MlgyMSJp/M4gDXZjBIs1yVNpXuoNfll/91e1X24Gaw4DqnoCUAAQQy/8P/0+/+/HuF1MIkwzDO4alDA8YQoDi14C2JjDIMyQwWjGas5myMXw4+YHh6/avqxmYGdIYOBg+wOwACCBGhhQGMaDC7QwFDEYMr4Ai8xnuAp34lsGOwYzBAsgXBeINQLyFYQIDF0MDAy/DR3CAcjAwMHIxMAAEEAswYF4x3GE4xXAdaIA6UCKcQZmBCYglwV5gYJgKDLJTDP0M7AyVQNv/ogcRQAAxAf3DwPCF4TTDJaAkyAXsQMwNxA+BeBYQ7wNq/M9Qhk0zCAAEEAvDZyD5l+EYwwWgs/WA3gHF8xOws38w3GbIAxo2mwFPcgMIIBawuX8ZbgA1XWV4ATTgF9i/74ERVQz083wGAmkVIIBYwP78B8Q/gY49BkwLzxleAzXHAVPdDpQoxQEAAogZGFwMYIX/gU5+zmDO8AkYLywMe8BiLEhJGZlmhrAZgWyAAGKkNDcCBBDFuREgwADDUYv001UhNgAAAABJRU5ErkJggg==
foldernew16:folder:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIbSURBVHjaYvz//z8DNQBAADGRrGMa438wRgMAAcREiWZkcYAAYgQR8sUPUBQ97FUQAVKfgfjX/6kM/xmypBgYjj9jYDgPFAGxwYYA+YZA2lIKzAYIIEaQIQVerCgWFVYuY2A4VaoIZD5DGBYLZOoDsRZU1TUgvgg0ZDEDYzYDI0AAgQ2y0vjBcO35N7y+uyBsBHXBGYjAcROwC0GGgLgAAcQCIn79+cvw8/dfsPz/178xDLmha8WAcNEriKBlDxBfBDp18X+gYewAAQQ16B/YILYP/xiiAuQYHrz7CTdk3ntlSLgcXwx0wWLMMALy/zM8+wkQQGCvaUl/YLj05AsDzzcmBj1DAYa/zMwoLlr7Ux1MB7PfhLMbrN8xNBwVArOBLhIBCCC412CGfPgJisA/KAa5MVyFML4BxaF2PP74i0Hj8jGGmzOsQCZ/BgggsEHfvyPC5dnb73gDXZDhCIOMkiQDw4OvMKEHILcABBDYoLfP/zGoaPIynLzziWDa/Pv/O8OTe88ZxF8ygVzjCDIEJA4QQCwwBfuO3SM6l/xhACYVQVEGaDoDA4AAAhtkJvyKoTNaD54EONhYGNjZmBkEeNgZ2FmZIWxuNjDNAeQbFZ6GueYtzCCAAALntWAPiCEgTSSAZ9BsBAYAAcTIYNZNejlyqlQdFsgwIYAAAiVvYVA6JdGo48jeAgGAAAIZxAY1jBTwFtk1IAAQYABU2rjPUTb0WgAAAABJRU5ErkJggg==
viewsidetree16:view:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAMWSURBVHjaYmST0NZhZGSQZvj/n+H/v/+MUBpIQWg4H8z+BxIHSTIwcOl9YhAMOAcQQIyWs749UJLmkP/xlYHhGxD/+MLA8P3LPyD+C6G//mf48fUvw5d3fxl+fv7L8O8XUPOfPwwMXy/8Y/h9yxoggFgEWL9LyPNyMHz4BxQD4m9/GRi+/GFiYANiLgYGhk9AtQw/gYgJqI8RyGZlYGAE4n+/xJn+/3kkABBALEoC/3+HqTGw//gFMRiE/wLxbyC++vALAy8nO4MAJyvDzx9AQ37+Y/gLtICDjZFh297/DLv2sf4FCCAWMU4GBj0xBqzg5sNXDAYqIgwmcqxIokAvMDAyvH/+j+HwcYYfAAHE8g8UOGjgydsfDJ+//WF48/k3w60n3xh4mJgYfgOd9Beo9t/f/wxcHEwMrz/8ZXglyKEBEEAs//7+Q9EMMnD27ocMMmLcDOpyQgy/fv9mOHr7IwMDEwvYZpALGP//YdAxlWOQfP5lKkAAsfxHc8EfoA3CvOwMqU4yDKdPH2cwMjdmYGZmg4QkAyhEgaHJwAlW27j37k+AAGICRSs6+AcUA4YVw4MHj6C2ArXPdWb40SLH8KNTBRhNj8HyINcCBBATtjBggGpjBMK1a9cz3H/0lIHl71eG/18+AvEHoC/+wtUBBBAL0BgUjcgOYgQGnoaqGoOwID/DP2F1BsZfv4HpgAPoCw64GoAAYkHWAWL+ASdZqAHANK6urs7Azs7O8FcngoFJ+TUkFbHxMsCsBQggFiZkZwPdzcEM9zYw0QCT8JcvDKysrAy/d1Ux/H18A+gCNgbucnsGJlZFsBqAAGJ59f4nz61nXxh+fP8DTH3AtP/jN8MvIA0yWJifj2Hr5o0M1nZODMpszAw/wS77B7YAZjFAALEcvvyu7ca9d2y/vv9i+A3U/Pv7D4YAV8UsoDIuRzcPsG9A+Lt+IgOD/EMGBmZ2ht/soqAswcDCzMgCEECM2vmnGSR4GYFpHZgZfv5huP31M8N/buarQqLccsjhy8guALQWkqT//3jLwML0j+Hekw9fAAIMALELS1OzP9gzAAAAAElFTkSuQmCC
folderopen16:folder:filesystems:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAACWElEQVR42mL8//8/AyUAIIAYVTTNfdMyCjahS0yb3B1w//bZjYQMAAggxq6Jy/+X5kWgCP7+859hwrSVX4BMHnQNE3ubnZ88vLoPxgcIIBYY48nTNwzMzMwMTExMDKysTAxAQ3mw2SgoIr2TW0jZ7tuHlxdAfIAAghvAyMjEwMLMyMDJzsjAzMTA8OfndwYWdjagDDPDgSs/GTrWfYCqVGOxLTh2DKYPIIDgBrCyMjJ8/snI0Lv9D8O//yADfzEwMnxj+PsX6KV/TAyN0eJgdc/f/mZ49/HH/T9/WLlmrTv1GCCA4AawsTAyzNz+l0FTmZfBQI4ZGA5AV/z9DzSEESjLxLDoCETd81c/GNbveH0W6FEp9jsTlgEEENyALz+ZGP4Ao9REiYVh15V/DF9/MILxtx8MDD9+MTCwMEHUMYFi/Sczk6bGX4XbZ69dAggguAFffwKd+pcRrPjzNwaGb0D+dyD+9RviBoZ/sCgC4m9MzEx/Pv768+3+LYAAghvwBhhpoDQF0vT1OyOY/vmHESgGNOAfRA4E/gMtYPjOwsn0/9Onf39+vQEIILgBW8/9ZoiyE2RYeeo/w0+gop+/IZqZQDYDw4PhL0TdH6DrNA0Z1W8emLvw/7//fwECiAUpTTFYqjIBMb50BzKFk6Fg6mv5KVtOgeMVIIDABvRu+sKQ4CLE8Ado28fPIH//AbriN8MfIA1x+n+Gv8C4BfEZmVgZbrzlZvj7+eoMkAxAADEqqRp4ZeSUb937wZHoDLSvz93/14cL4PwDEECMlOZGgABiYqAQAAQYAOO+6KysZFfCAAAAAElFTkSuQmCC
appwindow_list16:app:apps:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAADO0lEQVR42mJMSEhgUFBQYPjy5QsDIyMjw8+fPxlsbW1N1NTU+nt7e8svXLhw7NatWwzs7OwMTExMYDUg+s+fPwwcHBwMAAHErKenB+a8fPkSbMi7d+8YpKWlM+Tk5GJNTEyilJSU7N6/f3/nwYMHT/7//8/AzMwMNuDfv38MLCwsDAABxNjU1MTg5eXFcOrUKbAEJyenkouLy1mgoQInT55k+PXrF8Pfv3+/X7p0aTOQP+UwEDAAgaCgINgFAAHEAnIyLy8vg4qKCtglAgICkSIiIgJsbGwMYmJiDPv372c4ffo0J1BDmKenp39GRsZGoGFTv3//fgikBiCAmO3s7BiATmU4e/Ysw44dO4Tc3d0XADXygmwBOVFVVZUBaCAD0AsMT548YeHh4dEGhk8YKysr0GF/XwMEEBNQHQfQP/xAp/MDXRAqKysryYAEQH5VVFRkiIqKYnBzc2MAhcOnT5+4TU1NO4AG9QEEEOPkkz/+a4uxf3z17hfDh6+/uL//ZmZ5++UPw4cvvxg+fQOKffrKIMDBzHD3ySOGRuc/oDBiAHoB5K2/ly9fLgMIIBaQLW/+MvC//vOf4cMfVoY3n38zvP/0neEjUOPnz18ZPnz4yvCLk4nh+eOnDNevv2NQV1dnEBcXZ/jx48ep58+fLwUIILABocoMDL/lmMAh/vv3HyDNAMSsDN++sTF8/fobHLhzzmgzfHy3BWjgB7ALHj9+vAmYJl4CBBATzK+g+AUGDJgGBR4odoC2gOVAoc3IxALmgwLz3r17d4ABugqkFiCAWJAD6/fv32D68+fPDB8/fgQHGEgMRH/9wc3A9fUrw9OnTxkePny4BBgD90EGAAQQigEgDLIZGMpgMZBmEB+omOHLD06Gvy9egOTuv3jxYikw0f0HqQEIIBb0KAMlZ5AGEBvkd5ABIPztC/ufd0+fvgLKbQHih6A8AQIAAQQ3AKQY5EeQBBcXF5gNTcbAwPzG8O0HL9Pzp0/TgQafASmH6QMIIJaVq48zrFzNgAdwQjEDE1DzbWB4vIDZDgIAAcQoJy3L/ePnH1FQLmUABhdICqQApAbMBooygbMwMwMjK8s7oNBHZOMBAgwAWUiegwK1XZMAAAAASUVORK5CYII=
nav2uparrow16:nav:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAANOSURBVHjaYlRN2MvAwPCfAQygFBDwMPz/2/SKgTf1z++/DCJfX8/8/+9/3b9//74BaQaGv/8YgGygkn8MAAHEwsjECNEHJRj//2f5+/dv12se2Uw/d00GIc5/DEtXXyhmuXeDjfH3n6Lf337++fvjB8Ofrz8Z/nz/yQAQQMzChvFwa4FGcf75+3/aa0GFtBAvdYZqW0YGJ0UmBkYJSYbjj/6Z/3/5Qprx39/d///9+wOyHYQBAgjZANG//xnmvxdVifJwVGYIVmdkePWFgeHxRwYGRQFGBm4ZCYYrb5iN/j5/qsXw98++f7//fvv35y8DQACxgG3+/18KaNqSDxIajqZGsgyaggwM554xMPxjQABxDgYGZx9dht2MjIH/9u8WAAZCDFDnM4AAYmH8/0/53///q96LqxnJqMkycDIxMJx6hhyeQDbQpB9/GRh+AgXZdXUY3nz+6ch+dO9moHfCAAKI5R8j8+rnouqG/8QkGd58ZWB4+QmimZEBETHfgQYAw4wBFAEMzEBsaMzwn5XNiHXPttUAAcTyg5ld94uIJAPDHwaGb7+RrEV2PwiwwEMaDP4Y6jIwHTusCxBALMxfPh8Wun/F8RcrJzB+/wJD9i/DL14Rht8iokA+VBPQVubnzxiYXjwFO+kfI9CU168Z/r97exgggFgY//wK53t+y//ftx9s/378cv/LxOr3TtcO4gKYAcBwYfj6nYHt6D6G/58/rwKmoUPAcAMGCdNGgABi5tcI//bny89z/379/vCLnSfpva695C8RaQaG31BvgDDQe/8FhRj+icgyMD5+8O3vl8/df3//38PAyPgNIICYuaX9GP7/+uX4n1dw029DBzUmoNOBMcbAzoyGga5mExNgYJFVlP778F7wn/dvzv///e8BQAAx88gHBDALiSziMHeQ4BLhZ+AGKuZmw4GBcjyiPAzcKuq8P+4+8Prz+f1tgABilPVe90rK3VWUmReYf/4wEAUYgYb9fPmO4XLb5NcAAQRMSP8FRQQ4GLj4gN79i5QAQExGZF0IJhMwSr8y8jBcY2URBAggRlHLeXXcfDzl7Nyc///8+vMfnFWBafw/EINpUKb58wfOZvgPzLHMTIzf3nxg/PDkZSdAgAEAA4pi+uNErtoAAAAASUVORK5CYII=
nav2downarrow16:nav:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAM9SURBVHjaYlRJ2lfHyM5RzsPF9v/Prz/////9y/D/z1+Gf3/+gen/f/8B2X+gNITP8P8f46eX7xm/PXnZCRBAjAopR37b+VqwuGswM3z9yQABjAwIAGUzAmkmRgiXg52B4ejN3wwL8mf8AQgglr8/f79/8vaX6K9fnAzcQFmQBQz/GVAAMyNE6MtvBoY//yDsl6++Mvz+9vM9QACxsHz/nHZx54lZLz6aiVqpczNwMKLqB9n64w8Dw413DAxX3jAwfPzLwMD76T3D95UrXv97/zYNIIAYFcO2MPz78s3xEwv3Ek5TSyl5eUEGJqgrQM79DaTvfGRgePsFyGED4ucvGJg3rnrG9PxZDAMb636AAGKUdlvB8P8/UNXv36o/mNiX/jKyNWWQlAT6BeKSn38gzmZgBbrm4QMGlk1rTjO8fRv95++/2/9//2EACCBmXsUgUYafv6L+/fylzvTtMz/jg7va37iEGH7wCzIA5RlAehk4gJpv3mRgXb2Y4f/bt0f//vrN8u/vL32g6GOAAGKUdFu576uEkuNvTh6gVSDr/jL8FhZn+CMuAXYFGLCAbH/MwPD0IdBZjEAExK9eMjCcPrkfIIBYfrNy2X7SM4EoRg69v0hskEvkZBkYQJgRGrWg8LhzxxYggJgYP76/zHHrNsStf0ChBsV/0fAvKAbJgdQePMPA8O7tZYAAYuaR8NzD8vC2zb//rJL/RKDO/ocDgyxnAhL7DjIwbF91juHvnzCAAGLmlgt4/+/n7y3M928ZsXByKXLJSjCwA53IzoyKOYCYExiY/44eZfi7fdV+hv9MocAk9ggggJi5ZfwY/v399xmIt/2/d1uFnYlJU1hdloEbmFy5gIHHDfQrDycEf9+9j+Hb1s3rgUEaD8QvQS4CCCCIAeDM8/fbvx8/N/24eVOC9fcvI2ldJQZeTkYGHqCt3Kz/GF6u2cLwZsf2ucCQTgFq/ggLX4AAYuaRDwDnsP+/gfg/0Jhff7d9vHZT8P+Hj+YKhuoMnIz/GG7OX8PwbP/+6UAnZwPxL+R8AhBAjOyC9ZCs+u8fOCf9//cflH25/v/93SSkKJcOUvTu/sPZQI11wCD8woAGAAIMAGDXa3m4JV8wAAAAAElFTkSuQmCC
actcolorize16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAORSURBVHjaYvz//z8DJQAggBg3B0IYTEBzfv9k4GXmZAgRVFL3+C5sYCohK8HLyc3J8Onls78f7py7uf7g9V0rL/5d9uoXw32YAQABxAAyYJMfEPsyeJxqNDv15vyq/3suf/h/6uW///se//v/9s+////+/Pz/98WD/9+vbvu/t9H5kYcsQzJMP0AAAEEAvv8AsU4AALNSA2Tjr2n+/v7p//7++P9Nsf7/OL3+/yqp/v/Fz9P//qh2//7GnP/+roj//vLc/9ymaP4+GQBuAAAAAAIAQQC+/wNaJwA7Hz4+qdTf8OGul5DWFfXMCwcuKQr4CgoAFgjuAFsT3QAKy5MAAPPOAPvawQABJDYAEi83ASsA2kK3x+K/AgBBAL7/A3BTJJwGGiInZnu1YbvS7X/339MgfVsoM0kQ7QBVC9cACgLzAAAYHAD7FCcA/xwfAAMECQABCyMAGxQJBObMuw8CiEXU0MhKwtyGYXLB9faf79/lyOppGP3/94WB7eNlYKj+YmD4+xcUxAysTECa9R8Dw6d5DAzSJ4HiNxhs1HmtAAKIhfnzC2YOMVYG17xwLYaPH7UYGECKgIH86ycDwx+gAX9+AxX/ARoGxL+AfOEnDAzAqPr//z6DCC8zD0AAMf9/+ZxPm+W1BT8n0Bo2oGWf3zEwfAXi7x8YGL69B+K3QP4bBoYvb8D0j08CDD8esjKwP3jLcP/Bp58AAQBBAL7/A8nk/b3ExeTJ1crY/Rr/8igXGAwEAP36AAD49gAA+vcAAPnyAP/y7wAB+PMA0Pn7AN07fgD0H0kA+9qxANzQ8u0CiBkUFc++M9wFGrTh4Ok3V9WY3zoqK/LxgL3w4wvDv/8CDN9E/BjY/v9hWPzvDkOn0UeGzfyXGD5cvsbwaf+fYwABxIScLK9/YthQsOxt6tWT94Ee/s7w78s3husvchheSXUy3Pq7mMH8HTuD5tf7DMpf7jDI3//BsPY+ww6AAGJBT9vXgRbM2fFiWZ8cYxwTyx+GF7f5weH38bYwgycvG8OKdY8Yfv5gZqjbxXDu0ieGtQABxIwtgzz+wHCB9+d3d3XhP6KyApcYRGS+Myj9b2UQ4rrC8OXtP4Ype//e6r/AkP/zH8MlgABixJXLuJkZlLwUGbKNpRmcRbgZxLjZGBhffGL4vvcew+49jxjm/vjHcBao7C9AADESkWNFgJgHlHMZwImE4RUDKICgACDAAIaNf6pWNsqkAAAAAElFTkSuQmCC
actredo16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJpSURBVHjaYvz//z8DJQAggJgYKAQAAcTIUAokeYCYC8xT4uBlSBfkFohSEZIV4WblYrj1/s6fFx/er/72+V8zw2+G+wy/gOqYgfgDEL9lYAAIIBa4UX8ZPISlhGe66LnIpemlM6gxqALV/mZ4/e81w5QLkxPXnVlr/+3N9xCgJecZmMCWgQFAADEzWANJFgYnDmGODSbqJiIC7AIMRx4dZtj/YT/DXf47DC9YnzOoSKowMAswC966ccv0/4//64Amf2P4AtT3h4EBIIBAXlAGGnCUg59D/Pfv34v+fvx7iuEfEHIw6PHL8icquCqwCysJA5WwMFzafYnhxa4XOUCNUxk+QbwCEECMDPkM64DO0Qc6KwUocJyBneEHAytQ8h1Q5BuDA6M84wKueC5ZJmkmhr+v/jJ8m/ltO8NjBn+git8gLwAEEDODIUMikI4EajwH1PiH4SMkcIDOlAIazMzwiuH/7z+/bX5pAkOEHajnIlDlY4ZrQLViQFUKAAHEwvCfwRdmGjQwGcAhzQB0ES9DHdCDf8Aueg3EvECszCAH1LMJaAkLw1OG6wABxMxgAvQvKFpYoaniByRwgKLXgWxjBgdgdFgA+d+AGBRwckAsBVR5HhgK7xjiAQIIZAADhgG/wdH0leEzw1GgY90ZhBlEwLb/BOL3QLwS6MZrDBnAtLMRIIDwp0RWhrtAW+KAGp4AWQzgkN8IxOcYOoFyi0FKAAIItwsYoPQ/oE8/MDwAhoE3w3MGNqDTdwPVZQFZ4LABCCDCBkC8cwMYOyoML4Ha/jPEAtW9YmCB6AEIIEZKcyNAAFGcGwECDADsA7VEijwkewAAAABJRU5ErkJggg==
actundo16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJGSURBVHjaYvz//z8DJQAggJgYKAQAAcTIkAskuYGYB4xVeHkYN/z8/f/kr48MyQxfgWLfgBhE/4ey3wMxCxBzAjEbAwNAACFc8J+Bg/E34zRHDV9teRHVMIbfDIHEuAAggBAG/GCoUtdRd7W1smXwdvXl4RbingQ0xIyQAQABxMxgAST/MMTy6PJ0qfqoMt9nvs/whv01A7sUO9+b62/s/n/+v53hL9jhDEADQRYxMICsZQXrZgAIIGYGIwYnBhWGRcwxzFwvOV4yPIbCj3wfGf6I/hH5d/mfNsNPhh3gkMBiAEAAgQzYysDBIPPn9p8/vz79Yvqt8Jvh9+ffDD+3/2T4d+XfL4YPDMpATd+Amg4y/MIwgBUggFiAzk9nuA905HUGfoaXDDMYtBjkwAoeAvEJhn5gaK8E8l8x/APyP6CEmjIQTwUIIGYGQ4ZHQMZjoPMeAk13ZpBlUGXgBYpwAPEdBnmG5ww7gfZfYfgMjCdGsEYOIG0LNGg10NonAAEEMgDsF4bvQDveMwgAlXkxyEAN4AO66gNDBFCzFMMXoMv+MpgDxTIYuBj6gGIgD0UABBAjMLmANDMwfALHhgjQsJ0MPsCQ0YEmHpCz70MTEcjQz0B8Bcj7wOALTID7AAKImcEYKvgFnC6/Ac09DfSQK9BQQXBAAVMbgwQ0pT4D4utAL79hiAVatBskDxBAjAwp0OT5ESmA/jIoApNrLdCpoUBPsAD5IPk3wDBaBnTlTKDIPbBaYHIGCCBGSnMjQABRnBsBAgwAfPOnyr1HEEIAAAAASUVORK5CYII=
actback16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAPFSURBVHjaYmRIYYCA/0DMyMDG8IfBguEvQxIDK4MvIwsDH0j8/2+GTwzfGDYDVcxjYGE4AaR/QXUxAAQQI0MqVPN/Bjmg5magljgdPSkGS01jBgVhLgZmRiaGJ+9+MJy4epHh3IV7DP9eMSwCGl4L1PEIZABAADEyxANJZgYZht8MawQ0GMyLfWMZwtV8GVTY7Bh+/P/F8Pf/HwZWJmaG1/+vMmy5u5Ohde10hidnf50EujUEqPMJQAAxM+gysAM194toM3p3xKYyuMo4M3z9/Zth79OlDK8/3gf65hfDw5+XGT79/sygLqTCoK0qwnDi5XmZL8/+CQMt3g4QAEEAvv8DACoAOgERAJFgVDgALxYnAOX44ADP6sMAHAQnAEgedQASCCIA0PSwAOn74QDq+OQADwkOACAdDADH2d0w+/H/ugKIBej3ZHldbgY5KS6G61+uMDx9/5TBhseHwU++ChiozAynvqxkuPrjHNi3TEDy0+cvDO9YvjBwqbAxfHv1IxkggFgYuBh8BeRZGF78eMvw+M1rhgChWIZQxUaw5p2P+xk2PJnO8A+olRGo+emXNwzn/75jePYTyOEDYqBegABiZExj+KcXy8EoxMPG4MvizVCgtRiomYnh////DG+A3vn99zfQqyCH/mf4/u8Hw8GP+xiSjuczAIUYGHYy/AcIIBDF8OLXL4ZX334whIjzwDWDADMz0IEs7AzMTExgvhAjL4PET0kGZAAQQCzAWHr/+u0/IUZRBoa6Z3MYFPgNGDyFM8GSe95MYei/P5OBjZkbmmgYGK5+fA5yOgPDRyD+y/AeIICYGTQYtP7zMBgwAA3+9pWBYfPLbQzafMIM6txmDPJc+gxHPx1l2Pr0CsOjb18YHgLx939Ag0Dm3QXixwyrAAKImUGb4S3jL4ZEHlmgwZwMDL//MDAcfLuTQYtPkkGL247BVsCcYd3r6Qy/GP8zcLIyMHCyMzCwfgOqOws04AtDHkAAMTPoM7xk+MwgCxQ3kFBiYeBnZ2b4BwyDYx92MUhz8DHc+36TYd/bXQw8LMCMAZTjZmZi+HLqH8PPewwLgQE5EyCAGBmiwN6TAeaDNaKGzOaK5uwM3EJsDD9//gWmyB9AfzMycLNyMLCyMzF8e/eL4f7Jnwyvz/89CdQMTsoAAQRKyiDwCRjVu749+y/84ekffSZgPAtzszGI8fAw8P1nAzr1P8Ozyz8Y7hz5wfDh9r9FQM1Z4BAAAoAAgrkABiDZmYUhiRWYSJhZmfhAUfrvz/9Pv0HZ+Q9mdgYIMADeVDlsG0BwywAAAABJRU5ErkJggg==
actup16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAOxSURBVHjaYmSIYWBgYAFiJjBmZvjDYAnE4QysDM5AvgojUPj/b4Y7DN8Z9jIwMqwEqj0OFPrLAAUAAcSIZIAYULiRgZchQ1NbjMFQTZ9BU1gYaCIDw70PXxguXL/GcP7iPYa/bxlmAA2vBwq/AhkAEEAwAySAmhdxazC4FngFM8RoBjOosdkw/AJa+e//XwYWRiaG1wxXGdbcWMPQs3Exw5Ozv3YzsDHEAXW+AAggZgY9oPa/DO2c6gwR9RFhDP6Kfgw//jAw7HuyguHl57sMv/5/Y3j25y7Du5/vGDSE1Rh0NMQZTrw4p/zl2T8uoPN2AQQAQQC+/wMAKgA5AQ4Al15UNgA8GzAA5/jiAM/jwgAbAicARx9yABkJLwABAQQA1vS9AOX43gATChEAGBgHAMfW3jX99QC6AoiJ4R9DhLgGB4OSHCfD9a9XGY7dP8ig8F+fwU+lkoGVmRPsSyk2bQZjviCGFz8fMRx4sY/hEcdjBi4VFpBUBEAAsTBwMjiLKLIyvPr+nuHpkzsM/rzRDKE6jcBAZYaGMgQoclgyuAgkM4SfDGG4/e0fw38+oCBQL0AAMTOYMPSLGDAyf2f7ymDHaMuQYTALqJmJYePdFgZBdimGP4zfGXa87GKQ59JlkOE0ZvjN+J5h59OTkGh/yCAAEEBMICve/P3FcOPrR4aPAr8Znvy5yjD5ZRFDy90Ghl//fjOwA13SdWcKQ/LFCIZH3y8zfP33CeIsJojLAAIIFAN3Xn/4r8nMxcDQfn8zw/wXmxle/2RgEPsGUsMIxixs3Awr7u1n2PNan+EtUI6BA4i/AvE/hjsAAcQESmH/HzMw/PkPTHHA9PX8M5D9A8KGAWZQcLADXQqM3v9ANiMXKAUAMVAvQACBYmEF4wMGBt4PDAwCbAwMfEAFXECah5UJmIBYGFiY2IBirAzsrEA5oLgAUDMP0BLGh2AXrAAIIGYGfYbnQOeIsDMxmEoosTDwsjEzcANT3j+WvwxqAnIMb34/Zdjyag1YtQAHCwM3MIC/nP7H8PMBwzRgEpwDEECMDFFgV0oAM9AiUUNmVwVTdgY+UXaGXz//M3z9/Q2o7T8DNysnAwc7M8MnYOA8OP2T4fX5v7uBmsFJGSCAmBl0wQZ8AYbWzm/P/vN+ePLH5P+X/wz8HMwMAkCNvP/ZGf59+M/w5MIPhrvHfjB8vPNvBlBzHlDPS5BGgACCuQAeXuDszMQQzsLN4MzEzKgCEvz39/+dP1+B2fkfZnYGCDAAkBQi8GwctlQAAAAASUVORK5CYII=
viewmulticolumn16:view:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAM9SURBVHjaYtRtf7hLWIDd8c+v/wy/vv5h+PX9LxAD6W8I9u8fQPrbX4bf338z/Pn5j+Hfzz8M///8YPj//eF+gABiERfltjNQE2L58IGB4csnBoavXxkYPoPoTxD+f0YGht9/GRj+MjEw/ALS/34yAAWBmBFEb7UDCCAWIQ7G36o8DOxAtQw/2IGYF4j5GRi+/wDS34H0NygNwkDDfwEN+Ac0gAloyq2LLL8BAohFTfg/Q4Ie0LD//xn+//oClAWaxMYDlGaE2PT/L1D8K1CYGegKToa///4y/Pvzn4GdlYEhvpqJASCAmJiBaliBzmP7+pjhf5cMw/8eGQb2n08YOIAKONgYGNif7GBgaBNiYJmjz8DLzcQgyMvKwM3JwMDF9p+Bhek/A0AAMTEATQSB/0D677evDEw/vzO8f/2aYfHSFQwv3wI9xvif4d/XfwxMv78z3Lp1l2HhoiUMHz9+AboEGC5//zMABBDLX4h+BkZuSQbOpDUMTMxMDL8FZRlkZb4xsLEBnSFlycCSsgRopTADOws7g4S4JAMjIyNQMzA2/v9jAAggFqDnISawcjAwqQeAmdxA7GAvCmb//svJ8F8niuHXHwYG0d+/GMTFxYEB+ovh9+8/DP/+/WMACCCW/zAD0ABI+Pfvf5DABQfcP4Y/wMD7B2IDo4ERJA7EAAHEAuJgaAbiP0ANIMX/GVkZfrMzg9PBP2AsgZ0OtJkJagBAAAED8R9E09cXDD9nW4Pxvw/PGBiAYfGflYXh78MDDMxTdBhYV/pAlTKBA+/vn/9gVwIEECIMgKH87+4pYACBEsxHhmfv/jEIiokzcH5/zcBy7xrDf/G3DF+AyfTd23cMwsIiDMyguAfqBQggJngQsPMxMBmHMLCahzN8AOaBDevXMLx59pqBWVCZ4behBwODThDD82dPGHbv2cLw48cPcFoGaQUIIIbqVY8+A/30HwUD3Qiif3/79v/zpx//P/789//Np3//P775+P8bkP/iyev/b5+9+O+fsfEzQACx7D739s+T5x///PwGzGnAuPrz8xfDn9+gXAdMWCD6F0T8758/4NCFOZiZiZHhxr0PfwACiBFXNBILAAIMABvGsDfmxCuOAAAAAElFTkSuQmCC

filegroup16:component:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAO3SURBVHjaYvw3jwEV/GZgYmBliGRQFCldufbt6gMX/7dOT2Pw/PyJyev+3X9l374wfGf4xsDw5j0DQ8h2BgaAAGKBa/wDJj0YZKVrGPTMrBmkRBnMP28XY/z6+DWDjmU7t6SKkMjKNaoPzn+PZWJgeA3TBhBAUAMYrRlEJcoY9Hz8GBS1gfy3DAzfrzAoCP2VVHAXmPlfzYaBifMrg2S4qfufb6d3P77wPfw/A8NNkE6AAGJi+MfA8J+DO4HBfTJQcwQDw9+PDAw3djMwHD/K8J+Hl+E/LxPDty2LGP6+uMHAyMHEIOshqy+rybYLaLMtyACAAABBAL7/A39RAEsA9vrcAAT1TAH85QYAyqEAAPLqAAAdGgABGRcAAf77AAMA+gDyz+YAAfX5AAUK+wAPCPkPzsz7JqrbAKcCiOXXbwYXVnnNNMavj1gZrm9jYJAUYmAQl2Bg4OVhYODiAtL8DMy83Az8sswMb0+/YPh16wPD+SPf7zQfYajzFGP4DhBAzEWuDDufv/7GzG9i5MggxML07+MXBiYZMQYGAQGgAfIMDExAP/KyMjDwcDP8ePub4e3lDwxMLEw/Tdn+quhzMPwBCABBAL7/AgQDAADz8PaD6rKzm//5+QD9AwcA+N7tAAAECQD5ztcA9c3XAPLX7wDnt+AAAggBABlAGAD+/gADrd0A21/OANcCiIWVkZFBDWghkHr69+Zjht+MbAy/3r5heHf8KcOf178Y/vIKMvA7aTHwGv5n+HHmEsO1TU9/BK/9F/nqL8M+UCACBBDLbwYWoOb/DEzMTCysiqIMTD//AqOMjeHPc6Dm/+wMbKJiDD+ev2D4cuYeg7jCbwZWMZb/r/7+ug9LBwABxPLrByMwHhkZGFmYWDlFRRiYOZgZOP/9Z+BkZWdgAMr9fwd0ybdvDKyqwDARZWVgOvOCkYnhF+s/qAEAAcTy5dkvSEL8zbD9465nKQrRBmIMXMBY/gM0+AfQaxz/GFiZgWw2YPoDuvT/99csyCkfIICYgNEMDuhHHxmOtEx/5fV41tm7/7/xMzBwqzAwCAIDR1qKgUFMjOHXpe8MW3Ou3q1a+q4SqPwlzACAAAIGADgAGf6D8hEzw9mrB996PLm7Y7VxZaoBm6Iqw78z+xiOzLv0bMq6Vwu3vGKYD3TUbWQXAAQQqnOABrFyMtw5e/a9+6fC6ask5MVNpm64s2TlY4YZnxkYLjJA7EEBAAHEgi4Acg07B8Orw1c/+87b8lnrxT+Gc+BMjgMABBgAAPY/UCNn0RUAAAAASUVORK5CYII=
component16:component:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAB7klEQVR4nJWTS24TQRCGv5oZZ2yTiAWPSFkkCIlVxAEQYsGWA3AWVjlExCE4AmdAiA0IJGQhEcURIsGOHdsTTU93sejuedhmQUut6a6Z+uavv7rl5N13zXd6WIXKQunAWDDhaZWt4/xmxemrXOI+6+c9njx+xKSAX0u4msHPGYxv4PcSJgW4bTD7h1Ou622WivJwULKXwb0BHO7B8X1YlLAwUBhQPEwBDdCzadXhZv2e8PQgxYGf2pr40qzzexveG6u8/7IGSgT6eVonOvXJMTGCrEIS4iTKerUZrWSNiboGdE08wjdAGksK9TuF2dIwnhrSfMik8KZfrWB+C8b4b76Nd3l9dNtVZFu+WIXJomR0vuBgv8d8BZMFXC5hWkBZejV3h0NOPhzqxFjePh9Lpq3SHI2h+7vw7CjBKDjXLcsqVA4SgY8XJijS7b6kaUK+k5KGpCqYLQ4k+CECKtJ4tA5qG185f8qtepgN0EpBaE5+3TW3pszRJNiwjrA4k9CkDUU1KMBjsnUtJa6JO/FxD1IwlXaMtFbRLQoq7SrrKPp6ucR+uqjvkQOq0nL8YOD/7hoVW0FR0ZsXfYHmYMXx+XqgIr4zIt7YBN9yba2T2LUNQhijOVRnRe2NxkvrGh8TgR9zeHkHZDQa/Yv1X+Mv3FmXp7TcaosAAAAASUVORK5CYII=
setuptype16:component:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAANfSURBVHjaYoxf/u8cM9N/iTdfGf6++8rA8PEbA8OnHwwM338zMPz/xwAG//8DMQMjAxM7A/u7ZTEdf28t62OAAoAAYpHi+yvHzcIg/Buo4T3QgK8/GRjefGJg+AY0iJGRkQEOmICGfGZk+P/nlzKQB5L4DxIGCCAWA6m/v2zl/jN8ARrw4w/Q5r8MDL+BUl9+/Wd48Ogbw99ffxn+AdV++/WbgV9CmKHj1N9fD+5BNIMAQACxCPGwMkgIMoJFoC5meP35H8OTJ98ZhERYGQR5uBjeAW1+9Pwjw++37xg4GJn5GJAAQAAx7Ljx99m/f//+f/757//HP//+33395/+xS9//v3n35//X7//+v/307/+ZW//+H7787//1R//+L15x4Z2EtFEATD9AADFshxrwEWjAi2///h+7/PP/p69//4MN/QYx4OKdf//P3YKwQeKTZhx5xMzCpQLSDxBATAzQ0ADhd+/+MXBwMDN8+83I8AMYJpzsDAwcrAwM3FwMDJLCQJoT6E2gwoRYK1kDY58UkF6AAGICRRHI78CwY/gGjIE/fxmBfmZg+PCFgQEYbsDY+Mfw+/sPBh5OYFACFX0ExtQvoFpjMycnICUCEEAsII1/QBho0J9/TAwfgNH3G+o9UCzuOXKN4dbduwxR/s4MbFw8DO8/Ai1kYWAQEJGUAyqRAAggFpDt/6CuAGFeDgYGcX4GBn6gszmAXuDm5mEQFhJlYGeFeOcHUJ6RDZQQQFYzsAIEEAs7JyMXB9Cmn0BBHh4GBhkg5mSF2A4y0EBbnsFSX5aBn4cRnHz+Ai1jBqp9dO/yc6D0Z4AAYlm+fOexHUzvpX/9Z/z76wczS260r462EjsjyP+vPoKSNCODAB8zAzBoGFiZGRjEhBgYnr5kYDhyYMMxoAEvAQII5AxQwlAAYlkgls4qXzwXFFWvgVF2+BowDdwGRu8HSBR+/wmJxvLq+U+BznEBBRNAADGgA04eCaG2SYe2Xn/+7/+BG8A08Pjf/3c//v3/9hdoABC39W58zsbOlwG1mAEggBgZsAAWNj5+V+/0SgeP8DA5KT5Rfm6gW1+++bl5w8ZLG9dOmfP3z9dtQGUfQGoBAgirAQzwaGRWZmJiFAGmFWag04HB/g/oewZQ4P2EqQEIMAABhn3LmYHXTgAAAABJRU5ErkJggg==
actstop16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAMhSURBVHjaYtzPgAD/GRhUWRgYtvAJCSn9//eP4S9Q7B9EnOEPExPDs3fv7n1jYPABit/+CRQDYYAAYoFpBipUZ2Vg2KSWna0mlpPDwPD9OwMK4ORkeDxlitrRqVO3/GJg8AOK3AQJAwQQcwJEsxYzA8NWjeRkFbHCQgaGHz8YGFiAZgNthePfvxn4ra0Z+L5/F350/rwXUMUeoMteAwQQczzQZqDmzRrBwcpi4eEMDN+AjmRnZ2C4cYOB4e1bBoY3bxgYXr1iYBAUZGB4+ZKBX1mZgf/XL8EH16+7A72wCyCAmJMZGI6p2dmpint6MjD8BfrO3Z2BQV4eaPZrBobz5yGGaGoyMFhZMTBISjIwXLjAICgtzcD/7p3QgydP3AACiIWXnV1VXEmJgeHaNQYGNTUGBmZmiJ8dHcE2wtkgALTgL9DQP4cPMyg/f84gzcioChBALP//AkXv3mVh4OEBBgswXF68YGCormZg4ONjYAB5CRZDQMN+BAcz/D52DBw7f0DmARFAALH8A0YXw9OnEH//BwbLqlUQ/qRJDAxCQhDNwDD45uvL8OvMGQZGIB+EmaBRDBBAEANATgU5HcT+BYwkXl5IoEEBo6goA7OiIgMj0AAG1HTDABBADCeBEQTU9v8vFP+LjASmoX8Q/PIlBEP5P8LD/38FqgFhoBf+rwTqBQgghhMQe8ECf319EZqfP///19gYjEFsmPgfoBqQWpCe5UC9AAHEsBoYdA+Zmf//Y2f//09N7f+/u3f//3v79v8/R0ewIjAGsUFiIDmQGqDay0A9DUC9AAHEuBCShLfY8PKqyIACEhjHDBISwNRxDBKwIPDzJyQdgGIIGMA3gPzlnz/fAXrFByCAmIOASQXI2Pvo929PIT4+QX5WVkgiEhAAp38wBkUpSAyUAYCBvPz9+3ufgfkBmNhvAAQQODMBw//al///vXa8erXJhYdHTQmUEkGpEhkAY+nG48cMK1+9uvX5/38/VmhmAgggeG4EGnLzy79/Ptvu3dsi9/GjEiMjI8M/YLoAGfMfyP4NZN98+/beZ6AaoObbMH0AAQYAH1BuIRSQxJ4AAAAASUVORK5CYII=
actreload16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAAuNJREFUeJx9k99LUwEUx7/b3XWbzi3d3LRtTs1fzcpMypRZyDQJNegliyQlCot+0V8gvdlDUA8hhYRF9FJgqKQVZhr+iGrRL8s2U8fmNle67d67uevdvT2YErI6cF4O3/PhHL7niPCfaDNBlmlEvVyR0BoOspdPjePzRo0kXuPVAiSnacWNhuItZ80Nh3d5bB+FsfsDkXhaYmOhsxx1RZXabktzScsOa1aGUq2EmMgAQZA11iRfsoXlbM9C4P4JaDAgRZujOGau0qoQDQG+eSiUMVGWuTDNaK6oZhh32V4iMDDgRTguoNcFd2mE6Qu6Q/szzZp0go/BPjEJWWgaKpKFKa8sx+ueyRW+hR9NAgIBAJ0VKGjQo7DBBH1tMgLnP8FrESLPqSWmVm1M1jy99/2aY5p6q0uNlKlIHkmJqVtFy87xXhccYgBI1yv6rBebh4sO1A6RSuQDQOs7TM/YFusHOr+8FAsYPN6/cmloxHN3mXLBKAtBnSJtWnchRR7bnG1WEGHawPIR+NbWOT0BRxtYKwAxAAQ9XPusl24s1AgynVJSDkRXAVGW98M7b5IJJAkJ9ADca5ArAI/VxPxPzDIR7hdkEn2iVKLFGtm/xL6IuZwwGFSSTTrZGQC4bUF+lwUdt0qhWYPpVFCyUT4lsLgMeplbWXehVoOgWsm3aIwaKNX6ku2UI8pzkFtONLVzLF1VsbLU+8QP+qAaoiAdmZn6EejzMysPeuYwJQKANkBcXE9211VnH0owbIPHx8Ex5QzuOXpSxZNSDN68MTr7YfLIhfeYj3uJw4BgSeJHggxTmSGn9ampCTAV5sskgVmQ3lfIKrdmMuFojYXwjPa5sBD3lPu9oPbJucdOD5XI0oHcBMolTWT9IoRD4H12hIUknc/tme6ZE8b/Bog2jgQA13cib3exaqzYrNbY7UuUfS7wcDEgdHjewPbHlfWI+42CAL93gfE53fSdRSrWde41vsbTAcBv28c0QadsTMsAAAAASUVORK5CYII=
Added lib/Icons/InstallJammer.crystal.toolbar.png.tkico.




















>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
filenew22:act:actions:22x22:data:iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJGSURBVHjaYvz//z/DuUv3/jMxMTJgA79+/2H4/es3w9+//xg+fvoKFvP1MMeuGAkABBALiAAZaqCjiCH5D2jpj59/GP78+QfGj568YBDg52XYvOPkf0KGAwQQEyGbmYGWgixmZoIoZWdjZTA10gQbjk8fQADhNZiJEWggMxMDCxAzs0AcyMXFwSAizMOgpaGI13CAACLoYhBgRPI0Bzsz2CIpSUG8LgcIIBbiDIYEx959R4EYU7731u3/xXkxKGEOEEAEDQYZCEo5oGBJig8Bi/39+5fhydNX4BQDkluzZg2GPoAAYiLWxeCIZGYEG/rl63dwigGFPxMzdiMAAoigi///+w92Fcigb99+ApPfL2DS+8vAwcEGlGMAy2EDAAGE12CQYX+AGeMv0HBQOv4HpGGuZ2FmBnoBGCz//mHVCxBABF388+dfSFgCISi8WVlYwEEAyokg14JobAAggFjwuRaU60CuZQJmjn9Ql4EMZ/zPhOJ6bAAggFjQDYMBkKH//kFcCYw+iGIWBrgLQUHxDxTIDNgjDyCAUAz++esPRs4DhSPIAlCmgMmCgoUBGOYM/0CpAruLAQIIxTpGJAgVYMAa6f8RORLiakwAEEBMeLPxf6TszAjLMEzgsIVhJkbsRgAEEFEZhBwAEEA0MxgggPAbjKcox5XjYAAggHAmN1D4gvigFIEcYaD0/B/KgWR17JEHEEAoBrOxItIOzEBQlgXZB05ywIj6D8scDH/BFjD+we4tgABigZRaTAyllW1UDWOAAAMAdi/vQfhaEusAAAAASUVORK5CYII=
fileopen22:act:actions:22x22:data:iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAATeSURBVHjaYvz//z8DLQBAADHSymCAAGIkVUN540mFf3/+z2dlYzL4/Pm34uQu6w/Y1AEEEEmooulkQeeEi++v3/ry/879b/+zSg6vx6UWIIAYQEGBC8NAbespg6rmU+f3Hnjx/+vX//9fvfr9//37v/+nz7v1Pzn3UAA2cwECiFE+8fr/AAcxhn//GBh+/WVg+P3nH8OvPwwMa7Y//fB9i75gQ+eZBgUZgXpXJ3kGfl5Whj9//jP8/v0XTHNwMDPUtJ388PHTT8WlsxxRggQggBhty+79769XBBv2A2gwiP75m4Hh6Z3vDA+P32IIcpFlMDEUAhoGlPvFwPD3L8JgkK/uPv7C0Dzp0obdVxgLGS45PIAZDBBALOip4g9Q87NTTxl4//xgqMvTZ+DiBBmGPRj//fvPoKMmwGBrKBTw79/bhXsvMcANBggglr//EAZ/ePSd4enZBww+LgoMCnKceCPy/Zc/DBM3vGQAOhvoA26GW+/e9zPoHzQAhylQDCCAWJBd8+nFJwYrU0mChn74+o/Bu/YWg4uNFIOSLA/YLAV1CYXPX/8W/f7D8GFi7xlegAACuhihgUlajKFq3hUGc9N/DP+BFv799xcYDP8YgOmW4R8wbP9A2VtPvGMI8ZRnYBMVYDj4kAFsMDsHA8PF8x95H++98wpo1AGAAEIJivV7XjMoqIoy6EmzMAiKcDF8A8p9/wXCDAzffvxn+Pb7H8OPHwwM6WoSDD9ZWRhO3YMYysjEwPD24XeGV8cf/GX490WBgfF/C0AAoRi85/ArhltLdBjevvrNwC/MwvCPh4Hh9WcGhjdA/PA5A8OX90D2TyAGuundh78Mb17/ZPj29gvD86uvGD48+/qB4QfjYwbev+oMTP8PAAQQy58/EEP3n/rOYKvLx8AJ9BKrGCvD+VufGETl+BhuPWFguAP07ovXfxhev/nL8PINiP7D8O3Dd4bvH74CDXzP8B/oK4ZvDK8YWP6yAAPwGsMttwcAAcTyD5rcDp58xxBkLcQAjBeGl0BXvWLiY7hxAeiz/8zgYACl4R+//jH8BBry4+c/oGu/Mfz+Bkzc3NxAs4AaGICY+ZcAw/9/s0DmAQQQ0z9ghHz6ysBw+doHhnAXHmCyYWB4AsTAoGR49/kfw8cvQMN+Aw0DGvgLaM6Hj78ZXrz4xvCXhZ2BiYMdNbkw/+Fn+MuwAcQECCBwqthz/DODnR4/w4svDAw8QM9IAoODB5gq+CRZGD6++8Xwh4WRQejfHwa+3z8YeMV/MSgLMDP8+/mT4d+3nwx/gNn0+zdg8Lz9J/zw8e9XDA88L4AMBggglj/AZHTg2FuGskBxBg1eqM2CDOAs/OMHKPEzMfz8+QeI/wKDgwmIWYDif4DiIJoTyGcFYg6GdYc/Ci949H8zzPEAAcT0FWjbg4efGfzNUTMFEzAJsbAwMTAzMwLZTFA2E5wNokFyMPaRq9+Bae//Rph+gABiefvsK0NWlDxG7mJmhmBgUQNMq0AXAwP4+4+fDN+//2b49u0XMAJ/MvwAsn//BsXBH4Y7t78BI8d7A0w/QAAxMlif+K+uysMgwM0MjND/4ATPAKb/gXPdX6DGP8A0+RdYnP4F0n/+AEs2YOn2D8gH08Dc+fXbf4afr/5vYHjqHQgzGCCAaFbnAQQYALG5hI4vT2e0AAAAAElFTkSuQmCC
filesave22:act:actions:22x22:data:iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAWNSURBVHjaYmTABIyLFh399/TpS4Z9+6ZLs7CwfHn16tV3JSWlf6tXr/4HlP/PQAQACCAWdAEHBwfmx49fMAQG2jD8+vX7KQsLG4OEhAjDnDllMtbW1p9+AMHZs2f/Qi3AaQlAAKEbzBgX1/xbWJif4f///wz8/AIMzMxMDO/ff2awtk5/wsnJxSAuLsLw7Vu2FBMT02cODo6fuCwBCCAUg0NDQ5kePnzGYGamCjSYgeHnz18MpaU+DC9ffmGYP38/AxcXB8ObNx8YbGxynzExMTPIyEgxvH2bK/n9+/fPL1++/Ak0AhZU/wECiBHZYGNjY1Z396JfkZFODJs3n2JISnJiEBPjQfHS8+efGaZO3cnAyMjI8OPHL4anT5+DfSYlJQoUT5EAin8BWvIDIICQXcyYkND1S1lZguHfv/8Mr1+/AxrKjRF2kpK8DC0tIWD206cfGXp6toCDDWSRpWXxC1FREYbly/MkAAKICdlgUEqQkhIEK+Tl5QUJ4Y15KSk+hpxKf4bv33+AHVNREQ700Usg+58iQAAxIQUD8+fPXxk+f/7BsGrVEYaMDDeCSQrkyu66lQwKCtIMf//+A0bqLwY2NjagoyyEAAIIFhSMISFNv4SF+UC2Mbx69ZaBm4edoMG/f/8BRuxrYCSKA5OpFkNf3xqGAwda4//+/fsVIIDALp4x4yALKO3y83MBDf0ESr8MkyftAluCD7x48YVBWFiI4c+ffwwCAlxAfb+Arg/7C9T3GiCAwAZnZNj/BwXDjx+/wdjZ2QKctPLzFzNERfUzzJx5CKvBjY2rGOTkJIEG/wWm9W8MnJycn1+8uP0RmMa/AgQQKHYYa2vX/+PgYAfazsvAwsIEDjtQmIEikZWVheHJkzcMjx69AKbZd0BLzRmysuwZHj/+wJCZOZXB0FCbwclJh6G7eyUwGFpigeY9AmbO6wABBApjxuvX7wITvSE4XZ48eRkYCd+A2VicQV9fBei9Hwx8fFwMurrKQJcpAA18zZCaOgcYDK8YjIx0wC7n4+MAWvoGmEuVvv3+fec1UOgrQACBDGaCxeiXL98YtLRUgEHjwLBlyxWGbduOAV3MyiAoyAfMykIMHBxs4CACRZa4uDA4Ln79+gPU95NBVlYW6DO5P8+fX/sCileAAGIsLV0J8jEwfNgY7t17yuDubsYQE2MKTHY/wWkTlJ03bTrPcPToeXC61tVVBaeGv3//g2kfH2NgMKwCBkNzLDDSHv358+cGUOFbgABiOnjwKDBMGRg+ffoOdPV3hqAgfWB58BWYOr4wfP36i0FUlJshPNyUwdxcD2g5B8OxY+cZLl++DfT6R3CkgVIDyGViYp6/gJH2BhQMoDIDIICYdHX1GK5evQNWBMtBb99+Ayeh16+/MNy69Yrh7t23DFeu3GUwMFAHRpQFOA6AhgDj5CfDx4/fgcEiCnTMza/A5AYKhl+gQggggJhWriwQV1NTYnj48CnYq1FRExguXXrK8O7dVyD+Bs6J588/ABrwGWjxT2AYswNdJwb04ReGiAg7ho6O5cCyISf2z587n4EG/ICWcAwAAcTy5cuXzzNmJCoD2TJAL3FnZMzftmjRDqCL/wBjmZkhPt6DYe/eUwy2tkbApMgMjNAj4EwB8j4fHzvQgk/ACFb99uPHDVBq+AIzGCCAQKniJzDdPQfSn4EJnGP69AQtoDfFgBq50tPnbVuwAGLJoUNnGfz87MDBICgoADYYFAzCwiLAiPz7A2rob1iBDxBAsOKLEYpBOZENiEHlJTuwQOEFxrQoyCeZmQu33bnzEJwSQC4H0SBw6NBCYDDcfwhk3gSlBiAG1SgMAAGErVzEagkQg0p8UWDw8GRkLNx2/fodYNkszrB0aaY/UPwWKMcB8XeYiwECDABukX1OGPR1gQAAAABJRU5ErkJggg==
filefind22:act:actions:22x22:data:iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAT4SURBVHjaYmRAAsuX71BgYmKs//CfJ+ALA7fATyZ2BhGmTwxc/75eYPn3a2FEhMcEBhygad7x/4ePXWfYPSeJEcQHCCBGmMS8eRsSXjMI938UVBBgFhZm4OdlZGBhYWT4/5+B4def/wysr54x8L26dYHh18/ElJSAC+gGu6bM+//k0VOG67tqGUGWAAQQ2OBJk5YnvGKTnf9bxZBBTISJgZODkYGVFWLnr1//Gbi4GBmYmZgYPn/4wfDv3NEP/z++N8zLi3yAy/UgSwACiKm9fb7Cq3/8/b+UDRmkJJkZxMVYGKQlWRikgLSIIDMDJycjw4/vQGcD7ZGS5mTgNjQU+PWPcT66YSUTD/xPqN/0H8QGBQdAADH9/Pkz/4e4moCwIBODED8zg4QwE4M0LxBzMzL8BrpWUZqVQUCAGewLRiag4aoiDGwy0g719dMNYIZmd+78/+jJa4anT98wmAT3gw0HCCCm979YAjikJcEu4wF6mR8YBGJACUkgBgYtA/e//wwC/CBLmRj4eJgYuNgYGWRMVBm+ffsRDzP446dvDO/ff2b48eMnME7A5jIABBDLVwZuBQlOJnCYMjEzMAARAysQv/rxn4EXaBA3MAJ/A4OBBeQKIAZpk5ITAxkMd/Hdu08Z/vz5w/D752+GL58+gcUAAojpJxs/AytQFzBuGF6++ctw6dFvhuOv/zLc+/2fQQzoC2AIMHAxQDA3FIPY37//hIfv8RU5in9+/wEbeudgMzjWAQKI5e/nN0CXQpIVP9CFHECvglwmzgX0PpDxGcjmBGI2BohvQC7+BcTfvn1HjrsH5zeWMCILAAQQ0/cX9x+AkhQLUNezl38ZvgGDABQsv4CGfoAayIHkYpAlr+4+Abr4xwUGPAAggJi+vn624cW1G2AONzDyfv1hYPgNCX+wC1mgmAPJ4N2rdoGCYiE+gwECiOnXrz+Nt7as+/ANmFb5gMmMhYUBL7hz8xHDpTPXGBQVZT7gUwcQQEwHDsz98O3Vs8Tjs+YzfP32j4EXmH4ZoUntL4iG4h9AfBloaG/rLAYDA3UGPj5uA3wGAwQQMzjkH5y/IcIpcfHhmYse7AKiHGLA5MQGDGdgnDLAYmTbip0My2etYdDTVWOQlZVgEGV/F5Gne7Mh3IhLYempzxvRDQYIIJSYdHBIFgBS9XxiIgG8QvwKzEzAFAJU8eDqnQNA8YXW1kYXgDlVQIDp1Xy1b+sVzAx4Gd7fv8Nw/Tnngqh5zxORzQIIIDCqm330v23M9P/QOCIIZkRKvn99uub/t+vd/9+ssPx/skzg//QISZTyAyCAmMAJ/ORNhlcvXoGYP3K6dv038O3+j8/gr98ZCo+v38jALijAwKXnz6BspMmgI/Utod0XYThAAKEjGceEWf/VHOv/E3J1rZtEwopi3f9/X877/+1a+/83y83/783h+1/hJAE2HCCAGDuXnP7/+u1XhjfvPjEsaPRjZCAB5FtLJBgYis2Pqy1k+PnmGcO3ixsZTh+6zrD5AvcCgABievT0HQOsyDMO7P0Pq2ZAhTUhgycefbHg0LGXibPrJjCwi0kzcOn6MWibqTL8Z2JNAAggpq/ffsKLPAZGiINBdReomiEGzD/3csHxky8SZ9X0M/zhFGKYuw2YQw1iGAACiBEUpsAikOEnsLRCLp1IBfEG4vM5OZkSWLSiGO6/+LEBIMAAoQTTM1JSBJkAAAAASUVORK5CYII=
actrun22:act:actions:22x22:data:iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAATcSURBVHjaYmDAAySi9xuIR+9XYCADAAQQIzZBydgDDn8EOPb/0BRm4Dj74gLj11+O//79S2D4x5D//9+/if8ZGBa8W+f+AZ/BAAHEgsyRij9Y8P8/wwWgZoNP6soMP71FGH5LcBtwnH7+nvHtN4aPmcYM7Kee9XPuuCMAVN6Az2CAAGJENvSbvnj/f6DJ7NfefHgXYyDwR4GHgennPwaONz8ZGJkYGf6xMzH8ZPjLwDP11Aem198a//37/4Hh//8Hn7b5HEA3GCCA4AZLxh08/zzdzoBBBCEpcvg1g/CVdwzMTH8ZmJgZGVjYWBhYBLkY3sgD8a1nDL952BiYLz1nYHryMfHLTr8FyAYDBBATjPGTmd+AYQOQ8RaIfwENPfCaQfzuOwYuwT8M7Pz/GVh5/jEwsv1i+Pv1A4Pkgw8MBtISDOwWSgy/rBWBjv5vj+5igABigcX+/1/vP3B8fyHwg00CaAsDg+i9jwx8CqwP/v1h3sDwn+EjMCj0GZkZHRgZGQXAXv31lcH6PgvDqX9MDN///RdANxgggMAG/+HlOP9dXZyBgfc/2LVcr78zcPCzHGDjZw08GCUDj337ZU8EmFiY6hlZGQtA/L9Axfr8wgyHzZUCOP6uWw+M9IM/D4ZMAMkBBBCjeOQ+hR/SIvc/+ujCbWP+/Y9B58CjAxdbFR2xxbjngfcJTKxM80Fsnp8sDAcZORhevfjMwLz9AgPjvdeOv46EHgAIICZg+Cj8+cvDwPCcARwEIPwX6L3fghwOFu1PsGaO7Q6CCzhEOSZwinMyMIqzMkgDPfpPiJ/hr4kqKLzzQWoAAghk8APmd58ZGM4BeXuA+DEk8p7ICDKwsjH140qnrLxsjSzcrB9YuFgYmP4zgvUwbb4KMngiSB4ggJher3R5wPrjHQPP+6sMHN8fMjC8hxj8iZWd4YUgb4DbrNfzsRm8QpIRFPYH2H4xMvz+y8jAePc1A8OX9xf+//1/ASQPEEDg5PZ2pSMj27unhpxPbmxg/fESHiS3OXgY7nNwJ/gv+3A+dO0nB3TDOb8wPPgDNP76OwaG/2KiDH+dTQ3+s7OeZzJdpgAQQChlhYDftv6v5kYFv6XFUQzgYvzHoMv5m0Ge5/8DHk6mA6xszA9ZWJn8H3xmNDj8Aui730g5bu8JoE33DAECCMVg3sQj/z+7WAO9BBVgh0YoEhBmB2Z5FkaGZ1/RnC8KxMBIZJi5nYFhlxcjQADBCyF+n60OvwU4GBjkgJynQMwGVQxyzRMg/gxR9/YPlgKR6RcojQKTyyUGhjfvwOkYIICY4Vn61rIHnEK+Cv8kOA1ABnKsOcHA9Owdwz8DYOEhC1T2ENlrQCwOdSHQTIbnwHJgDtClT98vYDgXkwlSAhBAqEHhsUng/7//+0ElHBAlAtkG/zlZ+n+W2wr8v8yPUOgOzbPfgfgw1FcrgQXNoUC4eQABRBCx261xYO6/+p9hE9Cqxf//M+Xe/M9sseI8Y9mJ/wwPgWInQU449p/BaAlKmgcIICZCBoNcDwb6QKz5lYHx2tUHQEFHhn33NjDsv8fAsPo4A8PFe6AgKETWBxBALAQNBhbmjNtvP2C+8lLh/5dfDP8//wz8dyryA4Px0kKGScdBSiYCDcUo6AECiGjEbL5cgMlsuQGx6gECDAA/9MbcT9dpuQAAAABJRU5ErkJggg==
edittrash22:act:actions:22x22:data:iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAR6SURBVHjaYvz//z8DMmBkZATTPOFHBYAyAQz//8cD1Tj8//ef4R9Q7f+//xjAev79P/Dv3/+NQM6Cv9tdP4D0IJsFEECM2AzmiTjqABRez8TGzs0jKftOVFLwk6g46x9+TgYGfi4GBnZGBo4vbz5xPbn3QujixRdfP3z8kfh/l/sGZLMAAgjDYN7IYyBD94urqjxlkxD7BHQogwQ/A5soLwMXGzMDMysjAxszI8M/TjaGP+KCDD+4/v3iXLHskujZy28d/+91PwAzByCAmBjQANDQ+UpaKm+4pMQ+gfgS3Ax8UrwMwhysDJwsQEPBav4xMP389Yft06fffD//MzEnRmh/FBFgnY9sDkAAYRisr8CjEOsu9gvEFuJk4BXgYOAG++k/GDFAmXASGO5M/1hY/vPxsMojmwMQQBgG83OxMMjwQ1wmwM7ABRP/x4AbiPGwMP/7z/QHWQwggDAMfv3519tIDQa+LAsGISZGBmxBhQJs5FjZ7z768ePBsx+/kcUBAogFXeP33/9+PWFg2JxpyGAVZ8DAt/s2w6/rbxn+vP7B8O/VF4Z/wDBnEudhYLKQYWUVB/qnecP714uPfPoMtJEb2RyAAMIw+P/f/wzARPn24S+GzUZsDK7eagxc3gwMHEB/sn4DEm8+M/w9++D3j7pVH14fvvXtx59/2L0CEECYBiMpAPrtx3cgfg1kXH3PwHDl/l+Gq/e/Mlx98IPh/rMfqBrRIgEggDDCEJSWMIRgGv9DUwcWNeguBgggzMj59x+rwf+hvvkP4zD8x2swQABhBMU/VAWs//8y8P7/zcDF+OsvM8ufbwzs/74ycP4HYqa/wCBnBUYH829sBgMEEAs2HzEzMLCJsTE4AGkFWOJkBLqQCYiZGf8xsAAxO+MPLmbmHyI/GJi/fWLgecLwF9VggADCCAo2JgY2AQYGX2AOUQCVc4xMIF+ALGQEFlBMDExMrAzMzCwMTIzMEC8x/uXiY/mkDFSFYhZAAGG4WJiHVZgVSH8GZuofQKU/gR79+wdkMBPQYGagwcwMrCzALMnJBKT/MnwFpps///4ys7J8YUY2ByCAMFPFnz8MIkDqy6ffkGBhgriaiYkRXKQygVwNLN6YgRIsrKwMwnycDOGy1xnEuVGDAiCAMFz89etPhhcvPjIYActKkNJPf4GG/oUZDjEUFCRKQv8ZNAQ+MZgKvWCwM3NiuHD7Koo5AAGEYfDZG58Yrt17z/ATGAYCAjwM/Pwc4MJdEYhtxNgZPmmwM4gyf2X4/oOVgZ1diIGfT5fh+bv/DKeOPUcxByCAMIPi7/8F6ZPuMFy694nh06evDM+ff2R4+/Yrw5+PPxi4//5mkAV6mZeXm0FMVBhoKC/DtYc/GOxSdoF0LkA2BiCAsFZNDOYb+oEBXOBgIsTgYynG4GgkwqAszcPABqxCWFhYGB6/+sGw/+xrhtV7HjPs3PkQpG0Cw63oQmSzAAKIEVdlymC6TgGYzvKBPnAAZkcDaJpjgNP//18AZnNQVTQRaOgD9HIGIMAApp2w+uVu5nIAAAAASUVORK5CYII=
build22:app:apps:22x22:data:iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAGCUlEQVR42mL8v44BN/jDoM7AyV7MwMPpuXLTh/BFBxmObW1mYPj7kSHqz28GmQcvGLr+/2Jg+PmVgeHfTwYGzr8MDOuvMDBU7WNgAAggFgzD/gPxPwZJBkaGAgYZrXgGTUtxBuZvDMoX1jUwM/x0Y/jFEMWoYDafkVuYje/Adrn33xkKgTp+oxsDEECoBv9lEAKSUQyiaiUMGp7yDGLSDAyMn4FCXxkM7NUcWn9fm8kgZRnHZBLBxsb0kUGM7Wf2t3WHBP98/5MNVPQB2SiAAIIZzAl0ZQQDv1wug3qkIYOMIQMDE9B/DK8hjvnwiIH560dWHRX2tL8y5gzMTEA/M7xhYFZRZJDz/h71ePMZhXevfkcDffkAZjBAADFBXWrJIOM+j8FxpSGDnC/QUGawIMO3VwwMl3Yz/D93iIFRRIqBQVSU4deReQy/Hh4Fyv8Ayn9lYJUUYpBxUrMSFGTd8fc3gx4j1GCAAGKC0vv+vr++HxQrQL8DHfmegeH6egaGU8sYGL5/YGBU0WNgEJNiYOTjZ2CX4GP4eXw3w9cTZ4GRC4yxr58Z2PhZGeRsxdSFJVi2/f3L4AgyECCAQEHRxsDCcprx7aMl/69OsmcUUmdiuLsKGInAoBCRYWAQEGFgYOdgYGADYg5uBiZhVgYeIVGGj1efMLx78JxBSF8CmCy+MbAy/mL495tB4sJzBjWgmYcAAogFaMNfRl7pdUxK5gwM7y79ZniwjYlBSJyBgR8YcVy8DAys7BCD2TmBMQHks/xgYASKCdiJMrw9dY/h1bH7DAIyLAwPDr5/VbH6T+2+hwwrolQY/gIEEHNtGMP+py+/v+QSV/RkNotkYfj5kuHf5zcMjEBXMXDwAA3jBloApNmACQaYeBlAwc/OxcDAx8vApS7P8OHGO4YX+x8zvHj57x4TE+O9JFUGmQhFhvcAAcRcHw6M+49/z3x/evMGx8+HdiyGljx/P39i+PPqNQOzjBzQUJDBAsCgV2T4/wsY3tysDAw8PAzfn35keL37CjDEvjJIWEsxyGpyimsy/3B+9/Sv3sJbDLcBAgBZAKb/AfysAADh6wAA/P0AAA4DAJcWIBRoASkxAPve3QD7+gEACj48AP/7BgD3zNMA/fDgAAcxMQDw0eYA/PT6ABEwHQAJFgUA8crdAOC54eqrxvejpdoArOH0ANYCiPHXClaG//8hGY6R4X8/Cxd7wY/vTAwsoiIMv56/ZvjFzMvA+P0Tw99PXxl+fgcqEtRm4LM0ZuDVE2X4cvUGw7sdZxhuH3n1Jm/v/6BrnxkuwzIKQACx/P2PyHz///9nYhIRY2D/+5/h56vPDP8ZWRh+3H/B8Pvbf4a/f4DxqOLAIOzixvD3x0uG+zO3MTB9eMogoc3CcOEk899rn//cQM59AAHE8pcBKVcDnf4fGPPMXBwMXEAL/v/9x8Ct/RdoMAfD7w9fGP58f8zwed8Mhl+ffzCIyLEy8BoBUw83M8O/f1+Q8wQYAAQQy59fzAhz//4DJlJgugVFENBQRkZGIP7PwM4iyMAOKsJ+vQPnH0hu/QfEwADkBAYgAzNGWQYQQCzfX35CGPyP4Tz3tUf/Wa2MGBn4mCCaGUGhD0y/QEsYgP4DRwY4UoByLEAxLlYGZmYmDnSDAQKI5d+vfwgeI8Psvpl3/sW//DlVItKVnYEfmCmA2YnhPzAdMzOBilOIwUxAA5mB+NU3hhfrbzM8e/rzJAPCL2AAEEAsqFwGhrVXGeY6Kzx+9/HllnkqicECzDIqEAkuoMGMrJCgfP2B4e2umwxn1l2/u+b0l3lrnjNsAEp8RDYHIIAwCnoedrDo+juXXr351b92mWpCrAyHrjXE0Hf3GT4evMRwfdOlh8sOvFu96inDwpe/GR4CdXxGNwcggFiw1Uig4GTmYDh87forj3ft05ebJv3UZf73keHS8m2f1x1/u3DZfYaVj34xXATXAJAAwgAAAcSCq7oDhdB/Voar955/C/jUMWXu9XcM71fdZZh29hPDBXApTwAABBALPkmQ4awsDPdW3WdwX3aXQRDotHfY6jdsACDAACX/EgxHZ1YuAAAAAElFTkSuQmCC
quickbuild22:app:apps:22x22:data:iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAGr0lEQVR42mL8v44BN/jDoM7AyV7MwMPpuXLTh/BFBxmObW1mYPj7kSHqz28GGXZehn6Gfwxhf38wyP35yfAXKMb4l5Hhz/9/DMsBAogFw7D/QPyPQZKBkaGAQUYrnkHTUpyB+RuD8oV1DcwMP90YfjFEMSqYzWfkFmZ7d2K7saASawiTPg8Tyz9GBsZvfxl+H/344f9/hk0AAYRq8F8GISAZxSCqVsKg4SnPICbNwMD4GSj0lcHAXs2h9fe1mQxSlnFMJhFsbEwfGQTeXA1jkPrEwKgiyMAM8uCNjwx/fzOsYWBiuAMQQDCDOYGujGDgl8tlUI80ZJAxZGBg+goUfg3EvxkYPjxiYP76kVVHhT3tr4w5AzPTX6Apz4FSbxkYpPjALvr/5z/Dj/Of/v3/yzBftJDhP0AAsUBdaskg6z6PwbiBgYEFqInhOViQ4dsrBoY7Bxn+v3nMwCilBAwlRoZfR+YxMJu7MrAyvmf4z/GPgYmPDagWGLCPvjL8fP775LxtDMdARgIEEMzF+/6+v76f+e9HRwYWXqBL3gMNXM/A8PI80C/cQK/qMTDw8DEw/vrGwP4PGDDHdzP84eJg4NDnhOj+94/h+9WvDP++MGnJCP0Lv1vFcAQggEAGtzGwsJxmfPtoyf+rk+wZhdSZGO6uAkYiMChEZBgYBEQYGNg5GBjYgJiDm4FJmJWBhV2Y4dvDhwxcshxg1/7/85fh37d/DIxCzPzmxkwT/n/+8xgggFj+/mX4y8grvY5JyZyB4d2l3wwPtjExCIkzMPADI44L6HpWdojB7EDXcQL5LD8YWL99ZOBme8vw+xozwz8mAQYmfhYGPh8RBkZmRgbWvR8l3u75vBcggJiAqav2yaPnmb9///zLYJPDyqBgzPDv1y+oKzkhLgUZysIPtEgQiHkYGCV0GP7KlTH8+hbL8G7bD4Y/T34wMLEzMvx9+5vh3Ymv7xm/MUwBCCAWRkYGhh+/fs14dnLjO/GvdyZxmNuK/7v8m+HP0xcMbHqSQFcCDeUAupRRluE/80cGRi4WoCHKDCzcigyfgeoYQNIyQF99/cvwbu9Hhnf3//1bdI5BESCAwJHHAkyEQPeu+nDtqqPYt5cZzJqGDP8+f2H4euE6A5edDcP/z78Zvp9ZyfD3wwMGdkNDhg8XrzL8+fKTgUvInIFT+ScDI9Dib5e/M7w89/Nd4wmGiLc/GM4DBBDjrxWsDMCcAs5wwGjoZ+FiL/jxnYmBRVSE4dfz1wy/mHkZGL9/Yvj7CZicvgMVCWoz8FkaMzCJKDN83zaBQdgGmAg5WBhe7vrM8Obyz2dAg+7/+cWwCyCAWP7+R2S+////MzGJiDGw//3P8PPVZ4b/jCwMP+6/YPj97T+wIADGo4oDg7CLG8PfHy8ZXq9dwsDN8pnh611WBi4pRgZRc04GAQ12qbvrP0v9/fa/EyCAgNkBKVcDnf4fGPPMwDTKBbTg/99/DNzawPz/jYPh94cvDH++P2b4vG8Gw6/PPxj4hYEu/cPP8Ob8fwYZnp8MLMBk+PbiD4Yf7/+3Gy9k2AwQQCx/fjEjzP37j5WBB5huuVmBGQ+YLoExy8j4n4GdRZCB/ScwXf96BwovaLnyj+HLBz4GjjdHGFhYmRg+XfvJ8O3Grxv8HAztIGmAAGL5/vITwuB/DOe5rz36z2plxMjAxwTWzMAICn1QqmCEZPf/EJ+BFD88Z8wgyb4bGP5cDG9Ofv+67TpDQf5+BlCpxQAQQCz/fv1DBAUjw+y+mXf+xb/8OVUi0pWdgR+Ylv4Bk9R/HgZgyQMqTiEGMwEtAWYG7neHGdh5GIH56hvDkZeaJyvOvDkEKbgYGAACiAnsNRgGgrVXGeY+ufA48uaELR/+PgGaxKQCNEQCmDGAGYRXmIGBT5SB4TsLw5stHxn+vLz678eb/8AgkX8369zX4N//wcHKCiIAAogJvZznYQcXTevvXHrld61/7ZMfl18CBYCGMwKz+DsWho/rrzCcKNv28M4X6xvMf38zvX/BzdB+Xrzj/Y+/P/58ecEPcyJAALFgq5FAwcnMwXD42vVXHu/apy83Tfqpy/zvI8Ol5ds+rzv+duGy+wwrV6vuS//x4adyz1GGpnkXTs0BahMF1wjgApyBASCAWHBVdyBr/7MyXL33/FvAp44pc6+/Y3i/6i7DtLOfGC4Apd4IPd2XceTR/5vzLjC0AvmgmucZpBCHAIAAYsFTlYINZ2VhuLfqPoP7srsMgsAQfwdykZYIg96n7//F331jmAxV9hZdL0CAAQAuWm4F5cMEnAAAAABJRU5ErkJggg==
acthelp22:act:actions:22x22:data:iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAQCSURBVHjaYvz//z8DLQBAALGACEZGRgyJUwwMAv8YGBKA2B+IDf5B+Ax/GRg+AOkLQHoj0EkLPIF8dL0gxwIEECOYQDMYaGgBUFM9M9AwPnl5BgE9PQYmfX2w3N+HDxleX7zI8OrSJYZvQEOBFjT6MzBMQDcYIIAY0IMCaOj8M0C5R1pa//+sWfP//4sX///cuvX/44YN/z8A8fczZ8Bif3fv/n/Lze3/FqDatUA96AYDBBCKwTBD3/v4/P9/4cL/P0eO/H+/YMH/r+fP/0cGv58+/f/r1CmwmrcNDf/XA/WsQDIcZCZAAMENBnn/NMhQZ+f//3fs+P9n7dr/nzZv/o8T/P79///x42C1bwoL/68C6l0CNANmMEAAMYEYJ4FhCQpTcVlZBoGYGAaG588Zvj1+zMDr4wNxws+fDAwHDzIwbNvGwHDrFjTagfEuLQ1WKwyMAy0DA1DE1gOdLQCSBgggsMFAQxNAESVpbw9WCML/BQURgbZ7NwPDsWMMDMBI+71kCcO3Bw8g4kCHwNRrmJoycEBTEkgKIIDAyQ2UpHjZ2BhYQIaBFAIBu4QERPM3YNwfOsTA8OMHmPv60ycGKQUFSFh++MDwa+1ahj937jD8+/iRQRIodgNoFpCaABBAMIMNBPj5GRiePYM7kh3EvnuXgeHNGwgGgqefPzNwd3bC1fxesIDh19mzcL4UEF8DmgViAwQQ2GBg2Agws7OjGAwGSPwPMjIMYitXMrAKgIOQ4d+FCwy/GhtRMwbULBAbIIBgLmZgALqG4elTrNnz61+g8mnT4IaCXPqzsBAcFOjgH5QGCCCYwR/+fvokwPD9O6ZCYNL5bGvLIGFgAMl5GzYw/ElMZGDG4gAmqFkgNkAAMUGD4sJboAH/fv1iAKZPMP4LZP8B4n8g/r9/CN0TJzKwAils+BHE4AsgZQABBAvjjS8ZGBw0WVjg+pFdJHn5MgPD5s0Q8SNHIGkYC7j75w/I4I0gNkAAwYJiwRdg4r7HxiagxMmJoeEtUMNnYAbhASZHETk5BgZg0kIH54DB+OHPnw+gEg/EBwggsMHewHABWtN47cePfiFhYQYBDg4UTT/DwhgUWlogHD4+BobJk1HkXwPT+LH370EObCwDmlUCFAMIICaYJKjo+/nv34IDwCT2gRUYYqAUAMW8yKYAXY8s9xqodiVQz3eg3jKk4hMggDDK4+XAUoqZhSVBV0mJQQOaw8DA3R1C79yJ8D4wax+7d4/h+58/IEMTkUs3gADCWtAvBpZSoAKFi4tLQFZKikEOmDlgGQAE7jx5wnAH6Mr3376BwrSxDEtBDxBAWA0GgXlIVdNfaNX0F5pOQUnqH7RqKsVRNQEEECOtKlOAAAMANe/6QtKBq0EAAAAASUVORK5CYII=
actstop22:act:actions:22:data:iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAANgSURBVHjaYvz//z8DLQBAALGACEZGRhTB0wwMAkDr9rMzMBiA+CCr/0ExjP0LiD8zMFwAsh19GBg+IOsHORYggBjBBJLBMEMFdXUNFLu78brqUmkpw5PLly/8BRoeiGQ4yEyAAEIxGG6opqaB8urVDIz8/HgN/v/xI8PZ0FCGR9evg10eCjUcZCZAAMENhhuqqmqgPGsWAyMfH1Fh+f/TJ4ZTaWkMD27fBhseBTQcZCZAAIENPsPICDFUUdFAubOTgZGHh4GBlZWBQVubgeHqVQaG379RTUOT+//lC8Px8nKG+/fvg4Ml7v//DwABxASNnP2CMjIGysXFDIxARQzv3zMwGBszMEhKQmgQ/8ULCMYiB9JjCdQrBzQD6Or9IDMBAghsMBsw9hU9PBgYgWHG8Pw5A4OMDAODoCDEdSDa1RViIAiD2MhyILVAPf8uXWIwBVrGB01JAAEESW4g4u1bBgYODogGYMSBvWtpCeGLijIwREQg2FDwd906ht91dQx/7txh+P/zJ1iMGSoHEEBgg0HpkuHNG1CCRoRjTw8DQ1YWA4OzM4QvJYUSzL8XLGD4kZiIEZn/oDRAALHAMgDYxeiRVFPDwPDtGwODry9RhiIbDBBACBe/fg3MSp9RVYGSnIoKhmZmAwMGRgEBhv8fPmAmPygNEEDgxAxMw///MjP//8/KisAiIv//X7z4Hxf4e/78/28CAv+B/kHBq8D54z8DQACBDT4F5PyB4r8gGqjhP1AjMvg3fz4Yo4gB1fwCqgWWG3C8EmowQACBDT4K5PxjYoLj/wsWoDpv4UKEHJCNAoBqkfUuhBoMEEBgg7cyMJw/D/K+oCAEKyj8/3/5MkTj8uUIcRgGiYEASA1ILVR8O9CMLqBZIDMBAgicpbcAszQox8hwcxsYiYlBAh9UAIWEMDDMnYu9kEhOZmBYs4aBAZSpgGDHq1cMl79+vQCMPMcyYJYGCCB4IbQOWAiBDJcTEjIwVVAgqVDf8eABw+V378CGlkMLIYAAQik2gTEqAIy8/QoSEgYWoEKGGEOBBdHlFy/ghsJSGkAAYRT0S6EuV5STM7A2M8Nv6KlTDJcfPUIxFGYwQABhGAwCC6CGCwCDhZWNDV4tIVdN33/9YniJ5H30qgkggBhpVZkCBBgAsE0a3ur7zL0AAAAASUVORK5CYII=
Added lib/Icons/InstallJammer.ico.

cannot compute difference between binary files

Added lib/Icons/InstallJammer.tkico.


















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
## $Id: tkIcons.installbase,v 1.7 2003/10/08 01:41:17 damonc Exp $

################################################################################
# Copyright (c) 2002, Damon Courtney <damon@unreality.com>
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of TclHome Software nor the names of its
#       contributors may be used to endorse or promote products derived from
#       this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
################################################################################

## Icon links to other icons.
filedocument16:crystal:mime:16:icon:mimeunknown16
preferences16:crystal:actions:16:icon:acttooloptions16
startpage16:crystal:actions:16:icon:actcontents16
about16:crystal:actions:16:icon:actinfo16
displayscreen16:crystal:apps:16:icon:appdisplay16
insertaction16:crystal:apps:16:icon:appwinprops16

## A little check mark.
check:common:photo:16:data:R0lGODlhEAAQABEAACH5BAEAAAIALAAAAAAQABAAgf////8AAAAAAAAAAAIYlI+py+3fAjRBwmpVxlHy/jnhk03miUIFADs=

## Checkbox and radiobutton for option trees.
check-off:prefs:photo:16:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CJYyPacDtfZ5kEaiKb6DLar55FwgqpGiKZXJqYTaq01PNkIvnRwEAOw==
check-on:prefs:photo:16:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CK4yPacDtfZ5kEaiKlaXLJsoFYLV5Ynl6IehkZ2e+XfSZoWZPD6nf1w9UFAAAOw==
radio-off:prefs:photo:16:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CI4yPqcsGD1qANCqIcHrXHr6AjreRYpmRKcqm5vlVcDlLtl0AADs=
radio-on:prefs:photo:16:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CJoyPqcsGD1qANCqIcHrXHu54YBiC42RR5Ce2m8d2sPZWsHxL+l4AADs=

## Checkbox and radiobutton for Windows XP.
check-off:xpprefs:photo:16:data:R0lGODlhEAAQADMAACH5BAEAAAwALAAAAAAQABAAgxhRhP/7/+/v7+/r5/fz9+fj3vf3997f1t7f3vfz7+fn5//79wAAAAAAAAAAAAAAAARWEMhJqzwYI1SKGoMgXNnWfaGQkIfpgWJCkC4aEzPQcm8qGwZJDabCGRbCE/F3DEiUPuMi4AT0bsBpgCGxFQnNLRewBIcZaEkUrEWnAdize/yVzy14SgQAOw==
check-on:xpprefs:photo:16:data:R0lGODlhEAAQADMAACH5BAEAAAsALAAAAAAQABAAgxhRhP/7/yGiIefj3u/v7/fz7+/r5+fn5//79/fz9/f39wAAAAAAAAAAAAAAAAAAAAReEMhJqxw4n2MMIUVxZcPWfWEyYqYHCokKaJxbCLAytiguKIjLQXB6+RAByQbXOwaSAI7v5nxKOr4s8rm4frKCbWDRBaCo4eeYLAEVYmkuuZxSANVzNuCduMvzFoEUEQA7
radio-off:xpprefs:photo:16:data:R0lGODlhEAAQAEQAACH5BAEAABsALAAAAAAQABAAhP/7//f395Sire/v7/fz9//79ylVhCFVhFJtjN7j5/fz73uatcbT3nuKnISevZSerefn5+fn797n74Setb3HznOSrXuWrdbf597j773L1s7T1gAAAAAAAAAAAAAAAAAAAAV/4CZuyYMYBvIk4wgIh0VBUbYcAuA2lTYMCgIhcFk0dBtBBfILBgIFQGAhIB18wCEUoMMcEgJLUxtFbhwmSvZZbjFOEOfWLAqgImRuq57KsPV7G28PC3OBIg4CCQcXgIESX0mFhxsAE1WVDQsYjxNHLjAODE8MDjh0ImAnKYotIQA7
radio-on:xpprefs:photo:16:data:R0lGODlhEAAQAFUAACH5BAEAADcALAAAAAAQABAAhf/7//f395Sire/v797j5ylVhFJtjCFVhMbnxnuatffz93uKnErLSsbT3oSevffz7zGuKZSerUK+OVLXUufn55TfjITThL3Hzt7n7+fn7//7997j773L1s7T1tbf54SetTm+OTm2MVrLUkrPSimqISGiGDmqOTmmMVrbUnPDc2PPWnvHe3uWrXOSrVrbWnPbcymqKVrHUs7nxkquQlq+UlrrWkLDQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa1wJvwRogYCgVDhDAcAgQH1oWS4SQOAoBz0eoMBg+FIuBJLLQ3QYvyDQcCGkAgISAevANERSWyILQbBwQCLF8yLygTDBIxCEIORhdgFSg1LiMSECtCDUcUYSoTLoogECZCAUgZYyIMIww2ISQnqEkcbxYgEhIhMCUpnEoJcAg0EBAkJTOONw4CBAceAAAIKyYnKcwYgmnDTU0AH3U3AAsJG983GB9nTlAODW8NDlhoTYNHSc9NQQA7

## Plus and minus images for trees.
tree-plus:common:tree:9:data:iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAKFJREFUGFdj3HDo8olrjxgwgIWWHEPFjK3/sQGgOEjuz5/ff/+CEFAzkP3nz6/v3z5D5b5//wpGX4By3759+fjh9dOHt6ByX79+RLPu/u1LULlPn959+PDm7dvnQBWvXj5+/ODm7WtnoHJPHt68c+P8jcsngXLXLh67dObA+RO7oXKXzuw/tm/doR0rDu5YDkQHti87vGsVSA7oPyCFiYDiAIWxmffzwx+EAAAAAElFTkSuQmCC
tree-minus:common:tree:9:data:iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAABGdBTUEAALGPC/xhBQAAAKJJREFUGFdj3HDo8olrjxgwgIWWHEPFjK3/sQGgOEjuz5/ff/9CEZD958+v798+Q+W+f/8KRl+A6Nu3Lx8/vH768BZU7uvXj2jW3b99CSr36dO7Dx/evH37/M3rZ69ePn784Obta2egck8e3rxz4/yNyyevXzp+7eKxS2cOnD+xGyp36cz+Y/vWHdqx4uCO5UB0YPuyw7tWgeSA/gNSmAgoDgATQqT7EP+oXAAAAABJRU5ErkJggg==
Added lib/Icons/logo.png.

cannot compute difference between binary files

Added lib/Tktags/pkgIndex.tcl.


>
1
package ifneeded Tktags 1.0 [list source [file join $dir tktags.tcl]]
Added lib/Tktags/tktags.tcl.
























































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
##
## TkTags - An interface for associating symbolic names with Tk widgets.
##
## tag add       tagName <widget ?menuItem?> ??widget ?menuItem?? ... ?
## tag addmenu   tagName menu menuItem ?menuItem ...?
## tag addtag    tagName searchSpec ?arg arg ... ?
##
## tag addtag    tagName ?recursive? ?class widgetClass? ?type menuItemType?
##                       ?children widgetName? ?menuentries menuName? ?arg ... ?
##
## tag cget      widgetOrTagName option
## tag configure widgetOrTagName ?option? ?value? ?option value ... ?
## tag delete    tagName ?tagName ... ?
## tag names     ?widget ?menuItem??
## tag remove    tagName <widget ?menuItem?> ??widget ?menuItem?? ... ?
## tag widgets   tagName ?tagName ... ?
##

package require Tk
package provide "Tktags" "1.0"

namespace eval ::TkTags {
    variable tags
    variable widgets
}

proc ::TkTags::Lempty {list} {
    if {[catch {llength $list} len]} { return 0 }
    return [expr $len == 0]
}

proc ::TkTags::Lremove {list args} {
    foreach elem $args {
        set x [lsearch -exact $list $elem]
        if {$x < 0} { continue }
        set list [lreplace $list $x $x]
    }
    return $list
}

proc ::TkTags::OptionErrorString {word type value list} {
    set msg "$word $type \"$value\": must be "
    set last [lindex $list end]
    set list [lrange $list 0 end-1]
    append msg [join $list ", "] ", or $last"
    return $msg
}

proc ::TkTags::add {tagName args} {
    variable tags
    variable widgets
    foreach arg $args {
        if {![info exists tags($tagName)]
            || [lsearch -exact $tags($tagName) $arg] < 0} {
            lappend tags($tagName) $arg
        }

        if {![info exists widgets($arg)]
            || [lsearch -exact $widgets($arg) $tagName] < 0} {
            lappend widgets($arg)  $tagName
        }
    }
}

proc ::TkTags::addmenu {tagName menu args} {
    set list [list]
    foreach index $args {
        lappend list [list $menu $index]
    }
    eval add $tagName $list
}

proc ::TkTags::addtag {tagName args} {
    set recursive 0
    set pass      [list]
    set widgets   [list]
    for {set i 0} {$i < [llength $args]} {incr i} {
        set arg [lindex $args $i]

        switch -glob -- $arg {
            "cl*" { ## class
                set class [lindex $args [incr i]]
                lappend classes $class
                lappend pass class $class
            }

            "r*" { ## recursive
                set recursive 1
                lappend pass recursive
            }

            "t*" { ## type
                set type [lindex $args [incr i]]
                lappend types $type
                lappend pass type $type
            }

            default {
                lappend search $arg
            }
        }
    }

    set args $search

    for {set i 0} {$i < [llength $args]} {incr i} {
        set arg [lindex $args $i]

        switch -glob -- $arg {
            "ch*" { ## children
                set widget [lindex $args [incr i]]
                if {![winfo exists $widget]} { continue }
                foreach widget [winfo children $widget] {
                    if {[string match "*.#*" $widget]} { continue }
                    set class [winfo class $widget]
                    if {![info exists classes]
                        || [lsearch -exact $classes $class] > -1} {
                        lappend widgets $widget
                    }
                    if {$recursive} {
                        eval lappend widgets \
                            [eval addtag $tagName $pass children $widget]
                    }
                }
            }

            "m*" { ## menuentries
                set widget [lindex $args [incr i]]
                if {![winfo exists $widget]} { continue }
                if {[string match "*.#*" $widget]} { continue }
                if {![string equal [winfo class $widget] "Menu"]} {
                    return -code error "$widget is not a menu"
                }
                for {set j 0} {1} {incr j} {
                    if {[$widget index $j] != $j} { break }
                    set type [$widget type $j]
                    if {![info exists types]
                        || [lsearch -exact $types $type] > -1} {
                        lappend widgets [list $widget $j]
                    }

                    if {$type == "cascade" && $recursive} {
                        set menu [$widget entrycget $j -menu]
                        eval lappend widgets \
                            [eval addtag $tagName $pass menuentries $menu]
                    }
                }
            }

            default {
                if {[winfo exists $arg]} { lappend widgets $arg }
            }
        }
    }
    eval add $tagName $widgets
    return $widgets
}

proc ::TkTags::cget {tagName option} {
    variable tags
    if {![info exists tags($tagName)]} {
        set widget [lindex $tagName 0]
        set index  [lindex $tagName 1]
        if {![winfo exists $widget]} { return }
    } else {
        if {[llength $tags($tagName)] > 1} { return }
        set item   [lindex $tags($tagName) 0]
        set widget [lindex $item 0]
        set index  [lindex $item 1]
    }

    if {[Lempty $index]} { return [$widget cget $option] }

    if {[winfo class $widget] == "Menu"} {
        return [$widget entrycget $index $option]
    } else {
        return [$widget itemcget $index $option]
    }
}

proc ::TkTags::configure {tagName args} {
    variable tags
    if {![info exists tags($tagName)]} {
        set widget [lindex $tagName 0]
        if {![winfo exists $widget]} { return }
        set items [list $tagName]
    } else {
        set items $tags($tagName)
    }

    if {[llength $args] < 2} {
        if {[llength $items] > 1} { return }
        set item   [lindex $items 0]
        set widget [lindex $item 0]
        set index  [lindex $item 1]
        if {![winfo exists $widget]} { return }

        if {[Lempty $index]} { return [eval $widget configure $args] }

        if {[winfo class $widget] == "Menu"} {
            return [eval $widget entryconfigure $index $args]
        } else {
            return [eval $widget itemconfigure $index $args]
        }
    }

    foreach {opt val} $args {
        foreach item $items {
            set widget [lindex $item 0]
            set index  [lindex $item 1]
            if {![winfo exists $widget]} { continue }
            if {![Lempty $index]} {
                if {[winfo class $widget] == "Menu"} {
                    catch { $widget entryconfigure $index $opt $val }
                } else {
                    catch { $widget itemconfigure $index $opt $val }
                }
            } else {
                catch { $widget configure $opt $val }
            }
        }
    }
}

proc ::TkTags::delete {args} {
    variable tags
    variable widgets

    foreach tagName $args {
        if {![info exists tags($tagName)]} { continue }
        foreach widget $tags($tagName) {
            if {![info exists widgets($widget)]} { continue }
            set widgets($widget) [Lremove $widgets($widget) $tagName]
            if {[Lempty $widgets($widget)]} { unset widgets($widget) }
        }
        unset tags($tagName)
    }
}

proc ::TkTags::names {{widget ""}} {
    variable tags
    variable widgets
    if {[Lempty $widget]} { return [lsort [array names tags]] }
    if {![info exists widgets($widget)]} { return }
    return $widgets($widget)
}

proc ::TkTags::remove {tagName args} {
    variable tags
    variable widgets

    if {![info exists tags($tagName)]} { return }

    set tags($tagName) [eval Lremove [list $tags($tagName)] $args]
    if {[Lempty $tags($tagName)]} { unset tags($tagName) }

    foreach widget $args {
        if {![info exists widgets($widget)]} { continue }
        set widgets($widget) [Lremove $widgets($widget) $tagName]
        if {[Lempty $widgets($widget)]} { unset widgets($widget) }
    }
}

proc ::TkTags::widgets {args} {
    variable tags
    set widgets [list]
    foreach tagName $args {
        if {![info exists tags($tagName)]} { continue }
        foreach widget $tags($tagName) {
            if {[lsearch -exact $widgets $widget] > -1} { continue }
            lappend widgets $widget
        }
    }
    return $widgets
}

proc ::tag {args} {
    if {[::TkTags::Lempty $args]} {
	set msg "wrong # args: should be tag option arg ?arg ...?"
	return -code error $msg
    }

    set cmd [lindex $args 0]
    set lst [list add addmenu addtag cget configure delete names remove widgets]
    set command [info commands ::TkTags::$cmd]
    if {[::TkTags::Lempty $command]} {
	set cmds [info commands ::TkTags::$cmd*]
	if {[::TkTags::Lempty $cmds]} {
	    set msg [::TkTags::OptionErrorString bad option $cmd $lst]
	    return -code error $msg
	}
	if {[llength $cmds] > 1} {
	    set msg [::TkTags::OptionErrorString ambiguous option $cmd $lst]
	    return -code error $msg
	}
	set command [lindex $cmds 0]
    }

    return [eval $command [lrange $args 1 end]]
}
Added lib/actions.tcl.












































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::InstallJammer::LoadActions {} {
    global conf
    global preferences

    if {[string length $preferences(CustomActionDir)]} {
        set dir $preferences(CustomActionDir)
        lappend dirs $dir
        eval lappend dirs [glob -nocomplain -type d -dir $dir *]

    }

    set dir [file join $conf(lib) Actions]
    eval lappend dirs [glob -nocomplain -type d -dir $dir *]

    foreach dir $dirs {
        if {$dir eq $preferences(CustomActionDir)} {
            set group "Custom Actions"
        } else {
            set group [file tail $dir]
        }
        set name [::InstallJammer::StringToTitle $group]
        foreach file [glob -nocomplain -directory $dir *.action] {
            set ::InstallJammer::loadactions::group  $name
            set ::InstallJammer::loadactions::action ""

            catch {
                namespace eval ::InstallJammer::loadactions [read_file $file]
            }
        }
    }
}

proc ::InstallJammer::GetActions {} {
    variable actions
    set list [list]
    foreach action [lsort [array names actions]] {
        lappend list $actions($action)
    }
    return $list
}

proc ::InstallJammer::GetActionNames {} {
    set names [list]
    foreach action [::InstallJammer::GetActions] {
        lappend names [$action action]
    }
    return $names
}

proc ::InstallJammer::ActionList {} {
    variable ::InstallJammer::aliasmap

    foreach id [array names aliasmap] {
        if {[$id is action actiongroup]} {
            lappend list $aliasmap($id)
        }
    }

    return [lsort -unique $list]
}

proc ::InstallJammer::GetActionList { setup {activeOnly 0} } {
    set actions [list]
    foreach id [GetActionComponentList $setup $activeOnly] {
        set action [$id component]
        eval lappend actions $action [[$id object] includes]
    }

    return [lsort -unique $actions]
}

proc ::InstallJammer::GetActionComponentList { setup {activeOnly 0} } {
    set list [list]
    foreach id [GetComponentList $setup $activeOnly] {
        if {[$id is action]} { lappend list $id }
    }
    return $list
}

proc ::InstallJammer::GetRequiredPackages { {activeOnly 0} } {
    set list [list]
    foreach id [GetActionComponentList "" $activeOnly] {
        eval lappend list [[$id object] requires]
    }

    return [lsort -unique $list]
}

proc ::InstallJammer::AddAction { setup action args } {
    global widg

    variable ::InstallJammer::actions

    if {![info exists actions($action)]} {
        ## If we're trying to add an action that doesn't exist,
        ## it's probably because we no longer support the action.

        ## We need to destroy the object that references this action.
        array set _args $args
        if {[info exists _args(-id)]} { $_args(-id) destroy }

        return
    }

    set obj    $actions($action)
    set pref   $widg($setup)
    set sel    [lindex [$pref selection get] end]
    set index  end
    set parent [::InstallJammer::Tree::GetActionParent $pref $sel]

    set data(-id)     ""
    set data(-title)  [$obj title]
    set data(-parent) $parent
    array set data $args

    set id     $data(-id)
    set parent [::InstallJammer::ID $data(-parent)]

    if {$parent eq ""} {
        ::InstallJammer::Error -message "You cannot add an action here."
        return
    }

    set new 0
    if {$id eq ""} {
        set new 1

        if {$sel ne ""} {
            if {[$sel is action]} { set index [$pref index $sel] }
        }

	set id  [::InstallJammer::uuid]
        InstallComponent ::$id -parent $parent -index $index -setup $setup \
            -component $action -type action -title $data(-title)
    }

    $obj initialize $id

    if {$new} {
        set proc ::InstallJammer::actions::Insert.$action
        if {[::InstallJammer::CommandExists $proc]} { $proc $id }
    }

    if {[$pref exists $parent]} {
        $pref insert $index $parent $id \
            -text $data(-title) -data action -image [GetImage appwinprops16] \
            -createcommand [list ::InstallJammer::CreateActionFrame $id] \
            -fill [expr {$new ? "#0000FF" : "#000000"}]
    }

    Modified

    return $id
}

proc ::InstallJammer::CreateActionFrame { id } {
    global widg
    
    variable actions

    set setup  [$id setup]
    set action [$id component]

    if {$action eq "AddWidget"} {
        return [::InstallJammer::CreateAddWidgetActionFrame $id]
    }

    set obj  $actions($action)
    set pref $widg($setup)

    set frame [$pref getframe $id]

    if {[winfo exists $frame.sw]} { return }

    ScrolledWindow $frame.sw -scrollbar vertical
    pack $frame.sw -expand 1 -fill both

    set prop [PROPERTIES $frame.sw.p]
    $frame.sw setwidget $frame.sw.p

    $prop insert end root standard -text "Standard Properties" -open 1

    if {[llength [$obj properties 0]]} {
        $prop insert end root advanced -text "Advanced Properties" -open 0
    }

    $obj addproperties $prop $id

    if {[llength [$obj textfields]]} {
        $prop insert end root text -text "Text Properties"
        $obj addtextfields $prop text $id
    }
}

proc ::InstallJammer::CreateAddWidgetActionFrame { id } {
    global widg
    
    variable actions

    set setup  [$id setup]
    set action [$id component]

    set obj  $actions($action)
    set pref $widg($setup)

    set frame [$pref getframe $id]

    if {[winfo exists $frame.sw]} { return }

    ScrolledWindow $frame.sw -scrollbar vertical
    pack $frame.sw -expand 1 -fill both

    set prop [PROPERTIES $frame.sw.p]
    $frame.sw setwidget $frame.sw.p

    $prop insert end root standard -text "Standard Properties" -open 1
    $obj addproperties $prop $id -advanced 0

    set appearance {Background Foreground Height LabelJustify LabelSide
                    LabelWidth Type Width X Y}
    $prop insert end root appearance -text "Widget Properties" -open 0
    $obj addproperties $prop $id -properties $appearance -parentnode appearance

    $prop insert end root advanced -text "Advanced Properties" -open 0
    foreach property [$obj properties 0] {
        if {[lsearch -exact $appearance $property] > -1} { continue }
        $obj addproperties $prop $id -properties $property -parentnode advanced
    }

    $prop insert end root text -text "Text Properties"
    $obj addtextfields $prop text $id

    BUTTON $frame.preview -text "Preview Pane" -width 18 \
        -command [list ::InstallJammer::PreviewWindow $id]
    pack $frame.preview -side bottom -anchor se -pady 2

    ::InstallJammer::ConfigureAddWidgetFrame $id [$id get Type]
}

proc ::InstallJammer::ConfigureAddWidgetFrame { id {type ""} } {
    global widg
    
    variable actions

    set setup  [$id setup]
    set action [$id component]

    set obj  $actions($action)
    set pref $widg($setup)

    set frame [$pref getframe $id]
    set prop  $frame.sw.p

    if {![winfo exists $frame.sw]} { return }

    array set props {
        "button"         {Action}
        "browse entry"   {Action BrowseType FileTypes ValidateEntryOn
                          Value VirtualText}
        "checkbutton"    {Action Checked OffValue OnValue VirtualText}
        "combobox"       {Action Editable ValidateEntryOn Value Values
                          VirtualText}
        "entry"          {Action ValidateEntryOn Value VirtualText}
        "label"          {}
        "label frame"    {}
        "password entry" {Action ValidateEntryOn Value VirtualText}
        "radiobutton"    {Action Checked Value VirtualText}
        "text"           {Value VirtualText}
    }

    if {$type eq ""} { set type $::InstallJammer::active(Type) }
    set properties $props($type)

    if {![llength $properties]} {
        $prop itemconfigure advanced -state hidden
    } else {
        $prop itemconfigure advanced -state normal
        foreach node [$prop nodes advanced] {
            set type [$prop itemcget $node -data]
            if {[lsearch -exact $properties $type] < 0} {
                $prop itemconfigure $node -state hidden
            } else {
                $prop itemconfigure $node -state normal
            }
        }
    }
}

proc ::InstallJammer::AddActionGroup { setup args } {
    global widg

    set pref $widg($setup)

    array set data {
        -id     ""
        -edit   1
        -title  "New Action Group"
    }
    set data(-parent) "ActionGroups$setup"
    array set data $args

    set id     $data(-id)
    set parent $data(-parent)

    set new 0
    if {![string length $id]} {
        set new 1

	set id [::InstallJammer::uuid]
        InstallComponent ::$id -parent $parent \
            -setup $setup -type actiongroup -active 1
    }

    ::ActionGroupObject initialize $id

    if {$data(-edit)} {
        $pref open $data(-parent)
        set cmd [list ::InstallJammer::EditNewNode $pref]
    } else {
        set cmd [list $pref insert]
    }

    set open $new
    if {[info exists data(-open)]} { set open $data(-open) }

    eval $cmd [list end $parent $id -open $open \
        -text $data(-title) -data actiongroup \
        -image [GetImage appwindow_list16] \
        -createcommand [list ::InstallJammer::CreateActionGroupFrame $id]]

    set title [$pref itemcget $id -text]

    $id title $title

    Modified

    return $id
}

proc ::InstallJammer::CreateActionGroupFrame { id } {
    global widg
    
    variable actions

    set setup  [$id setup]
    set action [$id component]

    set pref $widg($setup)

    set frame [$pref getframe $id]

    if {[winfo exists $frame.sw]} { return }

    ScrolledWindow $frame.sw -scrollbar vertical
    pack $frame.sw -expand 1 -fill both

    set prop [PROPERTIES $frame.sw.p]
    $frame.sw setwidget $frame.sw.p

    set obj [$id object]

    $prop insert end root standard -text "Standard Properties" -open 1
    $obj addproperties $prop $id
}

proc ::InstallJammer::FindActionGroup { tree text } {
    foreach node [$tree nodes root] {
        set d [$tree itemcget $node -data]
        if {![string equal $d "actiongroup"]} { continue }
        set t [$tree itemcget $node -text]
        if {[string equal $t $text]} { return $node }
    }
}

proc ::InstallJammer::loadactions::Action { name {title ""} } {
    variable group
    variable action
    variable ::InstallJammer::actions

    if {[info exists actions($name)]} {
        return -code error "Action $name already exists"
    }

    if {$title eq ""} {
        set title [::InstallJammer::StringToTitle $name]
    }

    set action [::InstallJammer::Action ::#auto -title $title \
        -name $name -group $group]
}

proc ::InstallJammer::loadactions::Property { args } {
    variable action
    eval $action property $args
}

proc ::InstallJammer::loadactions::Text { args } {
    variable action
    lassign $args name pretty subst
    if {![string length $subst]}  { set subst 1 }
    if {![string length $pretty]} { set pretty $name }
    $action text $name $pretty $subst
}

proc ::InstallJammer::loadactions::Help { property text } {
    variable action
    $action help $property $text
}

proc ::InstallJammer::loadactions::Condition { name args } {
    variable action
    $action condition $action $name $args
}

proc ::InstallJammer::loadactions::Include { args } {
    variable action
    eval $action includes $args
}

proc ::InstallJammer::loadactions::Require { args } {
    variable action
    eval $action requires $args
}

proc ::InstallJammer::loadactions::Group { groupName } {
    variable action

    variable group [::InstallJammer::StringToTitle $groupName]

    if {$action ne ""} { $action group $group }
}
Added lib/build.tcl.




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::bgerror {err} {
    if {$::conf(building)} {
        BuildLog $::errorInfo -tags error
        BuildDone 1
    } else {
        ::InstallJammer::Message -icon error -message $::errorInfo
    }
}

proc BuildLog { text args } {
    global conf
    global widg

    array set _args {
        -tags       {}
        -logtofile  1
        -nonewline  0
    }
    array set _args $args

    set error [expr {[lsearch -exact $_args(-tags) error] > -1}]
    incr conf(buildErrors) $error
    incr conf(totalBuildErrors) $error

    Status [lindex [split $text \n] 0]

    set date "[clock format [clock seconds] -format "%D %r"]"

    set string "$date - $text"
    if {$conf(logBuild) && $_args(-logtofile)} {
	if {![info exists conf(logfp)]} {
            set logfile [::InstallJammer::GetBuildLogFile]
            if {![file exists [file dirname $logfile]]} {
                file mkdir [file dirname $logfile]
            }
	    set conf(logfp) [open $logfile a+]
            fconfigure $conf(logfp) -translation lf
	}
	puts  $conf(logfp) $string
	flush $conf(logfp)
    }

    if {[info exists widg(BuildLog)]} { 
        if {!$_args(-nonewline)} { append text \n }

        set auto [expr {[lindex [$widg(BuildLog) yview] 1] == 1}]

	$widg(BuildLog):cmd insert end "$date - " "" $text $_args(-tags)
        if {$auto} { $widg(BuildLog) see end }
        update idletasks
    } else {
	if {$error} {
            puts  stderr $string
            flush stderr
        } elseif {!$conf(silent) && ($conf(verbose) || $_args(-logtofile))} {
            puts  stdout $string
            flush stdout
        }
    }
} 

proc ::InstallJammer::ClearBuildLog {} {
    global widg

    if {[info exists widg(BuildLog)] && [winfo exists $widg(BuildLog)]} {
        $widg(BuildLog) clear
    }
}

proc ::InstallJammer::BuildOutput { line {errorInfo ""} } {
    global conf

    ::InstallJammer::CheckForBuildStop

    catch { lindex $line 0 } cmd

    if {$errorInfo ne ""} { set line $::errorInfo }

    switch -- $cmd {
        ":FILE" {
            BuildLog "Packing [lindex $line 1]..." -logtofile 0
            FileProgress 0
        }

        ":FILEPERCENT" {
            FileProgress [lindex $line 1]
        }

        ":PERCENT" {
            PlatformProgress [lindex $line 1]
        }

        ":ERROR" {
            BuildLog [lindex $line 1] -tags error
        }

        ":ECHO" {
            BuildLog [lindex $line 1]
        }

        ":DONE" {
            if {[threaded]} { ::InstallJammer::FinishBuild }
        }

        default {
            BuildLog $line -tags error
        }
    }
}

proc ::InstallJammer::ReadBuild { fp } {
    gets $fp line

    if {[string length $line]} {
        ::InstallJammer::BuildOutput $line
    }

    if {[eof $fp]} {
        catch { close $fp }
        ::InstallJammer::FinishBuild
    }
}

proc ::InstallJammer::FinishBuild { {errors 0} } {
    global conf
    global widg

    variable ::InstallJammer::solid

    ::InstallJammer::CheckForBuildStop 0

    set platform $conf(buildPlatform)
    set pretty   [PlatformText $platform]

    if {[::InstallJammer::IsRealPlatform $platform]} {
        set execdir [file dirname $conf(executable)]
        file delete -force [file join $execdir runtime]
    }

    if {$conf(buildStopped)} {
        BuildDone
        return
    }

    if {!$errors && [info exists solid]} {
        set tmp [::InstallJammer::BuildDir out.lzma]
        foreach methodName [lsort [array names solid]] {
            set method [lindex $methodName 0]
            BuildLog "Building $method solid archive..."

            set file [::InstallJammer::BuildDir solid.$method]

            set fp [miniarc::open crap $file w -method none]
            foreach fileid $solid($methodName) {
                set src [::InstallJammer::GetFileSource $fileid]
                BuildLog "Packing $src..." -logtofile 0
                miniarc::addfile $fp $src -name $fileid -temp $tmp
            }
            miniarc::close $fp

            BuildLog "Storing $method solid archive..."
            set fp [miniarc::open crap $conf(tmpExecutable) a -method $method]
            miniarc::addfile $fp $file -name solid.$method -temp $tmp
            miniarc::close $fp

            file delete -force $file
        }
    }

    if {!$errors && [file exists $conf(tmpExecutable)] && [catch {
            file rename -force $conf(tmpExecutable) $conf(executable)
        }]} {
        set errors 1
        BuildLog "Could not rename temporary build file to final\
                    installer.  Installer may be running." -tags error
    }

    if {$errors} {
        BuildLog "$pretty build completed with errors" -tags error
        Status "$pretty build errored." 3000
    } else {
        set secs  [expr [clock seconds] - $conf(buildForPlatformStart)]
        set fmt "%Mm%Ss"
        set time [clock format $secs -format $fmt -gmt 1]
        set size [file size $conf(executable)]
        BuildLog "$pretty build completed in $time."
        BuildLog "Installer size is [::InstallJammer::FormatDiskSpace $size]."

        if {[info exists widg(BuildLog)]} {
            set auto [expr {[lindex [$widg(BuildLog) yview] 1] == 1}]
            set date "[clock format [clock seconds] -format "%D %r"]"
            $widg(BuildLog):cmd insert end "$date - Installer located at "
            $widg(BuildLog):cmd insert end [file tail $conf(executable)] link
            $widg(BuildLog):cmd insert end \n
            if {$auto} { $widg(BuildLog) see end }
        }

        Status "$pretty build complete." 3000
    }

    BuildNext
}

proc ::InstallJammer::TryToDeleteFile { file {tries 0} {timeout 10} } {
    if {[file exists $file]} {
        if {[catch { file delete -force $file }]} {
            if {[incr tries] < $timeout} { after 500 [info level 0] }
        }
    }
}

proc BuildNext {} {
    global conf

    ::InstallJammer::CheckForBuildStop

    PlatformProgress 100

    incr conf(buildIdx)
    set next [lindex $conf(buildList) $conf(buildIdx)]

    if {$next eq ""} {
        BuildDone
    } else {
        set conf(buildErrors)   0
        set conf(buildPlatform) $next
        BuildForPlatform $next
    }
}

proc BuildDone { {errors 0} } {
    global conf
    global info
    global widg

    if {[info exists widg(StopBuildButton)]} {
        $widg(StopBuildButton) configure -state disabled
    }

    variable ::InstallJammer::saveConf
    if {[info exists saveConf]} {
        array set conf $saveConf
        unset saveConf
    }

    variable ::InstallJammer::saveInfo
    if {[info exists saveInfo]} {
        array set info $saveInfo
        unset saveInfo
    }

    ::InstallJammer::StatusPrefix

    set conf(building)  0
    set conf(buildList) {}

    set secs [expr {[clock seconds] - $conf(buildStart)}]
    set time [clock format $secs -format "%Mm%Ss" -gmt 1]

    if {$errors} {
        BuildLog "Fatal error in build." -tags error
        BuildLog "Build stopped." -tags error
        Status "Build stopped." 3000
    } elseif {!$conf(buildStopped)} {
        BuildLog "Build completed in $time."
        Status "Build complete." 3000
        if {$conf(cmdline) && !$conf(silent)} {
            puts  stdout "Installer: [file normalize $conf(executable)]"
            flush stdout
        }
    } else {
        BuildLog "Build stopped by user." -tags error
        Status "Build stopped." 3000
        ::InstallJammer::TryToDeleteFile $conf(tmpExecutable)
    }

    file delete -force $conf(stop) $conf(pause)

    if {[file exists [file join $conf(buildDir) bin]]} {
        file delete -force [file join $conf(buildDir) bin]
    }

    if {[info exists conf(logfp)]} {
	catch { close $conf(logfp) }
	unset -nocomplain conf(logfp)
    }

    unset -nocomplain info(Platform)
    unset -nocomplain conf(buildStart)
    unset -nocomplain conf(buildPlatform)

    FileProgress     0
    BuildProgress    0
    PlatformProgress 0

    ::InstallJammer::SetLastBuilt

    ::InstallJammer::SetMainWindowTitle

    ::InstallJammer::FlashMainWindow

    set ::conf(buildDone) 1
}

proc BuildUninstallData { infoArrayName } {
    global conf
    global info
    global widg

    upvar 1 $infoArrayName buildInfo

    set files [ThemeFiles Uninstall]
    set files [lremove $files init.tcl main.tcl user.tcl windows.tcl]
    lappend files windows.tcl user.tcl

    set data [read_file [file join $conf(lib) header.tcl]]

    #append data [ReadableArrayGet buildInfo info]\n

    append data [::InstallJammer::GetCommandLineOptionData -build 1 \
                -setup Uninstall -includedebug $info(IncludeDebugging)]\n

    append data "\nset PaneList [list [GetPaneList Uninstall 1]]\n"

    append data [::InstallJammer::SaveProperties -build 1 -setup Uninstall \
        -activeonly 1 -includecomments $info(IncludeDebugging) \
        -array ::InstallJammer::Properties]

    append data [::InstallJammer::BuildComponentData Uninstall]\n

    append data [::InstallJammer::GetWindowProcData \
        -build 1 -setups Uninstall -activeonly 1]

    set themedir [::InstallJammer::ThemeDir]

    append data [ShrinkFile [file join $themedir Uninstall init.tcl]]\n

    append data [ShrinkFile [file join $conf(lib) uninstall.tcl]]\n

    foreach file $files {
	set ext [string tolower [file extension $file]]
	if {![string equal $ext ".tcl"]} { continue }
	append data [ShrinkFile [file join $themedir Uninstall $file]]\n
    }

    foreach file [lremove [ThemeFiles Common] setup.tcl] {
        append data [ShrinkFile [::InstallJammer::ThemeFile Common $file]]\n
    }

    ## Store the component objects in the uninstall.
    append data [::InstallJammer::SaveInstallComponents \
                    -build 1 -setup Uninstall -activeonly 1]\n

    append data [ShrinkFile [file join $themedir Uninstall main.tcl]]\n

    return $data
}

proc BuildConditionsData { setup } {
    global conf

    set data ""

    set conditions [list]
    foreach id [GetComponentList $setup 1] {
        foreach cid [$id conditions] {
            lappend conditions [$cid component]
        }
    }

    foreach condition [lsort -unique $conditions] {
        append data [ProcDefinition ::InstallJammer::conditions::$condition 0]\n
    }

    return $data
}

proc ::InstallJammer::GetComponentProcDefinition { component } {
    variable ::InstallJammer::components

    set obj $components($component)

    if {[$obj isa ::InstallJammer::Action]} {
        return [ProcDefinition ::InstallJammer::actions::$component 0]
    } elseif {[$obj isa ::InstallJammer::Condition]} {
        return [ProcDefinition ::InstallJammer::conditions::$component 0]
    }
}

proc ::InstallJammer::BuildComponentData { setup {activeOnly 1} } {
    set list [list]
    foreach id [GetComponentList $setup $activeOnly] {
        if {[$id is action]} {
            lappend list [$id component]
            eval lappend list [[$id object] includes]
        }

        foreach cid [$id conditions] {
            lappend list [$cid component]
            eval lappend list [[$cid object] includes]
        }
    }

    set    data "namespace eval ::InstallJammer::actions {}\n"
    append data "namespace eval ::InstallJammer::conditions {}\n"

    foreach id [lsort -unique $list] {
        append data [GetComponentProcDefinition $id]\n
    }

    return $data
}

proc BuildActionsData { setup {activeOnly 1} } {
    set data "namespace eval ::InstallJammer::actions {}\n"
    foreach action [::InstallJammer::GetActionList $setup $activeOnly] {
        append data [ProcDefinition ::InstallJammer::actions::$action 0]\n
    }
    return $data
}

proc BuildGuiData {} {
    set data "proc ::InitGui {} \{"

    append data {
        if {[info exists ::conf(InitGui)]} { return }
        set ::conf(InitGui) 1

	set ::conf(x11)  0
	set ::conf(aqua) 0

        if {[catch { package require Tk } error]} {
            if {!$::info(FallBackToConsole)} {
                puts "This program must be run in a graphical environment,"
                puts "or you must specify a silent or console install."
                ::InstallJammer::ShowUsageAndExit
            }

            set ::info(GuiMode)       0
            set ::info(SilentMode)    0
            set ::info(DefaultMode)   0
            set ::info(ConsoleMode)   1
            set ::info($::conf(mode)) "Console"

            if {![catch { exec stty size } result]
                && [scan $result "%d %d" height width] == 2} {
                set conf(ConsoleWidth)  $width
                set conf(ConsoleHeight) $height
            }

            return
        }

        set ::info(GuiMode) 1

	set ::conf(wm)   [tk windowingsystem]
	set ::conf(x11)  [string equal $::conf(wm) "x11"]
	set ::conf(aqua) [string equal $::conf(wm) "aqua"]

        wm withdraw .

	if {[package vcompare [package require Tk] 8.5] >= 0} {
	    namespace eval :: { namespace import ::ttk::style }
	} else {
	    package require tile
	}

        package require tkpng

        if {$::conf(x11)} {
            tile::setTheme jammer
        }

        bind TButton <Return> "%W invoke; break"
    }

    append data [GetImageData {Install Uninstall} 1]\n

    ## Add the install theme's setup code.
    append data [ShrinkFile [::InstallJammer::ThemeDir Common/setup.tcl]]\n

    append data "ThemeSetup\n"

    append data [BuildBWidgetData]\n

    append data "ThemeInit\n"

    append data "::InstallJammer::HideMainWindow\n"

    append data "BWidget::use ttk 1 -force 1\n"

    append data "\}\n"

    return $data
}

proc BuildBWidgetData {} {
    global conf

    ## FIXME: Need to figure out how to append only certain BWidgets.
    #set bwidgets [list Wizard ListBox Tree Label]
    #lappend bwidgets -exclude [list DynamicHelp DragSite DropSite]

    set initlibs [list widget utils]

    set libs [list init label tree optiontree listbox \
        separator ttkbutton button buttonbox dialog scrollw \
        icons choosedir choosefile messagedlg text wizard]

    set data ""

    foreach lib $initlibs {
        append data [ShrinkFile [file join $conf(lib) BWidget $lib.tcl]]\n
    }

    append data [ShrinkFile [file join $conf(lib) bwidget.tcl]]\n
    append data "BWidgetInit\n"

    foreach lib $libs {
        append data [ShrinkFile [file join $conf(lib) BWidget $lib.tcl]]\n
    }

    append data "BWidget::LoadBWidgetIconLibrary\n"

    return $data
}

proc ::InstallJammer::BuildAPIData { varName } {
    upvar 1 $varName fullcode

    set data ""
    set code $fullcode

    ## We want to recursively walk through the procs in
    ## the ::InstallAPI namespace and check our code to
    ## see if they're used.
    set pattern {::InstallAPI::[a-zA-Z0-9_-]+}
    while {1} {
        set found 0

        foreach proc [lsort -unique [regexp -all -inline $pattern $code]] {
            if {![info exists done($proc)]} {
                set found 1
                set done($proc) 1
                append data [ProcDefinition $proc 0]\n
            }
        }

        if {!$found} { break }

        set code $data
    }

    append fullcode $data
    return $data
}

proc ::InstallJammer::IncludeTWAPI { code } {
    if {[Windows get IncludeTWAPI]} { return 1 }
    set pattern {twapi::[a-zA-Z0-9_-]+}
    foreach proc [lsort -unique [regexp -all -inline $pattern $code]] {
        if {$proc eq "twapi::get_shell_folder"} { continue }
        return 1
    }
}

proc ::InstallJammer::BuildPackageData { platform } {
    global conf

    set bin 0
    set cmd [list]

    set done(InstallJammer) 1

    foreach pkg [::InstallJammer::GetRequiredPackages 1] {
        if {[info exists done($pkg)]} { continue }
        set done($pkg) 1

        set file [file join $conf(pwd) Binaries $platform $pkg]

        if {![file exists $file]} {
            set file [file join $conf(lib) packages $pkg]
        }

        if {![file exists $file]} {
            continue
        }

        ## If the required package is a directory, just add
        ## it to our list of packages.  Otherwise, it's a
        ## script, and we want to copy it to a bin directory
        ## that we'll include as a package.
        if {[file isdirectory $file]} {
            lappend cmd -package $file
        } else {
            set dir [file join $conf(buildDir) bin]

            file mkdir $dir
            file copy -force $file $dir

            if {!$bin} {
                set bin 1
                lappend cmd -package $dir
            }
        }
    }

    foreach dir [list [file join $conf(lib) packages] [InstallDir packages]] {
        ## Find any packages in the packages/<platform> directory
        ## that we need to include in our installer.
        set dir [file join $dir $platform]

        set platforms [AllPlatforms]
        foreach pkg [glob -nocomplain -type d -dir $dir -tails *] {
            if {[info exists done($pkg)]} { continue }
            set done($pkg) 1

            lappend cmd -package [file join $dir $pkg]
        }

        ## Now check for non-platform-specific packages in the
        ## lib/packages directory to include.
        set dir [file dirname $dir]
        foreach pkg [glob -nocomplain -type d -dir $dir -tails *] {
            if {[info exists done($pkg)]} { continue }
            set done($pkg) 1

            if {[lsearch -exact $platforms $pkg] > -1} { continue }

            lappend cmd -package [file join $dir $pkg]
        }
    }

    return $cmd
}

proc ::InstallJammer::BuildFileManifest {filelist} {
    global conf

    variable ::InstallJammer::solid

    BuildLog "Building file manifest..."

    set fp [open_text $conf(packManifest) w -translation lf -encoding utf-8]

    if {$conf(buildArchives)} {
        set ffp [open_text $conf(fileManifest) w -translation lf \
            -encoding utf-8]
    }

    set i 0
    set nFiles 0
    foreach list $filelist {
        incr nFiles
        lassign $list id file group
        set method [::InstallJammer::GetFileCompressionMethod $id]

        if {[string match "*(solid)*" $method]} {
            lappend solid($method) $id
        } elseif {$conf(buildArchives)} {
            puts $ffp [concat $list [list $method]]
            if {![info exists archives($group)]} {
                set archives($group) setup[incr i].ijc
            }
        } else {
            puts $fp [list $file $id $method]
        }
    }

    foreach file [::InstallJammer::GetComponentExtraFiles Install] {
        incr nFiles
        puts $fp [list $file support/[file tail $file]]
    }

    close $fp
    if {[info exists ffp]} { close $ffp }

    if {!$nFiles} {
        file delete -force $conf(packManifest) $conf(fileManifest)
    }

    return [array get archives]
}

proc VirtualTextData {} {
    global info

    set data [list]
    foreach var [lsort [array names info]] {
        if {![::InstallJammer::IsReservedVirtualText $var]} {
            lappend data $var $info($var)
        }
    }

    return $data
}

proc Progress { {amt ""} } {
    global conf
    global widg

    if {$conf(cmdline)} { return }

    if {![lempty $amt]} {
	set ::conf(progress) $amt
    } else {
	incr ::conf(progress)
    }
    set value [$widg(Progress) cget -value]
    if {[info exists widg(Progress)]} {
	$widg(Progress) configure -value $::conf(progress)
    }

    if {!$amt} {
        ## If amt is 0, remove the progressbar.
        grid remove $widg(Progress)
        $widg(Status) configure -showresizesep 0
    } elseif {$amt && !$value} {
        ## If amt is greater than 0 and our previous value
        ## was 0, we need to grid the progressbar into place.
        grid $widg(Progress)
        $widg(Status) configure -showresizesep 1
        update idletasks
    }

    #update idletasks
}

proc PlatformProgress { amt } {
    global conf
    global widg

    if {$conf(cmdline)} { return }

    if {$conf(building)} {
        set len [llength $conf(buildList)]
        set x   [expr {round($amt / $len)}]
        BuildProgress $x
    }

    set conf(buildPlatformProgress) $amt

    if {[info exists widg(ProgressBuildPlatform)]
	&& [winfo viewable $widg(ProgressBuildPlatform)]} {
	$widg(ProgressBuildPlatform) configure -value $amt
	#update idletasks
    }
}

proc BuildProgress { amt } {
    global conf
    global widg

    if {$conf(cmdline)} { return }

    if {$conf(building)} {
        if {!$amt} { return }
        set len [llength $conf(buildList)]
        set conf(buildProgress) [expr {$amt + ($conf(buildIdx) * (100 / $len))}]
    } else {
        set conf(buildProgress) 0
    }

    if {[info exists widg(ProgressBuild)]
	&& [winfo viewable $widg(ProgressBuild)]} {
	$widg(ProgressBuild) configure -value $::conf(buildProgress)
	#update idletasks
    }
    ::InstallJammer::SetMainWindowTitle
    Progress $conf(buildProgress)
}

proc FileProgress { {amt ""} } {
    global conf
    global widg

    if {$conf(cmdline)} { return }

    if {![lempty $amt]} {
	set ::conf(fileProgress) $amt
    } else {
	incr ::conf(fileProgress)
    }
    if {[info exists widg(ProgressBuildFile)]
	&& [winfo viewable $widg(ProgressBuildFile)]} {
	$widg(ProgressBuildFile) configure -value $::conf(fileProgress)
	#update idletasks
    }
}

## FIXME:  Fix GetInstallComponentFiles
## Needs to be updated to actually get the full list of files needed
## when building.  This is usually just a list of icons that need to
## get included in the install.
proc ::InstallJammer::GetComponentExtraFiles { setup } {
    global conf

    set files [list]
    foreach id [GetComponentList $setup 1] {
        switch -- [$id component] {
            "InstallWishBinary" -
            "InstallWrappedScript" -
            "InstallWrappedApplication" {
                set icon [$id get WindowsIcon]
                if {![string length $icon]} { continue }

		if {[string equal [file pathtype $icon] "relative"]} {
		    set icon [file join $conf(pwd) Images "Windows Icons" $icon]
		}
		lappend files $icon
	    }
	}
    }

    return [lsort -unique $files]
}

proc ::InstallJammer::QuickBuild { {platforms {}} } {
    global conf

    variable saveConf

    set saveConf [list rebuildOnly $conf(rebuildOnly)]

    set conf(rebuildOnly) 1

    Build $platforms
}

proc ::InstallJammer::PauseBuild {} {
    global conf
    if {$conf(building)} {
        close [open $conf(pause) w]
    }
}

proc ::InstallJammer::StopBuild {} {
    global conf
    if {$conf(building)} {
        ::InstallJammer::PauseBuild
        close [open $conf(stop)  w]
    }
}

proc ::InstallJammer::CheckForBuildStop { {stop 1} } {
    global conf

    if {$conf(cmdline)} { return }

    if {$conf(buildStopped)} {
        if {$stop} { return -code return }
        return
    }

    while {[file exists $conf(pause)]} {
        if {[file exists $conf(stop)]} {
            set conf(buildStopped) 1
            if {!$stop} { return }

            ::InstallJammer::FinishBuild
            return -code return
        }
        after 500
    }
}

proc Build { {platforms {}} } {
    global conf
    global info
    global widg

    if {$conf(demo)} {
	set    msg "Cannot build installs in demo mode."
	append msg "Please see About Demo Mode for more information."

	::InstallJammer::Message -title "InstallJammer Demo Mode" -message $msg
    	return
    }

    if {!$conf(projectLoaded)} {
	::InstallJammer::Message -message "No project loaded!"
	return
    }

    if {$conf(building)} {
	::InstallJammer::Error -message "A build is already in progress."
	return
    }

    if {$conf(modified) && !$conf(cmdline)} {
	set msg "This project has been modified.  "
	append msg "Do you want to save before building?"
	set res [::InstallJammer::MessageBox \
	    -title "Project Modified" -type yesnocancel -message $msg]

	switch -- $res {
	    "yes"    {
	    	Save
	    }
	    "cancel" { return }
	}
    }

    set conf(buildErrors) 0
    set conf(totalBuildErrors) 0

    if {$conf(buildForRelease)} {
        variable ::InstallJammer::saveConf
        variable ::InstallJammer::saveInfo

        set saveConf [list \
                rebuildOnly $conf(rebuildOnly) \
                buildMainTclOnly $conf(buildMainTclOnly)]

        set saveInfo [list \
                IncludeDebugging $info(IncludeDebugging)]

        set conf(rebuildOnly)      0
        set conf(buildMainTclOnly) 0

        set info(IncludeDebugging) 0

        BuildLog "Configuring build for final release..."
    }

    if {!$conf(rebuildOnly) && [info exists widg(Product)]} {
        $widg(Product) raise diskBuilder
        update
    }

    if {$conf(fullBuildRequired) && $conf(rebuildOnly)} {
        set msg "The installer format has changed and a full rebuild is\
                required.  Do you want to continue with the full build?"

	set ans [::InstallJammer::MessageBox \
	    -title "Full Build Required" -type yesno -message $msg]

        if {$ans eq "no"} { return }

        set conf(rebuildOnly)       0
        set conf(fullBuildRequired) 0
    }

    set conf(stop)  [::InstallJammer::BuildDir .stop]
    set conf(pause) [::InstallJammer::BuildDir .pause]
    file delete -force $conf(stop) $conf(pause)

    ::InstallJammer::SaveActiveComponent

    set conf(buildIdx)     -1
    set conf(buildDir)     [::InstallJammer::BuildDir]
    set conf(buildDone)    0
    set conf(buildList)    [list]
    set conf(buildStart)   [clock seconds]
    set conf(buildStopped) 0
    set conf(refreshFiles) $info(AutoRefreshFiles)

    set all  [AllPlatforms]
    set real 0
    if {[lempty $platforms]} {
	foreach platform [ActivePlatforms] {
	    if {!$conf(build,$platform)}  { continue }
            incr real
	    lappend conf(buildList) $platform
	}

        if {!$conf(rebuildOnly)} {
            foreach archive $conf(Archives) {
                if {$conf(build,$archive) && [$archive get Active]} {
                    lappend conf(buildList) $archive
                }
            }
        }
    } else {
        foreach platform $platforms {
            if {[lsearch -exact $all $platform] > -1} {
                incr real
                lappend conf(buildList) $platform
            } else {
                if {!$conf(rebuildOnly)
                    && [string equal -nocase $platform "tar"]} {
                    lappend conf(buildList) TarArchive
                }
            }
        }
    }

    if {![llength $conf(buildList)]} {
        BuildLog "Nothing to build."
        return
    }

    if {!$conf(cmdline)} {
        set conf(buildProgress) 0
        grid $widg(Progress)
        $widg(Status) configure -showresizesep 1
        update idletasks
        $widg(BuildLog) see end
    }

    file mkdir [::InstallJammer::BuildDir] [::InstallJammer::OutputDir]

    BuildLog "Building message catalogs..."

    if {$real} {
        set msgfile [::InstallJammer::BuildDir messages]
        set fp [open_text $msgfile w -translation lf -encoding utf-8]
        puts $fp [::InstallJammer::GetTextData -setups Install \
            -activeonly 1 -build 1]
        close $fp
    }

    if {$conf(filesModified)} {
        foreach platform [AllPlatforms] {
            set file [::InstallJammer::BuildDir ${platform}-files.tcl]
            if {[file exists $file]} {
                file delete -force $file
            }
        }
        ::InstallJammer::FilesModified 0
    }

    if {[info exists widg(StopBuildButton)]} {
        $widg(StopBuildButton) configure -state normal
    }

    BuildNext

    if {!$conf(buildDone) && $conf(cmdline)} {
        vwait ::conf(buildDone)
    }
}

proc BuildForPlatform { platform } {
    global conf
    global info
    global widg

    variable ::InstallJammer::solid
    unset -nocomplain solid

    ::InstallJammer::CheckForBuildStop

    set conf(building) 1
    set conf(buildPlatform) $platform
    set conf(buildPlatformProgress) 0
    set conf(buildForPlatformStart) [clock seconds]

    set info(Ext)      [expr {$platform eq "Windows" ? ".exe" : ""}]
    set info(Platform) $platform

    if {[::InstallJammer::ArchiveExists $platform]} {
        ::InstallJammer::Build$platform
        ::InstallJammer::FinishBuild $conf(buildErrors)
        return
    }

    set cmdargs [list]

    set conf(main)     [::InstallJammer::BuildDir ${platform}-main.tcl]

    set conf(fileManifest) [::InstallJammer::BuildDir ${platform}.files]
    set conf(packManifest) [::InstallJammer::BuildDir ${platform}-manifest.txt]

    set conf(fileDataFile) [::InstallJammer::BuildDir ${platform}-files.tcl]

    set conf(tmpExecutable) [::InstallJammer::BuildDir ${platform}-build.tmp]
    file delete -force $conf(tmpExecutable)

    set executable [::InstallJammer::SubstText [$platform get Executable]]
    set executable [regsub -all {[<>:\"/\\\|\?\*]} $executable "_"]
    set conf(outputDir)  [::InstallJammer::OutputDir]
    set conf(buildArchives) [$platform get BuildSeparateArchives]
    if {$conf(buildArchives)} {
        set conf(setupFileList) {}
        if {![info exists conf(OutputDir)]} {
            set conf(outputDir) [file join $conf(outputDir) $platform]
        }
    }
    set conf(executable) [file join $conf(outputDir) $executable]

    file mkdir [::InstallJammer::BuildDir] $conf(outputDir)

    FileProgress     0
    PlatformProgress 0

    set text [PlatformText $platform]
    BuildLog "Building $text install...  "

    ::InstallJammer::StatusPrefix "Building $text install...  "

    set rebuildOnly 0
    if {$conf(rebuildOnly)} {
	if {![file exists $conf(executable)]} {
	    BuildLog "Install does not exist.  Doing a full build..."
	    set rebuildOnly 0
	} else {
	    BuildLog "Rebuilding without repackaging files..."
	    set rebuildOnly 1
	}
    }

    if {$platform eq "Windows"} {
        set admin [$platform get RequireAdministrator]
        set last  [$platform get LastRequireAdministrator]
        if {$admin ne $last} {
            BuildLog "Require Administrator changed.  Doing a full build..."
            set rebuildOnly 0
        }
        $platform set LastRequireAdministrator $admin
    }

    BuildLog "Building main.tcl..."

    set fp [open_text $conf(main) w -translation lf -encoding utf-8]

    puts $fp [read_file [file join $conf(lib) header.tcl]]

    puts $fp "namespace eval ::InstallAPI {}"
    puts $fp "namespace eval ::InstallJammer {}"
    puts $fp "set conf(version)     $conf(Version)"
    puts $fp "set info(Platform)    [list $platform]"
    puts $fp "set info(InstallerID) [list [::InstallJammer::uuid]]"

    set langs [::InstallJammer::GetActiveLanguages]
    puts $fp "array set ::InstallJammer::languagecodes [list $langs]"

    ::InstallJammer::CheckForBuildStop

    array set buildInfo [VirtualTextData]

    foreach var $conf(InstallVars) {
        set buildInfo($var) $info($var)
    }

    foreach var $conf(PlatformVars) {
        if {[$platform get $var value]} { set buildInfo($var) $value }
    }

    if {$info(InstallPassword) ne ""} {
        set buildInfo(InstallPasswordEncrypted) \
            [sha1 -string $info(InstallPassword)]
    }

    puts $fp [ReadableArrayGet buildInfo info]

    puts $fp [::InstallJammer::GetCommandLineOptionData -build 1 \
                -setup Install -includedebug $info(IncludeDebugging)]

    ::InstallJammer::CheckForBuildStop

    ## Make a dummy call to SaveFileGroups to find out what file groups
    ## we're going to use in this install.  This sets up the data so
    ## that GetSetupFileList will get only the files we're using.
    ::InstallJammer::SaveFileGroups -build 1 -platform $platform

    ## Build the file list first.  Getting a list of all the files will
    ## update the group objects with their proper sizes for when we
    ## save them in the install.

    ## If we're doing a quick build and we have existing file data,
    ## we'll just use that instead of rebuilding it.  Otherwise,
    ## we'll build the file data and then store it out to a file for
    ## next time.
    if {$rebuildOnly && [file exists $conf(fileDataFile)]
        && [file exists $conf(executable)]} {
        set fileData [read_textfile $conf(fileDataFile)]
    } else {
        set rebuildOnly 0
        if {$conf(refreshFiles)} {
            set conf(refreshFiles) 0
            ::InstallJammer::RefreshFileGroups
        }

        BuildLog "Getting file list..."
        set filelist {}
        ::InstallJammer::GetSetupFileList -platform $platform \
            -errorvar missing -listvar filelist -procvar fileData

        set ofp [open_text $conf(fileDataFile) w -translation lf \
            -encoding utf-8]
        puts $ofp $fileData
        close $ofp
    }

    ::InstallJammer::CheckForBuildStop

    if {!$rebuildOnly} {
        if {[llength $missing]} {
            set action $info(BuildFailureAction)
            if {$conf(cmdline)} {
                set action $info(CommandLineFailureAction)
            }
	    set fail [string match "*Fail*" $action]

            foreach file $missing {
		BuildLog "File '$file' does not exist!" -tags error
		if {!$fail} { incr conf(totalBuildErrors) -1 }
            }

	    if {$fail} {
                close $fp
                ::InstallJammer::FinishBuild 1
                return
            }
        }

        foreach {group file} [::InstallJammer::BuildFileManifest $filelist] {
            lappend arcFiles  $file
            lappend arcGroups $group
        }

        if {[info exists arcFiles]} {
            puts $fp "set info(ArchiveFileList) [list $arcFiles]"
            puts $fp "set info(ArchiveGroupList) [list $arcGroups]"
        }
    }

    ::InstallJammer::CheckForBuildStop

    BuildLog "Saving install information..."

    ## Save all the file groups, components and setup types inside a
    ## proc so that we can call it once the system has been initialized
    ## and not when the install is sourced in.
    set    setupData "proc ::InstallJammer::InitSetup {} \{\n"
    append setupData [::InstallJammer::SaveBuildInformation -platform $platform]
    append setupData "\n\}"

    ::InstallJammer::CheckForBuildStop

    ## Store properties.
    set propertyData [::InstallJammer::SaveProperties -build 1 -setup Install \
        -activeonly 1 -includecomments $info(IncludeDebugging) \
        -array ::InstallJammer::Properties]
    puts $fp $propertyData

    ## Build a string of procs and other data that we want to check
    ## for API calls.  When we build the API data, we will only
    ## include procs that have been called somewhere in our install.
    append apiCheckData $propertyData\n

    ## Store InstallJammer files in the main.tcl file.  This means that in
    ## order to update the install, we only have to overwrite one file.
    ## It also makes it easy to delete the entire install contents with
    ## just one file.
    set installBaseFiles [list common.tcl unpack.tcl]
    if {$platform ne "Windows"} { lappend installBaseFiles console.tcl }
    foreach file $installBaseFiles {
	set filedata($file) [read_file [::InstallJammer::LibDir $file]]
    }

    upvar 0 filedata(common.tcl) commonTcl

    ## Add the build system file by appending it to the common.tcl file.
    append commonTcl "\n[read_file [::InstallJammer::LibDir installkit.tcl]]"

    set filedata(files.tcl)      $fileData
    set filedata(setup.tcl)      $setupData
    set filedata(gui.tcl)        [BuildGuiData]
    set filedata(components.tcl) [::InstallJammer::BuildComponentData Install]

    ## Check for an uninstaller and add it if needed.
    set actions [::InstallJammer::GetActionList Install 1]
    if {[lsearch -exact $actions "InstallUninstaller"] > -1} {
	set filedata(uninstall.tcl) [BuildUninstallData buildInfo]
    }

    ::InstallJammer::CheckForBuildStop

    foreach file [lremove [ThemeFiles Install] init.tcl main.tcl] {
	puts $fp [ShrinkFile [::InstallJammer::ThemeDir Install/$file]]
    }

    foreach file [lremove [ThemeFiles Common] setup.tcl] {
        puts $fp [ShrinkFile [::InstallJammer::ThemeFile Common $file]]
    }

    set installCode [ShrinkFile [::InstallJammer::LibDir install.tcl]]

    append apiCheckData $installCode\n

    ::InstallJammer::CheckForBuildStop

    ## Store pane proc data.
    set windowProcData [::InstallJammer::GetWindowProcData \
        -build 1 -setups Install -activeonly 1]
    puts $fp $windowProcData

    append apiCheckData $windowProcData\n
    append apiCheckData [array get filedata]\n

    ## Add the install API routines.
    uplevel #0 [list source [file join $conf(lib) installapi.tcl]]
    append commonTcl "\n[::InstallJammer::BuildAPIData apiCheckData]"

    foreach file [array names filedata] {
        set filedata($file) [ShrinkCode $filedata($file)]
    }

    ## Store all of the stored file data.
    puts $fp "array set ::InstallJammer::files [list [array get filedata]]"
    puts $fp "::InstallJammer::SourceCachedFile common.tcl"

    ## Add the install theme's inititialization code.
    puts $fp [ShrinkFile [::InstallJammer::ThemeDir Install/init.tcl]]\n

    set installComponentData [::InstallJammer::SaveInstallComponents \
        -build 1 -activeonly 1 -setup Install -actiongroupvar actionGroupData]

    ## Store the action groups before the install routines because some
    ## of them can be executed during the install startup.
    puts $fp $actionGroupData

    ## Store the standard procedures used for all installs.
    puts $fp $installCode
    
    ::InstallJammer::CheckForBuildStop

    ## Store the component objects in the install.
    puts $fp $installComponentData

    set main [::InstallJammer::ThemeDir Install/main.tcl]
    if {[file exists $main]} {
        ## Add the install theme's main code last.
        puts $fp [ShrinkFile [::InstallJammer::ThemeDir Install/main.tcl]]
    } else {
        puts $fp "::InstallJammer::InstallMain"
    }

    close $fp

    ## If we're only building main.tcl, we don't need to do the rest.
    if {$conf(buildMainTclOnly)} { return }

    set execdir [file dirname $conf(executable)]
    if {![file exists $execdir]} { file mkdir $execdir }
    file delete -force [file join $execdir runtime]
    if {!$rebuildOnly} {
    	if {[catch { file delete -force $conf(tmpExecutable) }]} {
	    set msg "Failed to delete $conf(tmpExecutable)."
	    append msg "  The program may be running."
	    ::InstallJammer::Error -title "Error Building" -message $msg
	    ::InstallJammer::FinishBuild 1
	    return
	}
    }

    ::InstallJammer::CheckForBuildStop

    BuildLog "Building install..."

    ## If we're only rebuilding the interface, and we're running from
    ## an installkit, we can make this really short and sweet.
    if {$rebuildOnly && [info exists ::installkit::root]} {
        set files [list $conf(main) [::InstallJammer::BuildDir messages]]
        set names [list main.tcl catalogs/messages]
        installkit::addfiles $conf(executable) $files $names
	::InstallJammer::FinishBuild
	return
    }

    set buildScript [file join $conf(lib) dobuild.tcl]

    set cmd [list [BuildBinary] $buildScript -o $conf(tmpExecutable)]
    eval lappend cmd $cmdargs
    lappend cmd --build $conf(buildDir)
    lappend cmd --output $conf(outputDir)

    lappend cmd -temp [::InstallJammer::BuildDir]

    lappend cmd -level $info(CompressionLevel)

    lappend cmd -catalog [::InstallJammer::BuildDir messages]

    if {$info(InstallPassword) ne ""} {
        lappend cmd -password \
            [::InstallJammer::SubstText $info(InstallPassword)]
    }

    ## Include the InstallJammer package files.
    lappend cmd -package [file join $conf(lib) packages InstallJammer]

    eval lappend cmd [::InstallJammer::BuildPackageData $platform]

    if {$platform eq "Windows"} {
        ## If the user wants to include the TWAPI extension, or we
        ## find a twapi command anywhere in our code, we want to
        ## include the TWAPI extension.
        if {[lsearch -glob $cmd "*twapi"] < 0
            && [::InstallJammer::IncludeTWAPI $apiCheckData]} {
            ## Add the TWAPI extension.
            lappend cmd -package [file join $conf(pwd) Binaries Windows twapi]
        }

        if {[$platform get WindowsIcon icon]} {
            set file [::InstallJammer::FindFile $icon $conf(winico)]
	    if {![file exists $file]} {
		BuildLog "Windows Icon '$icon' does not exist." -tags error
	    } else {
		lappend cmd -icon $file
	    }
	}

        lappend cmd -company [::InstallJammer::SubstText $info(Company)]
        lappend cmd -copyright [::InstallJammer::SubstText $info(Copyright)]
        lappend cmd -fileversion \
            [::InstallJammer::SubstText $info(InstallVersion)]
        lappend cmd -productname [::InstallJammer::SubstText $info(AppName)]
        lappend cmd -productversion [::InstallJammer::SubstText $info(Version)]

        set desc [::InstallJammer::SubstText [$platform get FileDescription]]
        if {$desc ne ""} { lappend cmd -filedescription $desc }
    }

    if {$rebuildOnly} {
	file rename $conf(executable) [file join $execdir runtime]
	lappend cmd -w [file join $execdir runtime]
    } else {
        if {[file exists $conf(packManifest)]} {
	    lappend cmd -f $conf(packManifest)
        }

        if {$conf(buildArchives) && [file exists $conf(fileManifest)]} {
            lappend cmd --archive-manifest $conf(fileManifest)
        }

	lappend cmd -w [InstallKitStub $platform]
    }
    lappend cmd $conf(main)

    ::InstallJammer::CheckForBuildStop

    if {[threaded]} {
        thread::errorproc ::InstallJammer::BuildOutput
        set tid [installkit::newThread thread::wait]
        thread::send $tid [list set ::argv [lrange $cmd 2 end]]
        thread::send $tid [list lappend ::auto_path $conf(bin)]
        thread::send $tid [list source $conf(lib)/common.tcl]
        thread::send $tid [list source $conf(lib)/installkit.tcl]
        thread::send -async $tid [list source $buildScript]
    } else {
	set fp [open "|$cmd"]
	set conf(buildPID) [pid $fp]
	fconfigure $fp -blocking 0
	fileevent $fp readable [list ::InstallJammer::ReadBuild $fp]
    }

    ::InstallJammer::CheckForBuildStop
}

proc ::InstallJammer::BuildZipArchive {} {
    global conf
    global info

    set archive ZipArchive

    ::InstallJammer::StatusPrefix "Building zip archive...  "

    BuildLog "Building zip archive..."

    if {$conf(refreshFiles)} {
        set conf(refreshFiles) 0
        ::InstallJammer::RefreshFileGroups
    }

    BuildLog "Getting file list..."
    set filelist {}
    ::InstallJammer::GetSetupFileList -platform $archive \
        -checksave 0 -listvar filelist -includedirs 0

    if {![llength $filelist]} {
        BuildLog "No files to archive..." -tags error
        return
    }

    set level  [$archive get CompressionLevel]
    set output [::InstallJammer::SubstText [$archive get OutputFileName]]
    set output [::InstallJammer::OutputDir $output]

    set conf(executable)    $output
    set conf(tmpExecutable) $output.tmp

    if {[file exists $output]} { file delete -force $output }

    set map [list]
    foreach {string value} [$archive get VirtualTextMap] {
        lappend map $string [::InstallJammer::SubstText $value]
    }

    if {[catch { ::miniarc::open zip $conf(tmpExecutable) -level $level } fp]} {
        BuildLog "Error opening zip file for output! $fp" -tags error
        BuildLog $fp -tags error
        return
    }

    set filesdone    0
    set totalfiles   [llength $filelist]
    set lastpercent  0
    set totalpercent 100

    foreach list $filelist {
        lassign $list id file group
        set file [::InstallJammer::GetFileSource $id]
        set dest [string map $map [::InstallJammer::GetFileDestination $id]]

        if {![info exists done($dest)]} {
            BuildLog "Packing $file..." -logtofile 0

            if {[catch { ::miniarc::addfile $fp $file -name $dest } error]} {
                BuildLog "Error archiving file '$file': $error" -tags error
                return
            }
            set done($dest) 1

            set pct [expr {([incr filesdone] * $totalpercent) / $totalfiles}]

            if {$pct != $lastpercent} {
                PlatformProgress $pct
                set lastpercent $pct
                update
            }
        }
    }

    ::miniarc::close $fp
}

proc ::InstallJammer::BuildTarArchive {} {
    global conf
    global info

    set archive TarArchive

    ::InstallJammer::StatusPrefix "Building tar archive...  "

    BuildLog "Building tar archive..."

    if {$conf(refreshFiles)} {
        set conf(refreshFiles) 0
        ::InstallJammer::RefreshFileGroups
    }

    BuildLog "Getting file list..."
    set filelist {}
    ::InstallJammer::GetSetupFileList -platform $archive \
        -checksave 0 -listvar filelist -includedirs 1

    set output [::InstallJammer::SubstText [$archive get OutputFileName]]
    set output [::InstallJammer::OutputDir $output]

    set level [$archive get CompressionLevel]
    if {$level == 0 && [string match "*.gz" $output]} {
        set output [file root $output]
    }

    if {[file exists $output]} { file delete -force $output }

    set conf(executable) $output
    set conf(tmpExecutable) $output.tmp

    if {![llength $filelist]} {
        BuildLog "No files to archive..." -tags error
        return
    }

    set map [list]
    foreach {string value} [$archive get VirtualTextMap] {
        lappend map $string [::InstallJammer::SubstText $value]
    }

    if {[catch { ::miniarc::open tar $conf(tmpExecutable) } fp]} {
        BuildLog "Error opening tar file for output! $fp" -tags error
        BuildLog $fp -tags error
        return
    }

    set filesdone    0
    set totalfiles   [llength $filelist]
    set lastpercent  0
    set totalpercent 100

    if {$level > 0} { set totalpercent 95 }

    set defdirmode  [$archive get DefaultDirectoryPermission]
    set deffilemode [$archive get DefaultFilePermission]
    foreach list $filelist {
        lassign $list id file group
        set file [::InstallJammer::GetFileSource $id]
        set dest [string map $map [::InstallJammer::GetFileDestination $id]]

        set mode [$id permissions]
        if {$mode eq ""} {
            if {[$id is file]} {
                set mode $deffilemode
            } else {
                set mode $defdirmode
            }
        }

        if {![info exists done($dest)]} {
            BuildLog "Packing $file..." -logtofile 0

            if {[catch { ::miniarc::addfile $fp $file \
                        -name $dest -permissions $mode } error]} {
                BuildLog "Error archiving file '$file': $error" -tags error
                return
            }
            set done($dest) 1

            set pct [expr {([incr filesdone] * $totalpercent) / $totalfiles}]

            if {$pct != $lastpercent} {
                PlatformProgress $pct
                set lastpercent $pct
                update
            }
        }
    }

    ::miniarc::close $fp

    if {$level > 0} {
        BuildLog "Gzipping tar archive..."
        ::miniarc::gzip -delete 1 -level $level $conf(tmpExecutable) $output
    }
}
Added lib/builderapi.tcl.


















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

namespace eval ::BuilderAPI {}

proc ::BuilderAPI::GetAction { args } {
    ::InstallAPI::ParseArgs _args $args {
        -alias { string 1 }
        -setup { choice 0 "" {install uninstall} }
    }

    set setups $_args(-setup)
    if {$setups eq ""} { set setups [list install uninstall] }

    foreach setup $setups {
        set setup [string totitle $setup]

        set list [::InstallJammer::GetActionComponentList $setup]

        foreach id $list {
            if {[$id get Alias] eq $_args(-alias)} { return $id }
        }
    }
}

proc ::BuilderAPI::GetActionGroup { args } {
    ::InstallAPI::ParseArgs _args $args {
        -alias { string 1 }
        -setup { choice 0 "" {install uninstall} }
    }

    set setups $_args(-setup)
    if {$setups eq ""} { set setups [list install uninstall] }

    foreach setup $setups {
        set list [ActionGroups[string toupper $setup 0] children]

        foreach id $list {
            if {[$id get Alias] eq $_args(-alias)} { return $id }
        }
    }
}

proc ::BuilderAPI::ModifyObject { args } {
    ::InstallAPI::ParseArgs _args $args {
        -object { string  1 }
        -active { boolean 0 }
    }

    set id [::InstallJammer::ID $_args(-object)]

    if {[info exists _args(-active)]} {
        $id active $_args(-active)
    }
}

proc ::BuilderAPI::SetPlatformProperty { args } {
    ::InstallAPI::ParseArgs _args $args {
        -platform { string 1 }
        -property { string 1 }
        -value    { string 1 }
    }

    set platforms $_args(-platform)

    if {[string equal -nocase $_args(-platform) "all"]} {
        set platforms [AllPlatforms]
    }

    if {[string equal -nocase $_args(-platform) "unix"]} {
        set platforms [lremove [AllPlatforms] "Windows"]
    }

    if {[string equal -nocase $_args(-platform) "active"]} {
        set platforms [ActivePlatforms]
    }

    foreach platform $platforms {
        if {![::InstallJammer::ObjExists $platform]} {
            return -code error "\"$platform\" is not a valid platform"
        }

        $platform set $_args(-property) $_args(-value)
    }
}
Added lib/bwidget.tcl.


























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

if {[info exists ::InstallJammer]} { return }

namespace eval ::BWIDGET {
    variable LIBRARY [file join $::installkit::root lib InstallJammer]
}

proc BWidgetInit {} {
    set ::BWidget::imageDir $::BWIDGET::LIBRARY
    set ::BWidget::iconLibraryFile [file join $::BWIDGET::LIBRARY icons.tkico]

    BWidget::use ttk
    BWidget::use png
}

namespace eval DragSite    { proc use {} {} }
namespace eval DropSite    { proc use {} {} }
namespace eval DynamicHelp { proc use {} {} }

proc DragSite::include { class type event } {
    set dragoptions [list \
	    [list	-dragenabled	Boolean	0	0] \
	    [list	-draginitcmd	String	""	0] \
	    [list	-dragendcmd	String	""	0] \
	    [list	-dragtype	String	$type	0] \
	    [list	-dragevent	Enum	$event	0	[list 1 2 3]] \
	    ]
    Widget::declare $class $dragoptions
}
proc DragSite::setdrag {args} { }

proc DropSite::include { class types } {
    set dropoptions [list \
	    [list	-dropenabled	Boolean	0	0] \
	    [list	-dropovercmd	String	""	0] \
	    [list	-dropcmd	String	""	0] \
	    [list	-droptypes	String	$types	0] \
	    ]
    Widget::declare $class $dropoptions
}

proc DynamicHelp::include { class type } {
    set helpoptions [list \
	    [list -helptext String "" 0] \
	    [list -helpvar  String "" 0] \
	    [list -helptype Enum $type 0 [list balloon variable]] \
	    ]
    Widget::declare $class $helpoptions
}

proc DropSite::setdrop    { args } { }
proc DropSite::setcursor  { args } { }
proc DynamicHelp::sethelp { args } { }

package provide BWidget 1.8
Added lib/class.tcl.


























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

::itcl::class ::InstallJammer::ComponentDetails {
    inherit Object

    constructor { args } {
        eval configure $args

        standard ID         readonly   "ID"
        standard Active     boolean    "Active"  Yes
        standard Alias      shorttext  "Alias"
        standard Comment    text       "Comment"
        standard Data       text       "Data"
    }

    method initialize { id args } {
        variable ::InstallJammer::ComponentObjectMap
        set ComponentObjectMap($id) $this

        foreach {prop val} $args {
            $id set -safe $prop $val
        }

        foreach prop [properties] {
            $id set -safe $prop $propertyopts($prop,value)
        }

        foreach field [lsort $textfields] {
            $id set -safe $field,subst $propertyopts($field,subst)
        }
    }

    method get { prop field varName } {
        upvar 1 $varName var
        if {![info exists propertyopts($prop,$field)]} { return 0 }
        set var $propertyopts($prop,$field)
        return 1
    }

    method standard { prop args } {
        if {[lsearch -exact $standardprops $prop] < 0} {
            lappend standardprops $prop
        }
        eval [list property $prop] $args
    }

    method property { prop type pretty {value ""} {choices ""} } {
        if {[string equal $type "image"]} { image $prop }

        if {[lsearch -exact $properties $prop] < 0} { lappend properties $prop }
        set propertyopts($prop,type)    $type
        set propertyopts($prop,pretty)  $pretty
        set propertyopts($prop,value)   $value
        set propertyopts($prop,choices) $choices
        set propertyopts($prop,help)    ""
    }

    method text { field pretty subst } {
        lappend textfields $field
        set propertyopts($field,subst)  $subst
        set propertyopts($field,pretty) $pretty
    }

    method addproperties { prop id args } {
        array set _args {
            -array        ::InstallJammer::active
            -standard     1
            -advanced     1
            -parentnode   ""
            -properties   {}
            -standardnode standard
            -advancednode advanced
        }
        array set _args $args

        if {[llength $_args(-properties)]} {
            foreach property $_args(-properties) {
                set var  $_args(-array)($property)
                AddProperty $prop end $_args(-parentnode) $id $property $var \
                    -data    $property \
                    -help    $propertyopts($property,help)   \
                    -type    $propertyopts($property,type)   \
                    -pretty  $propertyopts($property,pretty) \
                    -choices $propertyopts($property,choices)
            }
            return
        }

        set standard [standardproperties]
        if {![string is boolean -strict $_args(-standard)]} {
            set standard $_args(-standard)
            set _args(-standard) 1
        }

        if {$_args(-standard)} {
            foreach property $standard {
                set var  $_args(-array)($property)
                AddProperty $prop end $_args(-standardnode) $id $property $var \
                    -data    $property \
                    -help    $propertyopts($property,help)   \
                    -type    $propertyopts($property,type)   \
                    -pretty  $propertyopts($property,pretty) \
                    -choices $propertyopts($property,choices)
            }
        }

        set advanced [properties 0]
        if {![string is boolean -strict $_args(-advanced)]} {
            set advanced $_args(-advanced)
            set _args(-advanced) 1
        }

        if {$_args(-advanced)} {
            if {[lempty $advanced]} { return }

            foreach property $advanced {
                set var  $_args(-array)($property)
                AddProperty $prop end $_args(-advancednode) $id $property $var \
                    -data    $property \
                    -help    $propertyopts($property,help)   \
                    -type    $propertyopts($property,type)   \
                    -pretty  $propertyopts($property,pretty) \
                    -choices $propertyopts($property,choices)
            }
        }
    }

    method addtextfields { prop node id {arrayName ::InstallJammer::active} } {
        set check $prop.editTextFieldSubst
        if {![winfo exists $check]} {
            # CHECKBUTTON $check -padx 0 -pady 0 -bd 0 -command Modified
            CHECKBUTTON $check -command Modified
            DynamicHelp::add $check \
                -text "Do virtual text substitution for this field"
        }

        foreach field [lsort $textfields] {
            set var    ${arrayName}($field)
            set subst  ${arrayName}($field,subst)
            set pretty $propertyopts($field,pretty)

            set start  ::InstallJammer::EditTextFieldNode
            set end    ::InstallJammer::FinishEditTextFieldNode
            set etitle "Edit $pretty"
            $prop insert end $node #auto -text $pretty -variable $var \
                -browsebutton 1 -browseargs [list -style Toolbutton] \
                -browsecommand [list EditTextField $id $field $etitle $var] \
                -editstartcommand  [list $start $prop $id $field $var $subst] \
                -editfinishcommand [list $end $prop $id $field $var $subst]
        }
    }

    method image { image } {
        lappend images $image
    }

    method help { prop {text ""} } {
        if {$text ne ""} {
            set propertyopts($prop,help) $text
        }
        return $propertyopts($prop,help)
    }

    method condition { which cond arguments } {
        lappend conditions($which) [list $cond $arguments]
    }

    method properties { {includeStandard 1} } {
        if {$includeStandard} {
            return [lsort $properties]
        } else {
            set props [list]
            foreach prop [eval lremove [list $properties] $standardprops] {
                if {![string equal $propertyopts($prop,type) "hidden"]} {
                    lappend props $prop
                }
            }
            return [lsort $props]
        }
    }

    method type { property } {
        return $propertyopts($property,type)
    }

    method default { property } {
        return $propertyopts($property,value)
    }

    method pretty { property } {
        return $propertyopts($property,pretty)
    }

    method choices { property } {
        return $propertyopts($property,choices)
    }

    method standardproperties {} {
        set list [list ID]
        if {[lsearch -exact $standardprops Component] > -1} {
            lappend list Component
        }
        return [concat $list [lsort [eval lremove [list $standardprops] $list]]]
    }

    method textfields {} {
        return $textfields
    }

    method images {} {
        return $images
    }

    method conditions { which } {
        if {[info exists conditions($which)]} { return $conditions($which) }
    }

    method component {} {
        return "ClassObject"
    }

    method name   { args } { eval cfgvar name   $args }
    method order  { args } { eval cfgvar order  $args }
    method title  { args } { eval cfgvar title  $args }
    method parent { args } { eval cfgvar parent $args }

    public variable order  0
    public variable title  ""
    public variable parent ""

    public  variable help
    public  variable name          ""
    private variable images        [list]
    public  variable properties    [list]
    private variable textfields    [list]
    public  variable standardprops [list]

    private variable conditions
    public  variable propertyopts
}

::itcl::class ::InstallJammer::Action {
    inherit ::InstallJammer::ComponentDetails

    constructor { args } {
        eval configure $args

        set ::InstallJammer::components($name) [namespace tail $this]

        set ::InstallJammer::actions($name) [namespace tail $this]
        lappend ::InstallJammer::actiongroups($group) [namespace tail $this]

        standard Component      readonly   "Component"
        standard Conditions     conditions "Conditions"
        standard Include        choice     "Include"       "Always include" \
            $::InstallJammer::PropertyMap(Include)
        standard IgnoreErrors   boolean    "Ignore Errors" "No"
        standard ExecuteAction  choice     "Execute Action" \
            "After Pane is Displayed" \
            $::InstallJammer::PropertyMap(ExecuteAction)
    }

    destructor {
        unset -nocomplain ::InstallJammer::actions($name)
    }

    method includes { args } {
        if {[llength $args]} { return [eval lappend includes $args] }
        
        variable ::InstallJammer::components

        set list $includes
        foreach include $list {
            eval lappend list [$components($include) includes]
        }

        return $list
    }

    method requires { args } {
        if {[llength $args]} { return [eval lappend requires $args] }

        variable ::InstallJammer::components

        set list $requires
        foreach include [includes] {
            eval lappend list [$components($include) requires]
        }

        return $list
    }

    method group { args } {
        variable ::InstallJammer::actiongroups

        if {[llength $args]} {
            set groupName [lindex $args 0]
            set tail [namespace tail $this]

            set actiongroups($group) [lremove $actiongroups($group) $tail]

            set group $groupName
            lappend actiongroups($group) $tail
        }

        return $group
    }

    method action { args } { eval cfgvar name $args }

    public variable group    ""
    public variable includes [list]
    public variable requires [list]
}

::itcl::class ::InstallJammer::Pane {
    inherit ::InstallJammer::ComponentDetails

    constructor { args } {
        eval configure $args
        set ::InstallJammer::panes($name) [namespace tail $this]

        standard Component  readonly   "Component"
        standard Conditions conditions "Conditions"
        standard Include    choice     "Include"    "Always include" \
            $::InstallJammer::PropertyMap(Include)
    }

    destructor {
        unset -nocomplain ::InstallJammer::panes($name)
    }

    method includes { args } {
        if {[llength $args]} { return [eval lappend includes $args] }
        
        variable ::InstallJammer::panes

        set list $includes
        foreach include $list {
            eval lappend list [$panes($include) includes]
        }

        return $list
    }

    method action { action arguments } {
        lappend actions [list $action $arguments]
    }

    method file { file } {
        lappend files $file
    }

    method actions {} {
        return $actions
    }

    method installtypes {} {
        return $installtypes
    }

    method directories {} {
        global conf
        global info
        global preferences

        lappend dirs [InstallDir Theme/$setup]
        if {[string length $preferences(CustomThemeDir)]} {
            set custom $preferences(CustomThemeDir)
            lappend dirs [::file join $custom $info(Theme) $setup]
        }
        lappend dirs [::file join $conf(pwd) Themes $info(Theme) $setup]
    }

    method deffile { args } {
        if {[llength $args]} { return [eval cfgvar deffile $args] }
        foreach dir [directories] {
            set file [::file join $dir $name.pane]
            if {[::file exists $file]} { return $file }
        }
        return $deffile
    }

    method tclfile { args } {
        if {[llength $args]} { return [eval cfgvar tclfile $args] }
        foreach dir [directories] {
            set file [::file join $dir $name.tcl]
            if {[::file exists $file]} { return $file }
        }
        return $tclfile
    }

    method pane    { args } { eval cfgvar name    $args }
    method setup   { args } { eval cfgvar setup   $args }

    public variable setup        ""
    public variable preview      0
    public variable deffile      ""
    public variable tclfile      ""
    public variable includes     [list]
    public variable installtypes [list Standard]

    private variable files   [list]
    private variable actions [list]
    private variable widgets [list]
}

::itcl::class ::InstallJammer::ActionGroup {
    inherit ::InstallJammer::ComponentDetails

    constructor { args } {
        eval configure $args

        standard Conditions conditions "Conditions"
    }
}

::itcl::class ::InstallJammer::FileGroup {
    inherit ::InstallJammer::ComponentDetails

    constructor { args } {
        eval configure $args

        standard Name              text   "Name"
        standard Size              text   "Size"
        standard CompressionMethod choice "Compression Method" "" \
            [concat {{}} $::conf(CompressionMethods)]
        standard Destination       installedfile "Destination Directory"
        standard DisplayName short "Display Name"
        standard FileUpdateMethod  filemethod "File Update Method" \
            "Update files with more recent dates"
        standard FollowDirLinks boolean "Follow Directory Links" "Yes"
        help FollowDirLinks "If this property is true, links to\
            directories will be followed and their contents stored in the\
            installer as normal files.  If this is false, the directory will\
            be stored as a symlink to be recreated on the target system"
        standard FollowFileLinks   boolean "Follow File Links" "No"
        help FollowFileLinks "If this property is true, links to files will\
            be followed, and the linked file will be stored as an actual file\
            within the installer.  If it is false, a link will be stored and\
            recreated as a link on the target system"
        standard Version           version "Version"
        standard SaveFiles         nullboolean "Save Files" ""
        help SaveFiles "Setting this property to Yes or No overrides the\
            default Save Only Toplevel Directories project preference.  If\
            the property is false, no files or subdirectories of any directory\
            in the file group will be saved in the project file.  Only\
            directories which are toplevel directories in the file group\
            will be saved"

        standard FileSize          hidden "File Size"
        standard Attributes        hidden "Windows File Attributes"
        standard Permissions       hidden "File Permissions"
    }
}

::itcl::class ::InstallJammer::Component {
    inherit ::InstallJammer::ComponentDetails

    constructor { args } {
        eval configure $args

        standard Name              text    "Name"
        standard Size              text    "Size"
        standard Checked           boolean "Checked"            "Yes"
        standard FileGroups        hidden  "File Groups"
        standard Selectable        boolean "Selectable"         "Yes"
        standard ShowComponent     boolean "Show Component"     "Yes"
        standard ComponentGroup    text    "Component Group"
        standard RequiredComponent boolean "Required Component" "No"

        text Description "Description"  1
        text DisplayName "Display Name" 1
    }
}

::itcl::class ::InstallJammer::SetupType {
    inherit ::InstallJammer::ComponentDetails

    constructor { args } {
        eval configure $args

        standard Name          text    "Name"
        standard Components    hidden  "Components"
        standard ShowSetupType boolean "Show Setup Type"     "Yes"

        text Description "Description"  1
        text DisplayName "Display Name" 1
    }
}

::itcl::class ::InstallJammer::File {
    inherit ::InstallJammer::ComponentDetails

    constructor { args } {
        eval configure $args

        standard CompressionMethod choice "Compression Method" "" \
            [concat {{}} $::conf(CompressionMethods)]
        standard Destination       installedfile "Destination Directory"
        standard FileUpdateMethod  filemethod "File Update Method" \
            "Update files with more recent dates"
        standard Version           version "Version"
        standard Location          location "Location"
        standard TargetFilename    short "Target Filename"
        standard SaveFiles         nullboolean "Save Files"
        help SaveFiles "Setting this property to Yes or No overrides the\
            default Save Only Toplevel Directories project preference.  If\
            the property is false, no files or subdirectories of any directory\
            in the file group will be saved in the project file.  Only\
            directories which are toplevel directories in the file group\
            will be saved"
    }
}

::itcl::class ::InstallJammer::Condition {
    inherit ::InstallJammer::ComponentDetails

    constructor { args } {
        eval configure $args

        standard Component      readonly  "Component"
        standard CheckCondition choice    "Check Condition" \
            "Before Pane is Displayed" $::conf(PaneCheckConditions)

        standard FailureFocus   text "Failure Focus"
        help FailureFocus "A widget to move the focus to after the failure\
                                message has been displayed."

        standard FailureMessage text "Failure Message"
        help FailureMessage "A message to display to the user if this conditon\
                                fails."

        standard Include choice "Include" "Always include" \
            $::InstallJammer::PropertyMap(Include)

        set ::InstallJammer::components($name) [namespace tail $this]

        set ::InstallJammer::conditions($name) [namespace tail $this]
        lappend ::InstallJammer::conditiongroups($group) [namespace tail $this]
    }

    destructor {
        unset -nocomplain ::InstallJammer::conditions($name)
    }

    method group { args } {
        variable ::InstallJammer::conditiongroups

        if {[llength $args]} {
            set groupName [lindex $args 0]
            set tail [namespace tail $this]

            set conditiongroups($group) [lremove $conditiongroups($group) $tail]

            set group $groupName
            lappend conditiongroups($group) $tail
        }

        return $group
    }

    method includes { args } {
        if {[llength $args]} { return [eval lappend includes $args] }
        
        variable ::InstallJammer::components

        set list $includes
        foreach include $list {
            eval lappend list [$components($include) includes]
        }

        return $list
    }

    method condition { args } { eval cfgvar name $args }

    public variable group     ""
    public variable includes  [list]
}

::itcl::class Platform {
    inherit InstallComponent

    constructor { args } {
        eval configure $args
    } {
        eval configure $args
        ::set type platform

        set Active                "NEW"
        set BuildSeparateArchives "No"
        set InstallMode           "Standard"
        set InstallType           "Typical"
        set ProgramName           ""
        set ProgramReadme         "<%InstallDir%>/README.txt"
        set ProgramLicense        "<%InstallDir%>/LICENSE.txt"
        set ProgramFolderName     "<%AppName%>"
        set ProgramExecutable     ""
        set ProgramFolderAllUsers "No"

        if {$name eq "windows"} {
            set Executable   "<%AppName%>-<%Version%>-Setup<%Ext%>"
            set FileDescription "<%AppName%> <%Version%> Setup"
            set InstallDir   "<%PROGRAM_FILES%>/<%AppName%>"
            set WindowsIcon  "Setup Blue Screen.ico"
            set IncludeTWAPI "No"
            set RequireAdministrator "Yes"
            set UseUncompressedBinaries "No"
            set LastRequireAdministrator "Yes"
        } else {
            set Executable "<%AppName%>-<%Version%>-<%Platform%>-Install<%Ext%>"
            set InstallDir "<%Home%>/<%ShortAppName%>"

            set PromptForRoot  "Yes"

            set RequireRoot    "No"
            set RootInstallDir "/usr/local/<%ShortAppName%>"

            set DefaultFilePermission      "0755"
            set DefaultDirectoryPermission "0755"

            set FallBackToConsole "Yes"
        }
    }

    method initialize {} {}

    method object {} {
        return ::PlatformObject
    }
} ; ## ::itcl::class Platform
Added lib/cmdline.tcl.






























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc CheckRunStatus {} {
    global conf

    if {!$conf(cmdline)} {
        if {![info exists ::tk_patchLevel]} {
            puts "InstallJammer must be run in a graphical environment."
            exit 1
        }

        return
    }

    ## We're running in command-line mode.

    ::InstallJammer::CommonInit

    if {$conf(windows)} {
        ## Windows needs to load BWidgets for the message dialogs.
        package require BWidget 2.0
        BWidget::use png
        BWidget::use ttk
        set ::BWidget::iconLibrary InstallJammerIcons
        SetIconTheme
    }

    ## Open the file passed in.
    Open [lindex $::argv end]

    ## Build the installer.
    ::InstallJammer::CommandLineBuild
}

## ::InstallJammer::CommandLineBuild
##
##    Do a little bit of setup before calling the InstallJammer Build
##    procedure.
##
proc ::InstallJammer::CommandLineBuild {} {
    global conf
    global info

    ::Build

    if {$conf(buildAndTest)} {
        set platform       [::InstallJammer::Platform]
        set info(Platform) $platform

        set executable [::InstallJammer::SubstText [$platform get Executable]]
        set executable [InstallDir output/$executable]
	if {![file exists $executable]} {
            ::InstallJammer::Message -title Error \
                -message "Could not find install executable to test."
	} else {
	    if {!$conf(silent)} {
                set msg "Testing $executable"
                if {$conf(testInTestMode)} {
                    append msg " without installing files"
                }
                append msg "..."
                BuildLog $msg
            }

            if {$conf(testInTestMode)} {
                exec $executable --test &
            } else {
                exec $executable &
            }
	}
    }

    ::exit [expr {$conf(totalBuildErrors) > 0}]
}
Added lib/commandline.tcl.




















































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::InstallJammer::AddDefaultCommandLineOptions {} {
    SafeArraySet ::InstallJammer::InstallCommandLineOptions {
        debug { Debugging Switch Yes No {}
            "run installer in debug mode"
        }

        debugconsole { ShowConsole Switch Yes No {}
            "run installer with a debug console open"
        }

        mode { InstallMode Choice No No {Console Default Silent Standard}
            "set the mode to run the installer in"
        }

        test { Testing Switch Yes No {}
            "run installer without installing any files"
        }

        prefix { InstallDir String No No {}
            "set the installation directory"
        }
    }

    SafeArraySet ::InstallJammer::UninstallCommandLineOptions {
        debug { Debugging Switch Yes No {}
            "run uninstaller in debug mode"
        }

        debugconsole { ShowConsole Switch Yes No {}
            "run uninstaller with a debug console open"
        }

        mode { UninstallMode Choice No No {Console Silent Standard}
            "set the mode to run the uninstaller in"
        }

        test { Testing Switch Yes No {}
            "run uninstaller without uninstalling any files"
        }
    }
}

proc ::InstallJammer::ClearCommandLineOptions {} {
    global widg

    unset -nocomplain ::InstallJammer::InstallCommandLineOptions
    unset -nocomplain ::InstallJammer::UninstallCommandLineOptions

    $widg(InstallCommandLineOptionsTable)   clear
    $widg(UninstallCommandLineOptionsTable) clear
}

proc ::InstallJammer::LoadCommandLineOptions {} {
    global widg

    if {[info exists widg(InstallCommandLineOptionsTable)]} {
        variable ::InstallJammer::InstallCommandLineOptions

        set table $widg(InstallCommandLineOptionsTable)

        $table clear

        foreach option [lsort [array names InstallCommandLineOptions]] {
            set values [list $option]
            foreach x $InstallCommandLineOptions($option) {
                lappend values $x
            }
            $table insert end root #auto -values $values
        }
    }

    if {[info exists widg(UninstallCommandLineOptionsTable)]} {
        variable ::InstallJammer::UninstallCommandLineOptions

        set table $widg(UninstallCommandLineOptionsTable)

        $table clear

        foreach option [lsort [array names UninstallCommandLineOptions]] {
            set values [list $option]
            foreach x $UninstallCommandLineOptions($option) {
                lappend values $x
            }
            $table insert end root #auto -values $values
        }
    }
}

proc ::InstallJammer::GetCommandLineOptionData { args } {
    global widg

    array set _args {
        -build        0
        -includedebug 1
    }
    array set _args $args

    if {![info exists _args(-setup)]} {
        return -code error "must specify -setup"
    }

    set setup $_args(-setup)

    upvar #0 ::InstallJammer::${setup}CommandLineOptions options

    if {[info exists widg(${setup}CommandLineOptionsTable)]} {
        set table $widg(${setup}CommandLineOptionsTable)
        foreach row [eval [list $table get items] [$table items root]] {
            set debug [lindex $row 3]
            if {!$_args(-includedebug) && $debug} { continue }
            set CommandLineOptions([lindex $row 0]) [lrange $row 1 end]
        }
    } else {
        foreach option [array names options] {
            set debug [lindex $options($option) 2]
            if {!$_args(-includedebug) && $debug} { continue }
            set CommandLineOptions($option) $options($option)
        }
    }

    if {$_args(-build)} {
        return [ReadableArrayGet CommandLineOptions \
                    ::InstallJammer::CommandLineOptions]
    } else {
        return [ReadableArrayGet CommandLineOptions \
                    ::InstallJammer::${setup}CommandLineOptions]
    }
}

proc ::InstallJammer::NewCommandLineOption { table } {
    ## Option VirtualText Type Debug Hide Values Description
    set values [list {} {} "Switch" "No" "No" {} {}]

    set item [$table insert end root #auto -values $values]

    $table see item $item
    $table edit start $item 0

    Modified
}

proc ::InstallJammer::DeleteCommandLineOption { table } {
    eval [list $table delete] [$table selection get]
    Modified
}

proc ::InstallJammer::EditStartCommandLine { table item col } {
    return 1
}

proc ::InstallJammer::EditFinishCommandLine { table item col } {
    variable ::InstallJammer::CommandLineOptions

    if {$col == 0} {
        set old [$table get value $item 0]
        set new [string trimleft [string trim [$table edit editvalue]] /-]

        set options [lsearch -all -exact [$table get col 0] $new]
        if {$new ne $old && [llength $options] > 0} {
            ::InstallJammer::Error -message \
                "An option with that name already exists."
            $table edit cancel
            return 1
        }

        $table edit editvalue $new
    }

    return 1
}

proc ::InstallJammer::EditCommandLineOptionChoices { table item } {
    set ::TMP [$table edit editvalue]

    ::editor::new -title "Editing Command Line Option Choices" -variable ::TMP

     $table edit editvalue [string trim $::TMP]
     ClearTmpVars

     set entry [$table edit entrypath]
     $entry selection range 0 end
     after idle [list focus $entry]
}

proc ::InstallJammer::EditCommandLineOptionDescription { table item } {
    set ::TMP [$table edit editvalue]
    ::editor::new -title "Editing Command Line Option Description" \
        -variable ::TMP
    $table edit editvalue [string trim $::TMP]
    ClearTmpVars

    set entry [$table edit entrypath]
    $entry selection range 0 end
    after idle [list focus $entry]
}
Added lib/common.tcl.










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

namespace eval ::InstallAPI {}
namespace eval ::InstallJammer {}
namespace eval ::InstallJammer::subst {}

rename ::source ::tcl_source
proc source {args} {
    if {[llength $args] == 1} {
        uplevel 1 [list ::tcl_source [lindex $args 0]]
    } elseif {[llength $args] == 3 && [lindex $args 0] eq "-encoding"} {
        set enc [encoding system]
        encoding system [lindex $args 1]
        uplevel 1 [list ::tcl_source [lindex $args 2]]
        encoding system $enc
    } else {
        return -code error \
            {wrong # args: should be "source ?-encoding encodingName? fileName"}
    }
}

proc lempty { list } {
    if {[catch {expr [llength $list] == 0} ret]} { return 0 }
    return $ret
}

proc lassign { list args } {
    foreach elem $list varName $args {
    	upvar 1 $varName var
	set var $elem
    }
}

proc lremove { list args } {
    foreach arg $args {
	set x [lsearch -exact $list $arg]
        if {$x > -1} { set list [lreplace $list $x $x] }
    }
    return $list
}

proc lreverse { list } {
    set new [list]
    set len [llength $list]
    for {set i [expr $len - 1]} {$i >= 0} {incr i -1} {
	lappend new [lindex $list $i]
    }
    return $new
}

proc lassign_array {list arrayName args} {
    upvar 1 $arrayName array
    foreach elem $list var $args {
	set array($var) $elem
    }
}

proc incr0 { varName {n 1} } {
    upvar 1 $varName var
    if {![info exists var]} { set var 0 }
    set var [expr {wide($var) + $n}]
}

proc iincr { varName {n 1} } {
    upvar 1 $varName var
    if {![info exists var]} { set var 0 }
    set var [expr {$var + $n}]
}

proc patheq {path1 path2} {
    global conf

    set path1 [::InstallJammer::Normalize $path1]
    set path2 [::InstallJammer::Normalize $path2]
    if {$conf(windows)} { return [string equal -nocase $path1 $path2] }
    return [string equal $path1 $path2]
}

proc recursive_glob {dir pattern} {
    set files [glob -nocomplain -type f -dir $dir $pattern]
    foreach dir [glob -nocomplain -type d -dir $dir *] {
        eval lappend files [recursive_glob $dir $pattern]
    }
    return $files
}

proc noop {args} {}

proc open_text {file {mode "r"} args} {
    set fp [open $file $mode]
    eval fconfigure $fp $args

    if {![catch {fileevent $fp readable}]} {
        ## Look for an options: line followed by a blank line.
        gets $fp line
        if {[string match "# options: -*" $line] && [gets $fp] eq ""} {
            eval fconfigure $fp [lrange $line 2 end]
        } else {
            seek $fp 0 start
        }
    }

    if {[llength $args] && ![catch {fileevent $fp writable}]} {
        puts $fp "# options: $args"
        puts $fp ""
    }

    return $fp
}

proc read_file { file args } {
    set fp [open $file]
    eval [list fconfigure $fp] $args
    set x [read $fp]
    close $fp
    return $x
}

proc read_textfile {file args} {
    set fp [eval open_text [list $file] $args]
    set x [read $fp]
    close $fp
    return $x
}

proc verbose {} {
    if {[info exists ::verbose]} { return $::verbose }
    return 0
}

proc debugging { {value ""} {level ""} {file ""} } {
    if {$value eq "state"} {
        if {$::debug || $::info(Debugging)} { return 1 }
        return 0
    } elseif {[string is true -strict $value]} {
        if {$level eq "" || $level eq "console"} {
            set ::debug 1
        } elseif {$level eq "file"} {
            set ::info(Debugging) 1
            if {$file eq ""} {
                set file [::InstallJammer::TmpDir debug.log]
            }
            if {[info exists ::debugfp]} {
                catch { close $::debugfp }
                set ::debugfp ""
            }
            set ::info(DebugLog) $file
            set ::debugfp [open $file w]
        } else {
            return -code error "bad debugging option \"$level\":\
                should be console or file"
        }
    } elseif {[string is false -strict $value]} {
        if {$level eq ""} {
            set ::debug 0
            set ::info(Debugging) 0
            if {[info exists ::debugfp]} {
                catch { close $::debugfp }
                set ::debugfp ""
            }
        } elseif {$level eq "console"} {
            set ::debug 0
        } elseif {$level eq "file"} {
            set ::info(Debugging) 0
            if {[info exists ::debugfp]} {
                catch { close $::debugfp }
                set ::debugfp ""
            }
        }
    } elseif {$value eq "level"} {
        if {$level eq ""} {
            if {!$::debug} { return 0 }
            return [expr {$::verbose + 1}]
        } else {
            if {$level < 0 || $level > 3} {
                return -code error "invalid debug level \"$level\":\
                    should be 0, 1, 2 or 3"
            }

            if {$level == 0} {
                set ::debug "off"
                set ::info(Debugging) 0
            } else {
                set ::debug "on"
                set ::info(Debugging) 1
                set ::verbose [incr level -1]
            }
        }
    } elseif {$value ne ""} {
        return -code error "usage: debugging ?on|off? ?file|console? ?logfile?"
    }

    if {$::debug || $::info(Debugging)} {
        echo "Debugging is turned on"
    } else {
        echo "Debugging is turned off"
    }
    if {$::debug} {
        echo "Debug output is being written to the console"
    }
    if {$::info(Debugging)} {
        echo "Debug output is being saved to a debug log file"
        echo "Debug log file is <%DebugLog%>" 1
    }
}

proc debug { message {id ""} } {
    global info

    ## We don't output debugging in the builder.
    if {[info exists ::InstallJammer]} { return }

    if {![string is true -strict $::debug]
        && ![string is true -strict $info(Debugging)]} { return }

    set time [clock format [clock seconds] -format "%m/%d/%Y %H:%M:%S%p"]
    set string "$time - $message"

    if {[set x [::InstallJammer::SubstText $message]] ne $message} {
        append string "\n$time - ** $x"
    }

    if {$id ne "" && [$id get Comment comment] && $comment ne ""} {
        append string "\n$time - # $comment"
        if {[set x [::InstallJammer::SubstText $comment]] ne $comment} {
            append string "\n$time - ** $x"
        }
    }

    if {![info exists ::InstallJammer]} {
        if {[string is true -strict $::debug]} {
            puts  stderr $string
            flush stderr
        }

        if {[string is true -strict $info(Debugging)]} {
            if {![info exists ::debugfp]} {
                set ::debugfp [open [::InstallJammer::TmpDir debug.log] w]
            } elseif {$::debugfp eq ""} {
                set ::debugfp [open [::InstallJammer::TmpDir debug.log] a]
            }

            puts  $::debugfp $string
            flush $::debugfp
        }
    }
}

proc threaded {} {
    global conf

    if {![info exists conf(threaded)]} {
        set conf(threaded) [info exists ::tcl_platform(threaded)]
        if {$conf(threaded)} {
            package require Thread
            if {[catch {thread::send [thread::id] #}]} { set conf(threaded) 0 }
        }
    }
    return $conf(threaded)
}

proc ::echo { string {subst 0} } {
    if {$subst} { set string [::InstallJammer::SubstText $string] }
    puts  stdout $string
    flush stdout
}

proc ::more { args } {
    global conf

    if {[expr {[llength $args] % 2}]} {
        set text [lindex $args end]
        set args [lrange $args 0 end-1]
    }

    array set _args {
        -file      ""
        -width     0
        -height    0
        -allowquit 1
    }
    array set _args $args

    if {$_args(-file) ne ""} {
        set text [read_file $_args(-file)]
    }

    set height $_args(-height)
    if {$height == 0} {
        set height 24
        if {[info exists conf(ConsoleHeight)]} {
            set height $conf(ConsoleHeight)
        } else {
            if {![catch { exec stty size } result]} {
                set height [lindex $result 0]
            }
        }
    }

    incr height -1

    if {$_args(-width) > 0} {
        set text [::InstallJammer::WrapText $text $_args(-width)]
    }

    catch { exec stty raw -echo <@stdin }

    if {!$_args(-allowquit)} {
        set prompt [::InstallJammer::SubstText "<%ConsolePauseText%>"]
    } else {
        set prompt [::InstallJammer::SubstText "<%ConsolePauseQuitText%>"]
    }

    catch { 
        set i 0
        foreach line [split $text \n] {
            puts stdout $line

            if {[incr i] >= $height} {
                puts -nonewline stdout $prompt
                flush stdout

                while {1} {
                    set x [read stdin 1]
                    if {$_args(-allowquit) && $x eq "q" || $x eq "Q"} {
                        return
                    } elseif {$x eq " "} {
                        break
                    }
                }

                puts  stdout ""
                flush stdout

                set i 0
            }
        }
    }

    catch { exec stty -raw echo <@stdin }

    return
}

proc ::tk_safeDialog {command opts safeOpts} {
    set args {}
    array set _args $opts
    foreach opt $safeOpts {
        if {[info exists _args($opt)]} {
            if {$opt eq "-parent" && ![winfo exists $_args($opt)]} { continue }
            if {$opt eq "-initialdir" && ![file exists $_args($opt)]} {continue}
            lappend args $opt $_args($opt)
        }
    }
    return [eval $command $args]
}

proc ::ij_chooseDirectory {args} {
    ::tk_safeDialog ::tk_chooseDirectory $args \
        {-initialdir -mustexist -parent -title}
}

proc ::ij_getOpenFile {args} {
    ::tk_safeDialog ::tk_getOpenFile $args \
        {-defaultextension -filetypes -initialdir -initialfile \
              -message -multiple -parent -title -typevariable}
}

proc ::ij_getSaveFile {args} {
    ::tk_safeDialog ::tk_getSaveFile $args \
        {-defaultextension -filetypes -initialdir -initialfile \
              -message -multiple -parent -title -typevariable}
}

if {[info exists ::conf(unix)] && $::conf(unix)} {
    ## Repace the core Tk get file dialogs with our own that looks nicer.
    proc ::tk_getOpenFile { args } {
        return [eval ChooseFile .__tk_getOpenFile $args -type open]
    }

    proc ::tk_getSaveFile { args } {
        return [eval ChooseFile .__tk_getSaveFile $args -type save]
    }

    proc ::tk_messageBox { args } {
        return [eval ::InstallJammer::MessageBox $args]
    }
}

proc SafeSet { varName value } {
    upvar 1 $varName var
    if {![info exists var]} { set var $value }
    return $value
}

proc SafeArraySet { arrayName list } {
    upvar 1 $arrayName array
    foreach {varName elem} $list {
	if {![info exists array($varName)]} { set array($varName) $elem }
    }
}

package require msgcat

## We're going to redefine some of Tcl's msgcat commands in the
## name of simplifying things.
proc ::msgcat::mc { src args } {
    foreach loc [::msgcat::mcpreferences] {
        if {[info exists ::msgcat::Msgs_${loc}($src)]} { break }
    }
    return [eval [list ::msgcat::mcget $loc $src] $args]
}

proc ::msgcat::mcexists { src {locales {}} } {
    if {![llength $locales]} {
        set locales [::msgcat::mcpreferences]
    }
    foreach locale $locales {
        if {$locale eq "None"} {
            upvar #0 ::info msgs
        } else {
            upvar #0 ::msgcat::Msgs_${locale} msgs
        }

        if {[info exists msgs($src)]} { return 1 }
    }
    return 0
}

proc msgcat::mclocale { args } {
    variable Locale
    variable Loclist

    if {[llength $args] == 1 && [lindex $args 0] eq ""} {
        set Loclist {}
        return
    }

    if {[llength $args]} {
        foreach locale $args {
            set loc  {}
            set word ""
            foreach part [split [string tolower $locale] _] {
                set word [string trimleft "${word}_${part}" _]
                if {[set x [lsearch -exact $Loclist $word]] > -1} {
                    set Loclist [lreplace $Loclist $x $x]
                }
                set Loclist [linsert $Loclist 0 $word]
            }
        }
        set Locale $locale
    }
    return $Locale
}

proc ::msgcat::mcset { locale src {dest ""} } {
    if {$locale eq "None"} {
        upvar #0 ::info msgs
    } else {
        upvar #0 ::msgcat::Msgs_${locale} msgs
    }

    if {[llength [info level 0]] == 3} { set dest $src }
    set msgs($src) $dest
}

proc ::msgcat::mcunset { locale src } {
    if {$locale eq "None"} {
        upvar #0 ::info msgs
    } else {
        upvar #0 ::msgcat::Msgs_${locale} msgs
    }

    array unset msgs $src
}

proc ::msgcat::mcmset { locale pairs } {
    if {$locale eq "None"} {
        upvar #0 ::info msgs
    } else {
        upvar #0 ::msgcat::Msgs_${locale} msgs
    }

    array set msgs $pairs
}

proc ::msgcat::mcgetall { locale } {
    if {$locale eq "None"} {
        upvar #0 ::info msgs
    } else {
        upvar #0 ::msgcat::Msgs_${locale} msgs
    }

    return [array get msgs]
}

proc ::msgcat::mcget { locale src args } {
    if {$locale eq "None"} {
        upvar #0 ::info msgs
    } else {
        upvar #0 ::msgcat::Msgs_${locale} msgs
    }

    if {![info exists ::msgcat::renderer($locale)]} {
        set ::msgcat::renderer($locale) \
            [expr {[info commands ::${locale}::render] ne ""}]
    }

    if {[info exists msgs($src)]} {
        set src $msgs($src)

        if {$::msgcat::renderer($locale)} {
            set src [::${locale}::render $src]
        }
    }

    if {[llength $args]} {
        return [uplevel 1 [linsert $args 0 ::format $src]]
    } else {
        return $src
    }
}

proc ::msgcat::mcclear { locale } {
    unset -nocomplain ::msgcat::Msgs_${locale}
}

## Procs for testing

proc inject {cmd args} {
    variable ::InstallJammer::tests

    switch -- $cmd {
        "before" - "after" {
            lassign $args id script
            set id [::InstallJammer::ID $id]
            lappend tests($cmd,$id) $script
        }

        "enter" - "leave" {
            lassign $args proc script
            trace add exec $proc $cmd [list inject run $script] }

        "run" {
            set test [lindex $args 0]
            if {[info exists tests($test)]} {
                foreach script $tests($test) {
                    uplevel #0 $script
                }
            } else {
                uplevel #0 $test
            }
        }
    }
}

proc test_pressButton {button} {
    set found 0
    foreach top [::InstallJammer::Grab stack] {
        foreach w [::InstallJammer::GetAllWidgets $top] {
            set c [winfo class $w]
            if {$c eq "Button" || $c eq "TButton"} {
                if {[$w cget -text] eq $button} {
                    set found 1
                    $w invoke
                    break
                }
            }
        }
        if {$found} { break }
    }
}

namespace eval ::InstallJammer {}
namespace eval ::InstallJammer::actions {}
namespace eval ::InstallJammer::conditions {}

proc ::InstallJammer::CommonInit {} {
    global info
    global conf

    if {[info exists conf(commonInit)]} { return }

    set conf(osx)       [string equal $::tcl_platform(os) "Darwin"]
    set conf(unix)      [string equal $::tcl_platform(platform) "unix"]
    set conf(windows)   [string equal $::tcl_platform(platform) "windows"]
    set conf(windows98) [expr {$conf(windows)
                           && $::tcl_platform(osVersion) < 5.0}]
    set conf(vista)     [expr {$conf(windows)
                           && $::tcl_platform(osVersion) >= 6.0}]
    set conf(wine)      [expr {$conf(windows) && [info exists ::env(_)]
                         && [file tail $::env(_)] eq "wine"}]

    array set conf {
	commonInit   1

        logInit      0

        ExitCode     ""

        ObjectStack   {}
        ParentWindow  {}
        UpdateWidgets {}
        ButtonWidgets {BackButton NextButton CancelButton}

        UserRCFiles {~/.bashrc ~/.cshrc ~/.tcshrc ~/.zshrc ~/.kshrc ~/.profile}
        SystemRCFiles {/etc/bashrc /etc/csh.cshrc /etc/zshrc /etc/profile}

        ShowConsoleProgress 1

        UpdateWindowsRegistry 0

        ModifySelectedComponents 1

        ComponentTrees  {}
        SetupTypeTrees  {}

        SaveResponseVars {
            "CreateDesktopShortcut boolean"
            "CreateQuickLaunchShortcut boolean"
            "InstallDir string"
            "InstallMode string"
            "InstallType string"
            "LaunchApplication boolean"
            "ProgramFolderName string"
            "SelectedComponents list"
            "ViewReadme boolean"
        }

        VirtualTextMap            {}
	VirtualTextRecursionLimit 10
    }

    lappend conf(VirtualTextMap) "\\" "\\\\" "\[" "\\\["
    lappend conf(VirtualTextMap) "<%" {[::InstallJammer::SubstVar [list }
    lappend conf(VirtualTextMap) "%>" {]]}

    if {[info exists ::installkit::root]} {
        set conf(vfs) $::installkit::root
    }
    set conf(exe)      [info nameofexecutable]
    set conf(script)   [info script]

    if {$conf(windows)} {
        set info(Ext)       ".exe"
        set info(ScriptExt) ".bat"
    } else {
        set info(Ext)       ""
        set info(ScriptExt) ".sh"
    }

    array set ::InstallJammer::PropertyMap {
        Include {
            "Always include"
            "Include only when testing"
            "Include only when not testing"
        }

        ExecuteAction {
            "After Pane is Cancelled"
            "After Pane is Displayed"
            "After Pane is Finished"
            "Before Next Pane is Displayed"
            "Before Pane is Cancelled"
            "Before Pane is Displayed"
            "Before Pane is Finished"
            "Before Previous Pane is Displayed"
        }

        FileUpdateMethod {
            "Update files with more recent dates"
            "Update files with a newer version"
            "Always overwrite files"
            "Never overwrite files"
        }

        CheckCondition {
            "After Pane is Cancelled"
            "Before Next Pane is Displayed"
            "Before Pane is Cancelled"
            "Before Pane is Displayed"
            "Before Pane is Finished"
            "Before Previous Pane is Displayed"
            "Before Action is Executed"
            "Before Next Action is Executed"
        }
    }

    ## Append some default directories to the PATH so that
    ## we can find tools we're looking for even if the user
    ## running the installer doesn't include these directoris.
    if {!$conf(windows)} {
        append ::env(PATH) ":/bin:/sbin:/usr/bin:/usr/sbin"
        append ::env(PATH) ":/usr/local/bin:/usr/local/sbin"

        ## Include KDE4 paths to get kdesu.
        append ::env(PATH) ":/usr/lib/kde4/libexec"
        append ::env(PATH) ":/usr/lib64/kde4/libexec"
    }

    ::InstallJammer::InitializeMessageCatalogs

    set conf(NativeChooseFile)       [expr {!$conf(unix)}]
    set conf(NativeMessageBox)       [expr {!$conf(unix)}]
    set conf(NativeChooseDirectory)  [expr {!$conf(unix)}]

    msgcat::Init
    if {[info exists ::InstallJammer]} {
        msgcat::mclocale en
    } else {
        ## Running from an installer or uninstaller

        ## Setup common variables for an install or uninstall.
        set ::debug "off"

        array set conf {
            ConsoleWidth      80
            ConsoleHeight     24
            NativeMessageBox  0
            panesToSkip       {}
        }
        set conf(NativeChooseDirectory) $conf(osx)

        SafeArraySet conf {
            twapi               0
            Wow64Disabled       0
        }

        array set info {
            Wizard             .wizard
            WizardFirstStep    0
            WizardLastStep     0
            WizardStarted      0
            WizardFinished     0
            WizardCancelled    0

	    Errors             ""

            SilentMode         0
            DefaultMode        0

            UserMovedBack      0
            UserMovedNext      0

            ShowConsole        0

            Debugging          0
            Testing            0
        }

	SafeArraySet info {
            AllowLanguageSelection 1
            PromptForRoot          1

            Language                "en"
            DefaultToSystemLanguage "Yes"

            InstallMode            "Standard"
            UninstallMode          "Standard"

            FallBackToConsole      0

            InstallVersionInfo     1
            InstallRegistryInfo    1

            RunningInstaller       0
            RunningUninstaller     0

            SpaceRequiredText      "<%DiskSpace <%SpaceRequired%>%>"
            SpaceAvailableText     "<%DiskSpace <%SpaceAvailable%>%>"
	}

        set info(Home) [::InstallJammer::HomeDir]

        if {$info(RunningInstaller)} {
            if {[info exists info(DefaultLanguage)]} {
                set info(Language) [GetLanguageCode $info(DefaultLanguage)]
            }

            set info(SystemLanguage) [::msgcat::mclocale]
            set codes [::InstallJammer::GetLanguageCodes]
            foreach lang [::msgcat::mcpreferences] {
                if {[lsearch -exact $codes $lang] > -1} {
                    set info(SystemLanguage) $lang
                    if {$info(DefaultToSystemLanguage)} {
                        set info(Language) $lang
                    }
                    break
                }
            }

            set info(InstallStartupDir) [pwd]
        } elseif {$info(RunningUninstaller)} {
            set info(UninstallStartupDir) [pwd]
        }

        if {$conf(windows)} {
            set info(Username)      $::tcl_platform(user)
            set info(PathSeparator) \;

            set info(Desktop) <%DESKTOP%>

            ::InstallJammer::SetWindowsPlatform
            ::InstallJammer::SetupRegVirtualText
        } else {
            set info(Username)        [id user]
            set info(PathSeparator)   :
            set info(HasKDEDesktop)   [::InstallJammer::HasKDEDesktop]
            set info(HasGnomeDesktop) [::InstallJammer::HasGnomeDesktop]

            switch -- [::InstallJammer::GetDesktopEnvironment] {
                "KDE" {
                    set info(Desktop) <%KDEDesktop%>
                }

                "Gnome" {
                    set info(Desktop) <%GnomeDesktop%>
                }
            }

            set info(HaveTerminal) [expr {[catch { exec tty }] == 0}]
        }

        if {[info exists info(Language)]} {
            ::InstallAPI::LanguageAPI -do setlanguage -language $info(Language)
        }

        set info(UserIsRoot)   [string equal $info(Username) "root"]
        set info(RealUsername) $::tcl_platform(user)

        ## Setup <%Status%> to automatically update the screen when modified.
        ::InstallAPI::SetVirtualText -virtualtext Status -value "" -autoupdate 1

        ## Call a command when <%InstallDir%> is modified.
        ::InstallAPI::SetVirtualText -virtualtext InstallDir \
            -command ::InstallJammer::ModifyInstallDir

        ## Change the main window title when <%InstallTitleText%> is changed.
        ::InstallAPI::SetVirtualText -virtualtext Language \
            -command ::InstallJammer::ModifyInstallTitle
        ::InstallAPI::SetVirtualText -virtualtext InstallTitleText \
            -command ::InstallJammer::ModifyInstallTitle
        ::InstallAPI::SetVirtualText -virtualtext InstallTitleText \
            -language all -command ::InstallJammer::ModifyInstallTitle

        ::InstallAPI::VirtualTextAPI -do settype -type directory -virtualtext {
	    CommonStartMenu
            Desktop
            FileBeingInstalled
	    GnomeCommonStartMenu
	    GnomeDesktop
	    GnomeStartMenu
	    Home
	    InstallDir
	    Installer
	    InstallLogDirectory
	    InstallSource
	    KDECommonStartMenu
	    KDEDesktop
	    KDEStartMenu
            ProgramReadme
            ProgramLicense
	    ProgramExecutable
	    ProgramFolder
	    Uninstaller
	    UninstallDirectory
	}
    }

    SafeArraySet info {
        Date            "<%Date <%DateFormat%>%>"
        DateFormat      "%Y%m%d"
    }
}

proc ::InstallJammer::CommonPostInit {} {
    global conf
    global info

    set conf(stop)  [::InstallJammer::TmpDir .stop]
    set conf(pause) [::InstallJammer::TmpDir .pause]

    if {[info exists conf(vfs)]} {
        set bin    [file join $conf(vfs) lib bin]
        set tmpbin [::InstallJammer::TmpDir bin]
        if {[file exists $bin] && ![file exists $tmpbin]} {
            set ::env(PATH) "$tmpbin$info(PathSeparator)$::env(PATH)"
            file copy -force $bin $tmpbin
            if {!$conf(windows)} {
                foreach file [glob -dir $tmpbin *] {
                    file attributes $file -permissions 0755
                }
            }
        }
    }
}

proc ::InstallJammer::InitializeGui {} {
    global conf
    global info

    if {[info exists ::InstallJammer]} { return }
    if {[info exists conf(InitializeGui)]} { return }
    set conf(InitializeGui) 1

    SourceCachedFile gui.tcl
    InitGui

    ## InitGui might fail because Tk cannot be loaded or because
    ## we don't have a DISPLAY to display to.  If that happens,
    ## we don't want to keep going with the rest of the init.
    if {!$info(GuiMode)} { return }

    set key Control
    if {$conf(osx)} { set key Command }

    bind Text <$key-a>   "%W tag add sel 1.0 end"
    bind Text <$key-Tab> [bind Text <Tab>]
    bind Text <Tab> "# nothing"
    bind Text <Shift-Tab> ""

    wm protocol $info(Wizard) WM_DELETE_WINDOW ::InstallJammer::CloseButton
}

proc ::InstallJammer::CloseButton {} {
    global info

    if {[grab current] eq "" || [grab current] eq $info(Wizard)} {
        $info(Wizard) cancel 1
    }
}

proc ::InstallJammer::InitializeMessageCatalogs {} {
    global conf
    global info

    variable languages
    variable languagecodes

    if {[info exists ::InstallJammer]} {
        set langfile [file join $conf(lib) msgs languages.txt]
        if {[file exists $langfile]} {
            array set ::InstallJammer::languagecodes [read_file $langfile]
        }
    }

    if {![array exists languagecodes]} {
        array set languagecodes {
            de      "German"
            en      "English"
            es      "Spanish"
            fr      "French"
            pl      "Polish"
            pt_br   "Brazilian Portuguese"
        }
    }

    if {[info exists info(Languages)]} {
        array set languagecodes $info(Languages)
    }

    foreach var [array names languagecodes] {
        set languages($languagecodes($var)) $var
    }
    set languages(None) None

    return [lsort [array names languagecodes]]
}

proc ::InstallJammer::GetLanguageCode { lang } {
    set lang [string tolower $lang]

    set codes [::InstallJammer::GetLanguageCodes]
    if {[set x [lsearch -exact [string tolower $codes] $lang]] > -1} {
        return [lindex $codes $x]
    }

    set langs [::InstallJammer::GetLanguages]
    if {[set x [lsearch -exact [string tolower $langs] $lang]] > -1} {
        return $::InstallJammer::languages([lindex $langs $x])
    }
}

proc ::InstallJammer::GetLanguageCodes {} {
    return [lsort [array names ::InstallJammer::languagecodes]]
}

proc ::InstallJammer::GetLanguage { code } {
    set code [string tolower $code]

    set langs [::InstallJammer::GetLanguages]
    if {[set x [lsearch -exact [string tolower $langs] $code]] > -1} {
        return [lindex $langs $x]
    }

    set codes [::InstallJammer::GetLanguageCodes]
    if {[set x [lsearch -exact [string tolower $codes] $code]] > -1} {
        return $::InstallJammer::languagecodes([lindex $codes $x])
    }
}

proc ::InstallJammer::GetLanguages { {includeNone 0} } {
    variable languages
    set list [lremove [lsort [array names languages]] None]
    if {$includeNone} { set list [linsert $list 0 None] }
    return $list
}

proc ::InstallJammer::ConfigureBidiFonts {} {
    if {$::info(Language) eq "ar"} {
        foreach font [font names] {
            font configure $font -family Arial -size 10
        }
    }
}

proc ::InstallJammer::LoadTwapi {} {
    global conf

    ## Check to see if the user included the TWAPI extension
    ## and that we're on Windows XP or higher.  If so, require
    ## the extension to load the commands.
    set conf(twapi) 0
    if {$conf(windows)
        && $::tcl_platform(osVersion) >= 5.0
        && [info exists ::installkit::root]
        && [llength [package versions twapi]]} {
        ## Set a variable to trick TWAPI.
        namespace eval ::twapi {
            set temp_dll_dir [::InstallJammer::TmpDir]
        }

        package require twapi
        set conf(twapi) 1
    }
}

proc ::InstallJammer::InitializeCommandLineOptions {} {
    global conf
    global info

    if {[info exists conf(initializeCommandLine)]} { return }
    set conf(initializeCommandLine) 1

    variable ::InstallJammer::CommandLineOptions

    ## Setup the default options that all InstallJammer installers have.
    ## These options should not be removed by the developer.

    set CommandLineOptions(help) {
        {} Switch 0 0 {}
        "display this information" 
    }

    set CommandLineOptions(temp) {
        TempRoot String 0 0 {}
        "set the temporary directory used by this program"
    }

    set CommandLineOptions(version) {
        {} Switch 0 0 {}
        "display installer version information"
    }

    if {$info(EnableResponseFiles)} {
        set CommandLineOptions(response-file) {
            ResponseFile String 0 0 {}
            "a file to read installer responses from"
        }

        set CommandLineOptions(save-response-file) {
            SaveResponseFile String 0 0 {}
            "a file to write installer responses to when the installer exits"
        }
    }

    ## Make all the options case-insensitive.

    foreach opt [array names CommandLineOptions] {
        set name [string tolower $opt]
        set CommandLineOptions($name) [concat $opt $CommandLineOptions($opt)]
        if {$opt ne $name} { unset CommandLineOptions($opt) }

        lassign $CommandLineOptions($name) x var type debug hide values desc
        if {$type eq "Prefix"} {
            lappend CommandLineOptions(PREFIX) $name
        }
    }
}

proc ::InstallJammer::HideMainWindow {} {
    global conf
    global info

    if {[info exists ::tk_patchLevel]} {
        ## Hide the . window so no one will ever find it.
        wm geometry . 0x0+-10000+-10000
        ::InstallJammer::ModifyInstallTitle
        if {!$conf(windows) || !$info(GuiMode)} { wm overrideredirect . 1 }

        if {$info(GuiMode)} { wm deiconify . }
    }
}

proc ::InstallJammer::NewStyle { newStyle oldStyle args } {
    style layout $newStyle [style layout $oldStyle]
    eval [list style configure $newStyle] [style configure $oldStyle] $args
    return $newStyle
}

proc ::InstallJammer::CreateDir { dir {log 1} } {
    variable CreateDir

    if {![info exists CreateDir($dir)]} {
        set list [file split $dir]

        for {set i 0} {$i < [llength $list]} {incr i} {
            lappend dirlist [lindex $list $i]
            set dir [eval file join $dirlist]
            if {![info exists CreateDir($dir)]} {
                set CreateDir($dir) 1
                if {![file exists $dir]} {
                    file mkdir $dir
                    if {$log} { ::InstallJammer::LogDir $dir }
                }
            }
        }
    }

    return $dir
}

proc ::InstallJammer::DirIsEmpty { dir } {
    set list1 [glob -nocomplain -directory $dir *]
    set list2 [glob -nocomplain -directory $dir -types hidden *]
    set list  [lremove [concat $list1 $list2] $dir/. $dir/..]
    return    [lempty $list]
}

proc ::InstallJammer::PlaceWindow { id args } {
    set id [::InstallJammer::ID $id]
    set anchor center

    if {[winfo exists $id]} {
        set target $id
    } else {
        set target [$id window]
        if {![$id get Anchor anchor]} { set anchor center }
    }

    array set data "
	-anchor $anchor
	-width  [winfo reqwidth  $target]
	-height [winfo reqheight $target]
    "

    array set data $args

    set w  $data(-width)
    set h  $data(-height)
    set sw [winfo screenwidth $target]
    set sh [winfo screenheight $target]
    lassign [wm maxsize .] maxw maxh
    set anchor $data(-anchor)
    switch -- $anchor {
	"center" {
	    set x0 [expr ($sw - $w) / 2 - [winfo vrootx $target]]
	    set y0 [expr ($sh - $h) / 2 - [winfo vrooty $target]]
	}

	"n" {
	    set x0 [expr ($sw - $w)  / 2 - [winfo vrootx $target]]
	    set y0 20
	}

	"ne" {
	    set x0 [expr $maxw - $w - 40]
	    set y0 20
	}

	"e" {
	    set x0 [expr $maxw - $w - 40]
	    set y0 [expr ($sh - $h) / 2 - [winfo vrooty $target]]
	}

	"se" {
	    set x0 [expr $maxw - $w - 40]
	    set y0 [expr $maxh - $h - 80]
	}

	"s" {
	    set x0 [expr ($sw - $w)  / 2 - [winfo vrootx $target]]
	    set y0 [expr $maxh - $h - 80]
	}

	"sw" {
	    set x0 20
	    set y0 [expr $maxh - $h - 80]
	}

	"w" {
	    set x0 20
	    set y0 [expr ($sh - $h) / 2 - [winfo vrooty $target]]
	}

	"nw" {
	    set x0 20
	    set y0 20
	}

	default {
	    append msg "bad anchor \"$anchor\": must be"
	    append msg "n, ne, e, se, s, sw, w, nw or center"
	    return -code error $msg
	}
    }

    set x "+$x0"
    set y "+$y0"
    if { $x0+$w > $sw } {set x "-0"; set x0 [expr {$sw-$w}]}
    if { $x0 < 0 }      {set x "+0"}
    if { $y0+$h > $sh } {set y "-0"; set y0 [expr {$sh-$h}]}
    if { $y0 < 0 }      {set y "+0"}

    wm geometry $target $x$y
    update
}

proc ::InstallJammer::CenterWindow { target {w 473} {h 335} {lower 0} } {
    set args [list -width $w -height $h]
    if {$lower} { lappend args -anchor s }
    eval [list PlaceWindow $target] $args
}

proc ::InstallJammer::ID { args } {
    set alias [string trim [join $args]]
    if {[info exists ::InstallJammer::aliases($alias)]} {
        return $::InstallJammer::aliases($alias)
    }
    return $alias
}

proc ::InstallJammer::FindCommonPane { pane } {
    foreach id [Common children] {
        if {[string equal [$id component] $pane]} { return $id }
    }
}

proc ::InstallJammer::FindObjByName { name objects } {
    foreach object $objects {
        if {[string equal [$object name] $name]} { return $object }
    }
}

proc ::InstallJammer::GetPaneProc { id prefix } {
    set proc $prefix.$id
    if {![::InstallJammer::CommandExists $proc]} {
    	set proc $prefix.[$id component]
    }
    if {[::InstallJammer::CommandExists $proc]}  { return $proc }
}

proc ::InstallJammer::CurrentObject { {command "get"} {id ""} } {
    global conf
    global info

    if {$command eq "get"} {
        set id [lindex $conf(ObjectStack) end]
    } elseif {$command eq "pop"} {
        set id [lindex $conf(ObjectStack) end]
        set conf(ObjectStack) [lrange $conf(ObjectStack) 0 end-1]
    } elseif {$command eq "push" && $id ne ""} {
        lappend conf(ObjectStack) $id
    }

    set info(CurrentObject) [lindex $conf(ObjectStack) end]

    return $id
}

proc ::InstallJammer::ExecuteActions { id args } {
    global conf
    global info

    array set _args {
        -when       ""
        -type       ""
        -parent     ""
        -conditions 1
    }
    array set _args $args

    set id [::InstallJammer::ID $id]

    if {![::InstallJammer::ObjExists $id]} { return 1 }

    if {[$id is action]} {
        set idlist [list $id]
    } else {
        set idlist [$id children]
    }

    if {![llength $idlist]} { return 1 }

    set msg "Executing actions $id"
    if {![catch { $id title } title]} { append msg " - $title" }
    if {$_args(-when) ne ""} { append msg " - $_args(-when)" }
    debug $msg

    set res 1
    set conf(moveToPane) ""
    foreach id $idlist {
        if {![$id active]} { continue }

        set obj  $id
        set type [$obj component]

        if {$_args(-type) ne "" && $type ne $_args(-type)} { continue }

        if {[$id type] eq "actiongroup"} {
            eval ::InstallJammer::ExecuteActions [list $id] $args
            continue
        }

        ## If we have a parent, it means that we're an ExecuteAction
        ## action that is calling another action, which can also be
        ## an action group.  We want the action we're executing
        ## to have the attributes of the parent action, so we create
        ## a temporary object that inherits the attributes of the
        ## parent and execute that in place of the original object.

        if {$_args(-parent) ne ""} {
            set obj [::InstallJammer::CreateTempAction $_args(-parent) $id]
            lappend tempObjects $obj
        }

        if {$_args(-when) ne ""
            && [$obj get ExecuteAction when]
            && ![string equal -nocase $_args(-when) $when]} { continue }

        set info(CurrentAction) $id
        ::InstallJammer::CurrentObject push $id

        $obj executed 0

        set when "Before Action is Executed"
        if {$_args(-conditions) && ![$obj checkConditions $when]} {
            debug "Skipping action $id - [$id title] - conditions failed"
            ::InstallJammer::CurrentObject pop
            continue
        }

        set when "Before Next Action is Executed"
        while {1} {
            $obj execute
            
            ## Check the after conditions.  If the conditions fail,
            ## we want to repeat the action until they succeed.
            ## This is mainly for console actions to repeat if their
            ## conditions fail, like the user entered bad data or
            ## select a bad option.
            if {!$_args(-conditions) || [$obj checkConditions $when]} { break }
        }

        ::InstallJammer::CurrentObject pop
        if {$conf(moveToPane) ne ""} {
            set res  0
            set pane $conf(moveToPane)
            if {$pane eq "stop"} {
                ## Do nothing.
            } elseif {$pane eq "next"} {
                ::InstallJammer::Wizard next 1
            } else {
                if {$pane eq $info(CurrentPane)} {
                    ::InstallJammer::Wizard reload
                } else {
                    ::InstallJammer::Wizard raise $pane
                }
            }
            break
        }
    }

    if {[info exists tempObjects]} {
        eval itcl::delete object $tempObjects
    }

    return $res
}

proc ::InstallJammer::CreateTempAction { id child } {
    set obj [InstallComponent ::#auto -temp 1 -parent [$id parent] \
        -setup [$id setup] -type action -id $child -name [$child name] \
        -component [$child component] -conditions [$child conditions] \
        -operator [$child operator]]

    return $obj
}

## Uses the wizard's -backcommand option.
proc ::InstallJammer::BackCommand { wizard id } {
    global info

    set when "Before Previous Pane is Displayed"

    if {![$id checkConditions $when]} { return 0 }

    set res [::InstallJammer::ExecuteActions $id -when $when]

    set info(UserMovedBack) 1
    set info(UserMovedNext) 0

    return $res
}

## This command is executed when the user hits next but before
## the next pane is displayed.
## Uses the wizard's -nextcommand option.
proc ::InstallJammer::NextCommand { wizard id } {
    global info

    set when "Before Next Pane is Displayed"

    if {![$id checkConditions $when]} { return 0 }

    set res [::InstallJammer::ExecuteActions $id -when $when]

    set info(UserMovedBack) 0
    set info(UserMovedNext) 1

    return $res
}

## This command is executed before the installer is cancelled.
## Uses the wizard's -cancelcommand option.
proc ::InstallJammer::CancelCommand { wizard id } {
    set when "Before Pane is Cancelled"

    if {![$id checkConditions $when]} { return 0 }

    return [::InstallJammer::ExecuteActions $id -when $when]
}

## Uses the wizard's <<WizardCancel>> event.
proc ::InstallJammer::CancelEventHandler { wizard } {
    #set id [$wizard raise]

    #set when "After Pane is Cancelled"
    #::InstallJammer::ExecuteActions $id -when $when

    if {[$wizard itemcget cancel -state] eq "normal"} {
        ::InstallJammer::exit 1
    }
}

## This command is executed before the installer is finished.
## Uses the wizard's -finishcommand option.
proc ::InstallJammer::FinishCommand { wizard id } {
    set when "Before Pane is Finished"

    if {![$id checkConditions $when]} { return 0 }

    return [::InstallJammer::ExecuteActions $id -when $when]
}

## Uses the wizard's <<WizardFinish>> event.
proc ::InstallJammer::FinishEventHandler { wizard } {
    set id [$wizard raise]

    set when "After Pane is Finished"
    ::InstallJammer::ExecuteActions $id -when $when

    ::InstallJammer::exit
}

## Uses the wizard's <<WizardStep>> event.
proc ::InstallJammer::RaiseEventHandler { wizard } {
    global conf
    global info

    set id [$wizard raise]

    set info(CurrentPane) $id

    set conf(skipPane) 0
    set when "Before Pane is Displayed"
    if {![$id active]} {
        set conf(skipPane) 1
        set msg "pane is inactive"
    } elseif {![$id checkConditions $when]} {
        set conf(skipPane) 1
        set msg "conditions failed"
    } elseif {[lsearch -exact $conf(panesToSkip) $id] > -1} {
        set conf(skipPane) 1
        set msg "skipped by action or API"
    } else {
        set component [$id component]
        if {[info exists ::InstallJammer::tests(before,$id)]} {
            inject run before,$id
        } elseif {[info exists ::InstallJammer::tests(before,$component)]} {
            inject run before,$component
        }

        ::InstallJammer::ExecuteActions $id -when $when
        set msg "skipped by actions"
    }

    if {$conf(skipPane) || [lsearch -exact $conf(panesToSkip) $id] > -1} {
        debug "Skipping pane $id - [$id title] - $msg" $id
        $wizard order [lrange [$wizard order] 0 end-1]
        ::InstallAPI::WizardAPI -do next
        return
    }

    ## If the wizard isn't currently displaying our object, then
    ## that means that the previous actions have moved us somewhere
    ## else in the wizard.  We want to just stop.
    if {$id ne [$wizard raise]} { return }

    debug "Displaying pane $id - [$id title]" $id

    ## If the last step we displayed was a window and not part
    ## of the wizard, we need to withdraw the window as we move on.
    if {[info exists conf(LastStepId)] && [$conf(LastStepId) is window]} {
        set window [$conf(LastStepId) window]
        ::InstallJammer::TransientParent $window 1
        wm withdraw $window
    } else {
        ::InstallJammer::TransientParent $wizard 1
    }

    ## If this component is a window, we need to withdraw the
    ## wizard and display it.
    if {[$id is window]} {
        set base [$id window]
        ::InstallJammer::TransientParent $base

        wm withdraw $wizard 

        ::InstallJammer::UpdateWidgets

        if {![$id get Modal  modal]}  { set modal  0 }
        if {![$id get Dialog dialog]} { set dialog 0 }

        if {[winfo exists $base]} {
            wm deiconify $base
            raise $base
            if {$modal} { ::InstallJammer::Grab set $base }
        }

        update

        set when "After Pane is Displayed"
        ::InstallJammer::ExecuteActions $id -when $when

        if {[winfo exists $base]} {
            if {$dialog} {
                if {[$id get DialogVairiable varName]} {
                    tkwait variable $varName
                } else {
                    tkwait window $base
                }
            }

            if {$modal} { ::InstallJammer::Grab release $base }
        }
    } else {
        ::InstallJammer::TransientParent $wizard
        ::InstallJammer::UpdateWidgets -wizard $wizard -step $id -buttons 1

        $wizard show
        focus [$wizard widget get next]
        update

        set when "After Pane is Displayed"
        ::InstallJammer::ExecuteActions $id -when $when
    }

    if {[info exists ::InstallJammer::tests(after,$id)]} {
        inject run after,$id
    } elseif {[info exists ::InstallJammer::tests(after,$component)]} {
        inject run after,$component
    }

    set info(WizardLastStep)  0
    set info(WizardFirstStep) 0

    set conf(LastStepId) $id
}

proc ::InstallJammer::UpdateWizardButtons { args } {
    global info

    if {[llength $args]} {
        lassign $args wizard id
    } else {
        set wizard $info(Wizard)
        set id [$wizard raise]
    }

    if {![$id get Buttons buttons]} { return }

    foreach button [list back next cancel finish help] {
        if {![$wizard exists $button]} { continue }

        set text [string totitle $button]
        if {[string match "*$text*" $buttons]} {
            $wizard itemconfigure $button -hide 0

            set w [$wizard widget get $button -step $id]
            ::InstallJammer::SetText $w $id [string toupper $button 0]Button
        } else {
            $wizard itemconfigure $button -hide 1
        }
    }
}

proc ::InstallJammer::Wizard { args } {
    global info

    set wizard $info(Wizard)

    if {![llength $args]} { return $wizard }

    set command [lindex $args 0]
    set args    [lrange $args 1 end]

    set id [::InstallJammer::ID [lindex $args 0]]

    switch -- $command {
        "back" {
            if {![llength $args]} { set args 1 }
            eval [list $info(Wizard) back] $args
        }

        "next" {
            if {![llength $args]} { set args 1 }
            eval [list $info(Wizard) next] $args
        }

        "create" {
            ::InstallJammer::CreateWindow $wizard $id
        }

        "raise" {
            set args [lreplace $args 0 0 $id]
            if {[llength $args] == 1} { lappend args 1 }
            $info(Wizard) order [concat [$info(Wizard) order] $id]
            eval [list $info(Wizard) raise] $args
        }

        "reload" {
            event generate $info(Wizard) "<<WizardStep>>"
        }

        "show" {
            $wizard show
        }

        "hide" {
            if {$id eq ""} {
                $wizard hide
            } else {
                wm withdraw [$id window]
            }
        }
    }
}

proc ::InstallJammer::CreateWindow { wizard id {preview 0} } {
    set id    [::InstallJammer::ID $id]
    set pane  [$id component]
    set istop [$id is window]

    set base  .[$id name]

    if {$istop} {
        if {[winfo exists $base]} { return $base }
    } else {
        if {[$wizard exists $id] && ($preview || [$id created])} {
            return [$wizard widget get $id]
        }
    }

    set parent [$id parent]

    if {$preview && ![$wizard exists $id]} {
        set parent root
        $id get WizardOptions opts
        eval [list $wizard insert step end $parent $id] $opts
    }

    if {!$preview && [$wizard exists $id]} {
        $wizard itemconfigure $id \
            -backcommand   [list ::InstallJammer::BackCommand  $wizard $id]  \
            -nextcommand   [list ::InstallJammer::NextCommand  $wizard $id]  \
            -cancelcommand [list ::InstallJammer::CancelCommand $wizard $id] \
            -finishcommand [list ::InstallJammer::FinishCommand $wizard $id]

        bind $wizard <<WizardStep>>   "::InstallJammer::RaiseEventHandler  %W"
        bind $wizard <<WizardCancel>> "::InstallJammer::CancelEventHandler %W"
        bind $wizard <<WizardFinish>> "::InstallJammer::FinishEventHandler %W"

        bind $wizard <<WizardLastStep>>  "set ::info(WizardLastStep)  1"
        bind $wizard <<WizardFirstStep>> "set ::info(WizardFirstStep) 1"

        $id created 1
    }

    set proc [GetPaneProc $id CreateWindow]

    if {[string length $proc]} {
        if {!$istop} {
            $wizard createstep $id

            $proc $wizard $id
            set base [$wizard widget get $id]
            $id window $base
        } else {
            $id window $base
            $proc $wizard $id
        }
    }

    return $base
}

proc ::InstallJammer::TransientParent { {parent ""} {remove 0} } {
    global conf

    if {$parent ne ""} {
        if {$remove} {
            set conf(ParentWindow) [lremove $conf(ParentWindow) $parent]
        } else {
            lappend conf(ParentWindow) $parent
        }
    }

    set parent "."
    if {[info exists conf(ParentWindow)]} {
        set windows $conf(ParentWindow)
        set conf(ParentWindow) [list]

        ## Strip out any windows that have been destroyed.
        foreach window $windows {
            if {[winfo exists $window]} {
                lappend conf(ParentWindow) $window
            }
        }

        ## Find the first parent that is actually visible.
        foreach window [lreverse $conf(ParentWindow)] {
            if {[wm state $parent] eq "normal"} {
                set parent $window
                break
            }
        }
    }

    if {[wm state $parent] ne "normal"} { set parent "" }

    return $parent
}

proc ::InstallJammer::ParseArgs { arrayName arglist args } {
    upvar 1 $arrayName a

    array set _args $args

    if {[info exists _args(-switches)]} {
        foreach switch $_args(-switches) {
            set a($switch) 0
            set s($switch) 1
        }
    }

    if {[info exists _args(-options)]} {
        array set o $_args(-options)
        foreach {option default} $_args(-options) {
            set a($option) $default
        }
    }

    set a(_ARGS_) [list]

    set len [llength $arglist]
    for {set i 0} {$i < $len} {incr i} {
        set arg [lindex $arglist $i]

        if {[info exists s($arg)]} {
            set a($arg) 1
        } elseif {[info exists o($arg)]} {
            set a($arg) [lindex $arglist [incr i]]
        } else {
            set a(_ARGS_) [lrange $arglist $i end]
            break
        }
    }
}

proc ::InstallJammer::SetObjectProperties { id args } {
    variable ::InstallJammer::Properties

    ::InstallJammer::ParseArgs _args $args -switches {-safe -nocomplain}

    set args $_args(_ARGS_)

    if {[llength $args] == 1} { set args [lindex $args 0] }
    if {[llength $args] == 1} {
        set property [lindex $args 0]
        if {[info exists Properties($id,$property)]} {
            return $Properties($id,$property)
        }

        if {!$_args(-nocomplain)} {
            return -code error "invalid property '$property'"
        }

        return
    }

    foreach {property value} $args {
        if {!$_args(-safe) || ![info exists Properties($id,$property)]} {
            if {$property eq "Alias"} {
		catch { $id alias $value }

		if {[info exists ::InstallJammer::aliasmap($id)]} {
		    $id CleanupAlias
		}

		if {$value ne ""} {
		    set ::InstallJammer::aliases($value) $id
		    set ::InstallJammer::aliasmap($id) $value
		}
            }

            if {$property eq "Active"} { $id active $value }

            if {![info exists ::InstallJammer]} {
                variable ::InstallJammer::PropertyMap
                if {[info exists PropertyMap($property)]} {
                    set n $value
                    if {![string is integer -strict $n]} {
                        set n [lsearch -exact $PropertyMap($property) $value]
                        if {$n < 0} {
                            return -code error [BWidget::badOptionString value \
                                $value $PropertyMap($property)]
                        }
                    }
                    set value $n
                }
            }
            set Properties($id,$property) $value
        }
    }

    return $Properties($id,$property)
}

proc ::InstallJammer::GetObjectProperty { id property {varName ""} } {
    set value  ""
    set exists [info exists ::InstallJammer::Properties($id,$property)]
    if {$exists} {
        set value $::InstallJammer::Properties($id,$property)
        if {[info exists ::InstallJammer::PropertyMap($property)]
            && [string is integer -strict $value]} {
            set value [lindex $::InstallJammer::PropertyMap($property) $value]
        }
    }

    if {$varName ne ""} {
        upvar 1 $varName var
        set var $value
        return $exists
    } else {
        return $value
    }
}

proc ::InstallJammer::ObjectProperties { id arrayName args } {
    upvar 1 $arrayName array
    variable ::InstallJammer::Properties

    ::InstallJammer::ParseArgs _args $args -options {-prefix "" -subst 0}

    set slen 0
    if {[info exists _args(-subst)]} {
        set subst $_args(-subst)
        set slen  [llength $subst]
    }

    set props $_args(_ARGS_)
    if {![llength $props]} {
        foreach varName [array names Properties $id,*] {
            lappend props [string map [list $id, ""] $varName]
        }
    }

    set vars {}
    foreach prop $props {
        if {![info exists Properties($id,$prop)]} { continue }

        set val $Properties($id,$prop)
        if {$slen && ($subst eq "1" || [lsearch -exact $subst $prop] > -1)} {
            set val [::InstallJammer::SubstText $val]
        }
        if {[info exists ::InstallJammer::PropertyMap($prop)]
            && [string is integer -strict $val]} {
            set val [lindex $::InstallJammer::PropertyMap($prop) $val]
        }
        set prop $_args(-prefix)$prop
        lappend vars $prop
        set array($prop) $val
    }

    return $vars
}

proc ::InstallJammer::ObjectChildrenRecursive { object } {
    set children [list]

    foreach child [$object children] {
        lappend children $child
        eval lappend children [::InstallJammer::ObjectChildrenRecursive $child]
    }

    return $children
}

proc ::InstallJammer::SetTitle { w id } {
    set id [::InstallJammer::ID $id]
    set title [::InstallJammer::GetText $id Title]
    wm title $w $title
}

proc ::InstallJammer::SetVirtualText { languages window args } {
    if {[llength $args] == 1} { set args [lindex $args 0] }

    if {[string equal -nocase $languages "all"]} {
        set languages [::InstallJammer::GetLanguageCodes]
    }

    foreach lang $languages {
        if {$lang eq "None"} {
            global info
            foreach {name value} $args {
                set info($name) $value
                debug "Virtual Text $name is now set to $value"
            }
        } else {
            set lang [::InstallJammer::GetLanguageCode $lang]
            foreach {name value} $args {
                ::msgcat::mcset $lang $window,$name $value
            }
        }
    }
}

proc ::InstallJammer::GetText { id field args } {
    global info

    array set _args {
        -subst      1
        -language   ""
        -forcelang  0
        -forcesubst 0
    }
    array set _args $args

    set languages {}
    if {$_args(-language) ne ""} {
        foreach lang $_args(-language) {
            lappend languages [::InstallJammer::GetLanguageCode $lang]
        }
    }
    if {!$_args(-forcelang)} {
        eval lappend languages [::msgcat::mcpreferences]
    }

    if {[string equal -nocase $_args(-language) "all"]} {
        foreach lang [::InstallJammer::GetLanguageCodes] {
            set text [::InstallJammer::GetTextForField $id $field $lang]
            if {[info exists last] && $last ne $text} { return }
            set last $text
        }
        if {$_args(-subst)} { set text [::InstallJammer::SubstText $text] }
        return $text
    }

    set found 0
    foreach lang $languages {
        set text [::InstallJammer::GetTextForField $id $field $lang]
        if {$text ne ""} {
            set found 1
            break
        }
    }

    if {$found} {
	if {$_args(-forcesubst)
	    || ($_args(-subst) && [$id get $field,subst subst] && $subst)} {
	    set text [::InstallJammer::SubstText $text]
	}

	return $text
    }
}

proc ::InstallJammer::GetTextForField { id field lang } {
    set id   [::InstallJammer::ID $id]
    set item [$id component]
    set text [::msgcat::mcget $lang $id,$field]
    if {$text eq "$id,$field"} {
        set text [::msgcat::mcget $lang $item,$field]
    }
    if {$text ne "$item,$field"} {
        return $text
    }
}

proc ::InstallJammer::SetText { args } {
    if {[llength $args] == 3} {
        lassign $args w id field
        set id   [::InstallJammer::ID $id]
        set text [::InstallJammer::GetText $id $field]
    } elseif {[llength $args] == 2} {
        lassign $args w text
    }

    if {![winfo exists $w]} { return }

    set class [winfo class $w]

    if {$class eq "Frame" || $class eq "TFrame"} {
    	foreach child [winfo children $w] {
	    set class [winfo class $child]
	    if {$class eq "Label" || $class eq "TLabel"} {
	    	set w $child
		break
	    }
	}
    }

    if {$class eq "Text"} {
        ## We're using the -maxundo property as a trick for other
        ## code to tell us not to update this widget.
        if {![$w cget -maxundo]} {
            set state [$w cget -state]
            if {$state eq "disabled"} { $w configure -state normal }
            if {$state eq "readonly"} {
                $w clear
                $w Insert end $text
            } else {
                $w delete 0.0 end
                $w insert end $text
            }
            if {$state eq "disabled"} { $w configure -state disabled }
        }
    } elseif {($class eq "Label" || $class eq "TLabel")
    	&& [string length [$w cget -textvariable]]} {
        set [$w cget -textvariable] $text
    } else {
	$w configure -text $text
    }
}

proc ::InstallJammer::Image { id image } {
    global images

    set id    [::InstallJammer::ID $id]
    set image $id,$image

    if {![ImageExists $image]} { set image [$id component],$image }
    if {![ImageExists $image]} { return }

    set x [::InstallJammer::SubstText $images($image)]
    if {[string index $x 0] eq "@"} { set x [string range $x 1 end] }
    set x [::InstallJammer::ID $x]
    set x [::InstallJammer::Normalize $x unix]
    if {[info exists images($x)]} { return $images($x) }

    if {[::InstallJammer::IsID $x] && [::InstallJammer::ObjExists $x]} {
        set images($x) [image create photo -file [$x srcfile]]
    } elseif {[file exists $x]} {
        set images($x) [image create photo -file $x]
    }

    if {[info exists images($x)]} { return $images($x) }
}

proc ::InstallJammer::SetImage { w id image } {
    set image [::InstallJammer::Image $id $image]
    if {[winfo class $w] eq "TLabel"} { set image [list $image] }
    $w configure -image $image
}

proc ::InstallJammer::ImageExists {img} {
    global images
    return [info exists images($img)]
}

proc ::InstallJammer::GetWidget { widget {id ""} } {
    global info

    if {![info exists info(Wizard)] || ![winfo exists $info(Wizard)]} { return }

    if {$id eq ""} { set id [$info(Wizard) raise] }
    if {$id eq ""} { return }

    while {![$id ispane]} {
        if {$id eq ""} { return }
        set id [$id parent]
    }

    set widget [join [string trim $widget] ""]

    switch -- $widget {
        "BackButton" - "NextButton" - "CancelButton" {
            set widget [string tolower [string range $widget 0 end-6]]
            set widget [$info(Wizard) widget get $widget]
        }

        default {
            if {![winfo exists $widget]} {
                set widget [$id widget get $widget]
            }
        }
    }

    return $widget
}

proc ::InstallJammer::FindUpdateWidgets { textList args } {
    global conf
    global info

    if {![info exists ::tk_patchLevel]} { return }
    if {![info exists info(Wizard)]} { return }

    set _args(-wizard)  $info(Wizard)
    array set _args $args

    set wizard $_args(-wizard)
    if {![winfo exists $wizard]} { return }

    if {![info exists _args(-step)]} { set _args(-step) [$wizard raise] }
    set step $_args(-step)

    if {$step eq ""} { return }

    set widgets [concat [$step widgets] $conf(ButtonWidgets)]

    ## Remove the trace on the info array so that we don't accidentally
    ## trigger something with our testing.
    trace remove variable ::info write ::InstallJammer::VirtualTextTrace

    set include {}
    foreach virtualtext $textList {
        unset -nocomplain orig
        if {[info exists info($virtualtext)]} { set orig $info($virtualtext) }

        foreach widget $widgets {
            set info($virtualtext) TEST1
            set text1 [::InstallJammer::GetText $step $widget]

            set info($virtualtext) TEST2
            set text2 [::InstallJammer::GetText $step $widget]

            if {$text1 ne $text2} { lappend include $widget }
        }

        if {[info exists orig]} {
            set info($virtualtext) $orig
        } else {
            unset info($virtualtext)
        }
    }

    ## Reset the trace on the info array.
    trace add variable ::info write ::InstallJammer::VirtualTextTrace

    return $include
}

proc ::InstallJammer::UpdateSelectedWidgets { {widgets {}} args } {
    if {![info exists ::tk_patchLevel]} { return }

    if {![llength $widgets]} { set widgets $::conf(UpdateWidgets) }

    if {[llength $args]} {
        set wizard [lindex $args 0]
        set step   [lindex $args 1]
        if {![winfo exists $wizard]} { return }
    } else {
        set wizard $::info(Wizard)
        if {![winfo exists $wizard]} { return }

        set step   [$wizard raise]
    }

    foreach widget $widgets {
        if {[lsearch -exact $::conf(ButtonWidgets) $widget] > -1} {
            set name [string tolower [string map {Button ""} $widget]]
            if {[$wizard exists $name]} {
                set w [$wizard widget get $name -step $step]
                ::InstallJammer::SetText $w $step $widget
            }
        } else {
            set w [$step widget get $widget]

            if {![winfo exists $w]} { continue }

            switch -- [$step widget type $widget] {
                "progress" {
                    set value [::InstallJammer::GetText $step $widget]
                    if {[string is double -strict $value]} {
                        $w configure -value $value
                    }
                }

                "image" {
                    ::InstallJammer::SetImage $w $step $widget
                }

                "text" {
                    ::InstallJammer::SetText $w $step $widget
                }

                "usertext" {
                    if {![$w cget -maxundo]} {
                        $w clear
                        $w insert end [::InstallJammer::GetText $step $widget]
                    }
                }
            }
        }
    }
}

proc ::InstallJammer::UpdateWidgets { args } {
    global conf
    global info

    if {![info exists ::tk_patchLevel]} { return }
    if {![info exists info(Wizard)]} { return }

    array set _args {
        -update          0
        -buttons         0
        -widgets         {}
        -updateidletasks 0
    }
    set _args(-wizard)  $info(Wizard)
    set _args(-widgets) $conf(UpdateWidgets)

    array set _args $args

    set wizard $_args(-wizard)
    if {![winfo exists $wizard]} { return }

    if {![info exists _args(-step)]} { set _args(-step) [$wizard raise] }
    set step $_args(-step)

    if {$step eq ""} { return }

    if {![llength $_args(-widgets)]} { set _args(-widgets) [$step widgets] }
    
    ::InstallJammer::UpdateSelectedWidgets $_args(-widgets) $wizard $step

    if {$_args(-buttons)} { ::InstallJammer::UpdateWizardButtons $wizard $step }

    set update     $_args(-update)
    set updateIdle $_args(-updateidletasks)
    if {[info exists conf(update)]} {
        set update     $conf(update)
        set updateIdle $conf(update)
    }
    if {$update} { update; set updateIdle 0 }
    if {$updateIdle} { update idletasks }
}

proc ::InstallJammer::DirIsWritable {dir} {
    global conf

    ## Assume wine is always writable.
    if {$conf(wine)} { return 1 }
    if {$conf(windows98)} { return [expr {![catch {file attributes $dir}]}] }
    return [file writable $dir]
}

proc ::InstallJammer::Normalize { file {style ""} } {
    global conf

    if {$file ne ""} {
        set file [eval file join [file split $file]]

        if {[string match "p*" $style]} {
            ## platform
            set style $::tcl_platform(platform)
        }

        switch -glob -- $style {
            "u*" {
                ## unix
                set style forwardslash
                if {[string index $file 1] == ":"} {
                    set file [string range $file 2 end]
                }
            }

            "w*" {
                ## windows
                set style backslash
                if {[string index $file 1] == ":"} {
                    set file [string toupper $file 0]
                }
            }
        }

        switch -glob -- $style {
            "f*" {
                ## forward
                set file [string map [list \\ /] $file]
            }

            "b*" {
                ## backward
                set file [string map [list / \\] $file]
            }
        }
    }

    return $file
}

proc ::InstallJammer::RelativeFile { file {relativeDir "<%InstallDir%>"} } {
    if {[file pathtype $file] eq "relative"} {
        set file [::InstallJammer::SubstText "$relativeDir/$file"]
    }
    return [::InstallJammer::Normalize $file]
}

proc ::InstallJammer::RollbackName { file } {
    global info
    return [file join [file dirname $file] .$info(InstallID).[file tail $file]]
}

proc ::InstallJammer::SaveForRollback {file} {
    file rename -force $file [::InstallJammer::RollbackName $file]
}

proc ::InstallJammer::GetShellFolder { folder } {
    set folder [string toupper $folder]
    array set map {DESKTOP DESKTOPDIRECTORY MYDOCUMENTS PERSONAL}
    if {[info exists map($folder)]} { set folder $map($folder) }
    if {[catch {twapi::get_shell_folder csidl_[string tolower $folder]} path]} {
        return [installkit::Windows::getFolder $folder]
    }
    return $path
}

proc ::InstallJammer::WindowsDir { dir } {
    set dir [string toupper $dir]

    ## We can't trust the WINDOWS directory on some systems apparently,
    ## so it's safer to trust the windir or SYSTEMROOT environment variables.
    if {$dir eq "WINDOWS"
        || [catch { ::InstallJammer::GetShellFolder $dir } windir]} {
        set windir ""
    }

    if {$windir ne ""} { return [::InstallJammer::Normalize $windir windows] }

    ## We couldn't find the directory they were looking for.
    ## See if we can give them something.

    if {[string match "COMMON_*" $dir]} {
        ## Windows 9x doesn't support COMMON_* directories, so let's
        ## see if we can give them the normal one.
        set chk [string range $dir 7 end]
        if {[catch { ::installkit::Windows::getFolder $chk } windir]} {
            set windir ""
        }
        if {[string length $windir]} {
            return [::InstallJammer::Normalize $windir windows]
        }
    }

    set curr {Software\Microsoft\Windows\CurrentVersion}
    set key  "HKEY_LOCAL_MACHINE\\$curr"

    switch -- $dir {
	"MYDOCUMENTS" {
	    set windir [::InstallJammer::WindowsDir PERSONAL]
	}

	"WINDOWS" {
	    if {[info exists ::env(SYSTEMROOT)]} {
		set windir $::env(SYSTEMROOT)
            } elseif {[info exists ::env(windir)]} {
		set windir $::env(windir)
	    } elseif {![catch {registry get $key SystemRoot} result]} {
		set windir $result
	    } else {
		set windir "C:\\Windows"
	    }
	}

	"PROGRAM_FILES" {
	    if {[info exists ::env(ProgramFiles)]} {
		set windir $::env(ProgramFiles)
	    } elseif {![catch {registry get $key ProgramFilesDir} result]} {
		set windir $result
	    } else {
		set windir "C:\\Program Files"
	    }
	}

	"SYSTEM" {
	    set windir [file join [WindowsDir WINDOWS] system]
	}

	"SYSTEM32" {
	    set windir [file join [WindowsDir WINDOWS] system32]
	}

	"QUICK_LAUNCH" {
	    set windir [WindowsDir APPDATA]
	    set windir [file join $windir \
	    	"Microsoft" "Internet Explorer" "Quick Launch"]
	}

	"COMMON_QUICK_LAUNCH" {
	    set windir [WindowsDir COMMON_APPDATA]
	    set windir [file join $windir \
	    	"Microsoft" "Internet Explorer" "Quick Launch"]
	}

	"WALLPAPER" {
	    set windir [registry get $key WallPaperDir]
	}

	default {
            ## We couldn't find the directory.  Let's try one more
            ## time by looking through the known registry values.

            array set regkeys {
                ADMINTOOLS        {USER "Administrative Tools"}
                APPDATA           {USER AppData}
                CACHE             {USER Cache}
                CDBURN_AREA       {USER "CD Burning"}
                COOKIES           {USER Cookies}
                DESKTOP           {USER Desktop}
                FAVORITES         {USER Favorites}
                FONTS             {USER Fonts}
                HISTORY           {USER History}
                INTERNET_CACHE    {USER Cache}
                LOCAL_APPDATA     {USER "Local AppData"}
                LOCAL_SETTINGS    {USER "Local Settings"}
                MYDOCUMENTS       {USER Personal}
                MYMUSIC           {USER "My Music"}
                MYPICTURES        {USER "My Pictures"}
                MYVIDEO           {USER "My Video"}
                NETHOOD           {USER NetHood}
                PERSONAL          {USER Personal}
                PRINTHOOD         {USER PrintHood}
                PROGRAMS          {USER Programs}
                RECENT            {USER Recent}
                SENDTO            {USER SendTo}
                STARTMENU         {USER "Start Menu"}
                STARTUP           {USER Startup}
                TEMPLATES         {USER Templates}

                COMMON_ADMINTOOLS {SYS "Common Administrative Tools"}
                COMMON_APPDATA    {SYS "Common AppData"}
                COMMON_DESKTOP    {SYS "Common Desktop"}
                COMMON_DOCUMENTS  {SYS "Common Documents"}
                COMMON_FAVORITES  {SYS "Common Favorites"}
                COMMON_MUSIC      {SYS CommonMusic}
                COMMON_PICTURES   {SYS CommonPictures}
                COMMON_PROGRAMS   {SYS "Common Programs"}
                COMMON_STARTMENU  {SYS "Common Start Menu"}
                COMMON_STARTUP    {SYS "Common Startup"}
                COMMON_TEMPLATES  {SYS "Common Templates"}
                COMMON_VIDEO      {SYS CommonVideo}
            }

            set SYS  "HKEY_LOCAL_MACHINE\\$curr\\Explorer\\Shell Folders"
            set USER "HKEY_CURRENT_USER\\$curr\\Explorer\\Shell Folders"

            if {[info exists regkeys($dir)]} {
                upvar 0 [lindex $regkeys($dir) 0] regkey
                set val [lindex $regkeys($dir) 1]
                set windir [::installkit::Windows::GetKey $regkey $val]
            }

            ## We still found nothing.  Return the virtual text string.
            if {$windir eq ""} { return <%$dir%> }
	}
    }

    return [::InstallJammer::Normalize $windir windows]
}

proc ::InstallJammer::SetupRegVirtualText {} {
    global info

    set env        {HKEY_LOCAL_MACHINE}
    set user       {HKEY_CURRENT_USER}
    set current    {HKEY_LOCAL_MACHINE}
    append env     {\SYSTEM\CurrentControlSet\Control\Session Manager}
    append current {\Software\Microsoft\Windows\CurrentVersion}

    set info(REG_USER_ENV)        "$user\\Environment"
    set info(REG_SYSTEM_ENV)      "$env\\Environment"
    set info(REG_UNINSTALL)       "$current\\Uninstall"
    set info(REG_CURRENT_VERSION) "$current"

    return
}

proc ::InstallJammer::SetWindowsPlatform {} {
    global conf
    global info

    set string Windows

    if {$conf(windows)} {
        switch -- $::tcl_platform(os) {
            "Windows 95" { set string "Win95" }
            "Windows 98" { set string "Win98" }
            "Windows NT" {
                switch -- $::tcl_platform(osVersion) {
                    "4.0" { set string "WinNT" }
                    "4.9" { set string "WinME" }
                    "5.0" { set string "Win2k" }
                    "5.1" { set string "WinXP" }
                    "5.2" { set string "Win2003" }
                    "6.0" { set string "Vista" }
                    "6.1" { set string "Windows7" }
                }
            }
        }
    }

    set info(WindowsPlatform) $string
}

proc ::InstallJammer::SubstVar { var } {
    global conf
    global info

    ## If this variable exists in the info array, return its value.
    if {[info exists info($var)]} {
	set string $info($var)
        if {[info exists ::InstallJammer::VTTypes($var)]} {
            if {$::InstallJammer::VTTypes($var) eq "boolean"} {
                set string [string is true $string]
            } elseif {$::InstallJammer::VTTypes($var) eq "directory"} {
                set string [::InstallJammer::Normalize $string platform]
            }
	}
   	return $string
    }

    ## See if this is a virtual text variable that exists in
    ## our message catalog.  If it does, we want to use the
    ## language-specific version instead of a generic.
    if {[::msgcat::mcexists $var]} { return [::msgcat::mc $var] }

    if {![info exists ::InstallJammer::subst]} {
        foreach proc [info commands ::InstallJammer::subst::*] {
            set ::InstallJammer::subst([namespace tail $proc]) $proc
        }
    }

    set idx  [string wordend $var 0]
    set word [string range $var 0 [expr {$idx - 1}]]
    set args [string trim [string range $var $idx end]]

    if {[info exists ::InstallJammer::subst($word)]} {
        return [eval ::InstallJammer::subst::$word $args]
    }

    if {$var ne "" && $var eq [string toupper $var]} {
        ## If the string is all uppercase and we haven't matched
        ## something yet, it's a Windows directory.
        return [::InstallJammer::WindowsDir $var]
    }

    return "<%$var%>"
}

proc ::InstallJammer::subst::Date { args } {
    set secs [lindex $args 0]
    if {[string is integer -strict $secs]} {
        set format [join [lrange $args 1 end]]
    } else {
        set secs   [clock seconds]
        set format [join $args]
    }

    return [clock format $secs -format $format]
}

proc ::InstallJammer::subst::Dir { args } {
    set dir      [lindex $args 0]
    set platform [lindex $args 1]
    if {$platform eq ""} { set platform $::tcl_platform(platform) }
    return [::InstallJammer::Normalize $dir $platform]
}

proc ::InstallJammer::subst::Dirname { args } {
    return [file dirname [join $args]]
}

proc ::InstallJammer::subst::DiskSpace { args } {
    return [::InstallJammer::FormatDiskSpace [join $args]]
}

proc ::InstallJammer::subst::DOSName { args } {
    global conf

    set file [join $args]

    if {$conf(windows) && [file exists $file]} { 
        set file [file attributes $file -shortname]
        set file [::InstallJammer::Normalize $file windows]
    }

    return $file
}

proc ::InstallJammer::subst::Env { args } {
    set var [lindex $args 0]
    if {[info exists ::env($var)]} { return $::env($var) }
}

proc ::InstallJammer::subst::FileGroup { args } {
    set group [join $args]
    set obj [::InstallJammer::FindObjByName $group [FileGroups children]]
    if {$obj ne ""} {
        set str [$obj directory]
        set str [::InstallJammer::Normalize $str $::tcl_platform(platform)]
        return $str
    }
}

proc ::InstallJammer::subst::FormatDescription { args } {
    set lines  [join $args]
    set string ""
    foreach line [split [string trim $lines] \n] {
        if {[string trim $line] eq ""} { set line "." }
        append string " $line\n"
    }
    return $string
}

proc ::InstallJammer::subst::GUID { args } {
    global info
    set info(LastGUID) [::InstallJammer::guid]
    return $info(LastGUID)
}

proc ::InstallJammer::subst::InstallInfoDir { args } {
    return [::InstallJammer::InstallInfoDir]
}

proc ::InstallJammer::subst::Property { args } {
    set property [lindex $args end]
    if {[llength $args] == 1} {
        set object [::InstallJammer::CurrentObject]
    } else {
        set object [::InstallJammer::ID [lindex $args 0]]
    }

    return [$object get $property]
}

proc ::InstallJammer::subst::RegValue { args } {
    set key  [lindex $args 0]
    set val  [lindex $args 1]
    return [::installkit::Windows::GetKey $key $val]
}

proc ::InstallJammer::subst::SpaceAvailable { args } {
    global info
    set dir [join $args]
    if {$dir eq ""} { set dir $info(InstallDir) }
    return [::InstallJammer::GetFreeDiskSpace $dir]
}

proc ::InstallJammer::subst::Tail { args } {
    return [file tail [join $args]]
}

proc ::InstallJammer::subst::Temp { args } {
    return [::InstallJammer::TmpDir]
}

proc ::InstallJammer::subst::Tolower { args } {
    return [string tolower $args]
}

proc ::InstallJammer::subst::Toupper { args } {
    return [string toupper $args]
}

proc ::InstallJammer::subst::UUID { args } {
    global info
    set info(LastUUID) [::InstallJammer::uuid]
    return $info(LastUUID)
}

proc ::InstallJammer::SubstForEval { string } {
    set map [list "<%" "\[::InstallJammer::SubstText \{<%" "%>" "%>\}\]"]
    return [string map $map $string]
}

proc ::InstallJammer::SubstForPipe { string } {
    set list [list]
    foreach arg $string {
        lappend list [::InstallJammer::SubstText $arg]
    }
    return $list
}

proc ::InstallJammer::SubstText { str {num 0} } {
    global conf

    if {$num > $conf(VirtualTextRecursionLimit)} { return $str }

    if {$str eq ""} { return }

    set s $str
    set s [string map $conf(VirtualTextMap) $s]
    set s [subst -novariables $s]
    if {$str ne $s} { set s [::InstallJammer::SubstText $s [incr num]] }

    return $s
}
interp alias {} sub {} ::InstallJammer::SubstText

proc settext {var val} {
    set ::info($var) $val
}

proc getobj {text} {
    if {[info exists ::InstallJammer::aliases($text)]} {
        return $::InstallJammer::aliases($text)
    } elseif {[info exists ::InstallJammer::names($text)]} {
        return $::InstallJammer::names($text)
    }
}

proc vercmp {ver1 ver2} {
    foreach v1 [split $ver1 ._-] v2 [split $ver2 ._-] {
        if {$v1 eq ""} { set v1 0 }
        if {$v2 eq ""} { set v2 0 }
        if {$v1 < $v2} { return -1 }
        if {$v1 > $v2} { return 1 }
    }
    return 0
}

proc ::InstallJammer::HasVirtualText { string } {
    return [string match "*<%*%>*" $string]
}

proc ::InstallJammer::TmpDir { {file ""} } {
    global conf
    global info

    if {![info exists info(TempRoot)] || ![file exists $info(TempRoot)]} {
        set dirs [list]
	if {[info exists ::env(TEMP)]} { lappend dirs $::env(TEMP) }
	if {[info exists ::env(TMP)]}  { lappend dirs $::env(TMP)  }
        if {$conf(windows)} {
            set local [::InstallJammer::WindowsDir LOCAL_APPDATA]
            lappend dirs [file join [file dirname $local] Temp]

            lappend dirs [::InstallJammer::WindowsDir INTERNET_CACHE]

	    lappend dirs C:/Windows/Temp
	    lappend dirs C:/WINNT/Temp
            lappend dirs C:/Temp

	} else {
	    lappend dirs /tmp /usr/tmp /var/tmp
	}

	foreach dir $dirs {
	    if {[DirIsWritable $dir]} {
                if {[info exists ::InstallJammer]} {
                    if {$file ne ""} { set dir [file join $dir $file] }
                    return $dir
                }
                set info(TempRoot) [::InstallJammer::Normalize $dir forward]
                break
            }
        }

        if {![info exists info(TempRoot)]} {
            if {[info exists ::env(TMP)]} { set tmp $::env(TMP) }
            if {[info exists ::env(TEMP)]} { set tmp $::env(TEMP) }
            if {![info exists tmp] || [catch {file mkdir $tmp}]} {
                return -code error \
                    "could not find a suitable temporary directory"
            }
            set info(TempRoot) $tmp
        }
    }

    if {![info exists info(Temp)]} {
        set info(Temp) [::InstallJammer::Normalize \
            [file join $info(TempRoot) ijtmp_[::InstallJammer::uuid]]]
    }

    if {![file exists $info(Temp)]} { file mkdir $info(Temp) }

    if {$file ne ""} {
	return [::InstallJammer::Normalize [file join $info(Temp) $file]]
    }

    return $info(Temp)
}

proc ::InstallJammer::TmpFile {} {
    global conf
    return [::InstallJammer::TmpDir [pid]-[incr0 conf(tmpFileCount)]]
}

proc ::InstallJammer::TmpMount {} {
    variable tmpMountCount

    if {![info exists tmpMountCount]} { set tmpMountCount 0 }

    while {1} {
        set mnt /installjammervfs[incr tmpMountCount]
        if {![file exists $mnt]} { break }
    }

    return $mnt
}

proc ::InstallJammer::ModifyInstallDir {} {
    global conf
    global info

    set dir [::InstallJammer::SubstText $info(InstallDir)]

    if {[info exists info(InstallDirSuffix)]} {
        set suf [::InstallJammer::SubstText $info(InstallDirSuffix)]

        set dir [::InstallJammer::Normalize $dir forward]
        set suf [::InstallJammer::Normalize $suf forward]
        if {![string match "*$suf" $dir]} { set dir [file join $dir $suf] }
    }

    if {[file pathtype $dir] eq "relative"} { set dir [file normalize $dir] }

    set info(InstallDir) [::InstallJammer::Normalize $dir platform]

    if {$conf(windows)} {
        set info(InstallDrive) [string range $info(InstallDir) 0 1]
    }
}

proc ::InstallJammer::ModifyInstallTitle {} {
    if {[info exists ::tk_patchLevel]} {
        set title [::InstallJammer::SubstText "<%InstallTitleText%>"]
        wm title . $title
        if {[info exists ::info(Wizard)] && [winfo exists $::info(Wizard)]} {
            $::info(Wizard) configure -title $title
        }
    }
}

proc ::InstallJammer::GetInstallInfoDir { {create 0} } {
    global conf
    global info

    if {![info exists info(InstallJammerRegistryDir)]} {
        if {$conf(windows)} {
            set root [::InstallJammer::WindowsDir PROGRAM_FILES]
            if {![::InstallJammer::DirIsWritable $root]} {
                ## If the Program Files directory is not writable
                ## it means this user has no permissions on this
                ## system.  We need to store our registry in the
                ## Application Data directory.
                set root [::InstallJammer::WindowsDir APPDATA]
            }

            set dir  [file join $root "InstallJammer Registry"]
        } else {
            if {[id user] eq "root"} {
                set dir "/var/lib/installjammer"
            } else {
                set dir "[::InstallJammer::HomeDir]/.installjammerinfo"
            }
        }

        set info(InstallJammerRegistryDir) [::InstallJammer::Normalize $dir]
    }

    if {![info exists info(InstallInfoDir)]} {
        set id $info(ApplicationID)
        if {[info exists info(UpgradeInstall)] && $info(UpgradeInstall)} {
            set id $info(UpgradeApplicationID)
        }

        set dir [file join $info(InstallJammerRegistryDir) $id]
        set info(InstallInfoDir) [::InstallJammer::Normalize $dir]
    }

    if {$create && ![file exists $info(InstallInfoDir)]} {
        ::InstallJammer::CreateDir $info(InstallInfoDir) 0
        if {$conf(windows)} {
            file attributes [file dirname $info(InstallInfoDir)] -hidden 1
        }
    }

    if {[info exists ::InstallJammer]} {
        set infodir $info(InstallInfoDir)
        unset info(InstallInfoDir) info(InstallJammerRegistryDir)
        return $infodir
    } else {
        return $info(InstallInfoDir)
    }
}

proc ::InstallJammer::InstallInfoDir { {file ""} } {
    set dir [::InstallJammer::GetInstallInfoDir 1]
    if {[string length $file]} { append dir /$file }
    return $dir
}

proc ::InstallJammer::SetPermissions { file perm } {
    if {$perm eq ""} { return }

    if {$::tcl_platform(platform) eq "windows"} {
	if {[string length $perm] > 4} { return }
	lassign [split $perm ""] a h r s
	file attributes $file -archive $a -hidden $h -readonly $r -system $s
    } else {
        file attributes $file -permissions $perm
    }
}

proc ::InstallJammer::WriteDoneFile { {dir ""} } {
    if {$dir eq ""} { set dir [::InstallJammer::TmpDir] }
    close [open [file join $dir .done] w]
}

## This proc attempts to find any InstallJammer temporary directories laying
## around and clean them up.  If a file called .done is in the directory,
## we know the InstallJammer program using that directory has finished with it,
## and it's ok to remove.
proc ::InstallJammer::CleanupTmpDirs {} {
    global info

    if {[string is true -strict $info(Debugging)]} { return }

    set tmp  [file dirname [TmpDir]]
    set time [expr {[clock seconds] - 86400}]
    foreach dir [glob -nocomplain -type d -dir $tmp ijtmp_*] {
        if {[DirIsEmpty $dir]
	    || [file exists [file join $dir .done]]
	    || [file mtime $dir] < $time} {
            catch { file delete -force $dir }
        }
    }
}

proc ::InstallJammer::EvalCondition { condition } {
    if {[string is true  $condition]} { return 1 }
    if {[string is false $condition]} { return 0 }

    set test [::InstallJammer::SubstForEval $condition]

    if {![string length $test]} { return 1 }
    if {[catch {expr [subst $test]} result]} {
        set msg "Error in condition '$condition'\n\n$::errorInfo"
        return -code error $msg
    }
    return $result
}

proc ::InstallJammer::HomeDir { {file ""} } {
    set return [file normalize ~]
    if {$file ne ""} { set return [file join $return $file] }
    return $return
}

proc ::InstallJammer::PauseInstall {} {
    global conf
    if {[info exists conf(pause)]} {
        ::InstallJammer::TmpDir
        close [open $conf(pause) w]
    }
}

proc ::InstallJammer::ContinueInstall {} {
    global conf
    if {[info exists conf(pause)]} { file delete $conf(pause) }
}

proc ::InstallJammer::StopInstall {} {
    global conf
    global info
    if {[info exists conf(stop)]} {
        ::InstallJammer::TmpDir
        close [open $conf(stop) w]
        set info(InstallStopped) 1
    }
}

proc ::InstallJammer::PauseCheck {} {
    global conf
    global info

    if {$info(InstallStopped)} { return 0 }

    while {[file exists $conf(pause)]} {
	if {[file exists $conf(stop)]} {
	    set info(InstallStopped) 1
            return 0
	}
	after 500
    }

    return 1
}

proc ::InstallJammer::UninstallFile {file} {
    file delete -force $file
}

proc ::InstallJammer::UninstallDirectory { dir {force ""} } {
    file delete $force $dir
}

## Uninstall a registry key.  If value is specified, we only want to delete
## that value from the registry key.  If, once the value has been deleted,
## the registry key is empty, we will delete that as well.
proc ::InstallJammer::UninstallRegistryKey {key {value ""}} {
    if {![lempty $value]} {
	catch { registry delete $key $value }
	if {[catch { registry keys $key } keys]} { return }
	if {[catch { registry values $key } values]} { return }
	if {[lempty $keys] && [lempty $values]} {
	    UninstallRegistryKey $key
	}
    } else {
	catch { registry delete $key }
    }
}

proc ::InstallJammer::LogDir { dir } {
    global conf
    global info

    if {!$conf(logInit)} {
        set conf(logInit) 1
        ::InstallJammer::TmpDir
        ::InstallJammer::GetInstallInfoDir
    }

    set dir [::InstallJammer::Normalize $dir forward]
    if {![string match $info(InstallInfoDir)* $dir]
        && ![string match $info(Temp)* $dir]} {
        ::InstallJammer::InstallLog [list :DIR $dir]
    }
}

proc ::InstallJammer::LogFile { file } {
    global conf
    global info

    if {!$conf(logInit)} {
        set conf(logInit) 1
        ::InstallJammer::TmpDir
        ::InstallJammer::GetInstallInfoDir
    }

    set file [::InstallJammer::Normalize $file forward]
    if {![string match $info(InstallInfoDir)* $file]
        && ![string match $info(Temp)* $file]} {
        ::InstallJammer::InstallLog [list :FILE $file]
    }
}

proc ::InstallJammer::SetVersionInfo { file {version ""} } {
    global info
    global versions
    if {$version eq ""} { set version $info(InstallVersion) }
    set versions($file) $version
}

proc ::InstallJammer::StoreLogsInUninstall {} {
    global conf
    global info

    if {[info exists conf(uninstall)]} {
        set tmp [::InstallJammer::TmpDir]

        foreach file [glob -nocomplain -dir $tmp *.info] {
            lappend files $file
            lappend names [file tail $file]

            set file [file root $file].log

            if {[file exists $file]} {
                lappend files $file
                lappend names [file tail $file]
            }
        }

        foreach file [glob -nocomplain -dir $tmp *.dead] {
            lappend files $file
            lappend names [file tail $file]
        }

        installkit::addfiles $conf(uninstall) $files $names
    }
}

proc ::InstallJammer::SetDialogArgs {which arrayName} {
    global conf
    upvar 1 $arrayName _args

    set parent [::InstallJammer::TransientParent]

    set _args(-parent)        $parent
    set _args(-transient)     [expr {$parent ne ""}]
    set _args(-usenative)     $conf(Native$which)
    set _args(-placerelative) [expr {$parent ne "" && $parent ne "."}]
}

proc ::InstallJammer::MessageBox { args } {
    global conf
    global widg

    if {$conf(windows)} { ::InstallJammer::InitializeGui }

    set win  .__message_box

    array set _args {
        -type        "ok"
        -buttonwidth 12
    }
    ::InstallJammer::SetDialogArgs MessageBox _args

    if {[info exists ::InstallJammer]} {
        set _args(-title) "InstallJammer"
    } else {
        set _args(-title) [::InstallJammer::SubstText "<%AppName%>"]
    }

    array set _args $args
    if {$_args(-title) eq ""} { set _args(-title) " " }

    set type $_args(-type)
    if {!$_args(-usenative) && $type ne "user"} {
        set idx 0

        set cancel     -1
        set default    -1
        set buttonlist {Retry OK Yes No Cancel}
        switch -- $type {
            "abortretryignore" {
                set default 0
                set buttonlist {Abort Retry Ignore}
            }

            "ok"          { set default 0 }
            "okcancel"    { set default 0; set cancel 1 }
            "retrycancel" { set default 0; set cancel 1 }
            "yesno"       { set default 0; set cancel 1 }
            "yesnocancel" { set default 0; set cancel 2 }
        }

        if {![info exists _args(-cancel)]} { set _args(-cancel) $cancel }
        if {![info exists _args(-default)]} { set _args(-default) $default }

        foreach button $buttonlist {
            set lbutton [string tolower $button]
            if {[string first $lbutton $type] > -1} {
                lappend buttons $lbutton
                lappend _args(-buttons) [::InstallJammer::SubstText <%$button%>]

                if {[info exists _args(-default)]
                    && $_args(-default) eq $lbutton} {
                    set _args(-default) $idx
                }

                incr idx
            }
        }

        if {[llength $buttons] == 1} { set _args(-default) 0 }

        set _args(-type) user
    }

    set result [eval [list MessageDlg $win] [array get _args]]

    if {!$_args(-usenative) && $type ne "user"} {
        return [lindex $buttons $result]
    }
    return $result
}

proc ::InstallJammer::Message { args } {
    set gui [info exists ::tk_patchLevel]

    if {[info exists ::InstallJammer]
        && $::tcl_platform(platform) eq "windows"
        && [file extension [info nameof]] eq ".com"} { set gui 0 }

    if {$gui} {
        if {[catch { eval ::InstallJammer::MessageBox $args } error]} {
            if {[info exists ::conf(unix)] && $::conf(unix)} {
                catch {rename ::tk_messageBox ""}
            }
            eval tk_messageBox -title "InstallJammer" $args
        }
    } else {
        set _args(-icon) "info"
	array set _args $args
	if {![info exists _args(-message)]} { return }

        set chan stdout
        if {$_args(-icon) eq "error"} { set chan stderr }

        puts  $chan "$_args(-message)"
        flush $chan
    }
}

proc ::InstallJammer::HandleThreadError { tid errorMsg } {
    global info

    set message "Error in thread $tid: $errorMsg"
    if {$info(Installing)} {
        ::InstallJammer::UnpackOutput $message
        ::InstallJammer::UnpackOutput :DONE
    } else {
        ::InstallJammer::MessageBox -message $message
    }
}

proc ::InstallJammer::ChooseDirectory { args } {
    global conf

    ::InstallJammer::SetDialogArgs ChooseDirectory _args

    set _args(-title) \
        [::InstallJammer::SubstText "<%PromptForDirectoryTitle%>"]
    set _args(-message) \
        [::InstallJammer::SubstText "<%PromptForDirectoryMessage%>"]
    set _args(-newfoldertext) \
        [::InstallJammer::SubstText "<%PromptForDirectoryNewFolderText%>"]
    set _args(-oktext)     [::InstallJammer::SubstText "<%OK%>"]
    set _args(-canceltext) [::InstallJammer::SubstText "<%Cancel%>"]
    array set _args $args

    if {[info exists _args(-command)]} {
        set command $_args(-command)
        unset _args(-command)
    }

    if {[info exists _args(-variable)]} {
        upvar 1 $_args(-variable) dir
        unset _args(-variable)

        if {![info exists _args(-initialdir)] && [info exists dir]} {
            set _args(-initialdir) $dir
        }
    }

    if {$_args(-usenative)} {
        set _args(-title) $_args(-message) 
        set res [eval ij_chooseDirectory [array get _args]]
    } else {
        unset -nocomplain _args(-usenative)
        if {[llength $conf(ParentWindow)] > 1} {
            wm withdraw [lindex $conf(ParentWindow) end]
        }

        set res [eval ::ChooseDirectory .__choose_directory [array get _args]]

        if {[llength $conf(ParentWindow)] > 1} {
            wm deiconify [lindex $conf(ParentWindow) end]
        }
    }

    if {$res ne ""} {
        set dir $res
        if {[info exists command]} { uplevel #0 $command }
        return $dir
    }
}

proc ::InstallJammer::ChooseFile { args } {
    global conf

    ::InstallJammer::SetDialogArgs ChooseFile _args
    array set _args $args

    if {[info exists _args(-command)]} {
        set command $_args(-command)
        unset _args(-command)
    }

    if {[info exists _args(-variable)]} {
        upvar 1 $_args(-variable) file
        unset _args(-variable)
    }

    if {$_args(-usenative)} {
        set type Open
        if {[info exists _args(-type)]} {
            set type [string toupper $_args(-type) 0]
        }
        set res [eval [list ij_get${type}File] [array get _args]]
    } else {
        unset -nocomplain _args(-usenative)
        if {[llength $conf(ParentWindow)] > 1} {
            wm withdraw [lindex $conf(ParentWindow) end]
        }

        set res [eval ::ChooseFile .__choose_file [array get _args]]

        if {[llength $conf(ParentWindow)] > 1} {
            wm deiconify [lindex $conf(ParentWindow) end]
        }
    }

    if {$res ne ""} {
        set file $res
        if {[info exists command]} { uplevel #0 $command }
        return $file
    }
}

proc ::InstallJammer::CommandExists { proc } {
    return [string length [info commands $proc]]
}

proc ::InstallJammer::uuid {} {
    global conf

    if {$conf(windows)} {
        return [string range [::InstallJammer::guid] 1 end-1]
    }

    set sha [sha1 -string [info hostname][clock seconds][pid][info cmdcount]]

    set i 0
    foreach x {8 4 4 4 12} {
        lappend list [string range $sha $i [expr {$i + $x - 1}]]
        incr i $x
    }

    return [string toupper [join $list -]]
}

proc ::InstallJammer::guid {} {
    global conf
    if {$conf(windows)} {
        return [string toupper [::installkit::Windows::guid]]
    }
    return \{[string toupper [::InstallJammer::uuid]]\}
}

proc ::InstallJammer::IsID { id } {
    if {[string length $id] != 36} { return 0 }
    set list [split $id -]
    if {[llength $list] != 5} { return 0 }
    set i 0
    foreach n {8 4 4 4 12} {
        if {[string length [lindex $list $i]] != $n} { return 0 }
        incr i
    }
    return 1
}

proc ::InstallJammer::ObjExists { obj } {
    return [info exists ::InstallJammer::ObjMap([namespace tail $obj])]
}

proc ::InstallJammer::ReadMessageCatalog { catalog } {
    set catalog [file join $::installkit::root catalogs $catalog]
    eval [read_textfile $catalog]
}

proc ::InstallJammer::Wrap { args } {
    global conf
    global info

    set include 1
    if {[set x [lsearch -exact $args -noinstall]] > -1} {
        set include 0
        set args [lreplace $args $x $x]
    }

    if {$include} {
        set pkgdir [file join $::installkit::root lib InstallJammer]
        set args [linsert $args 0 -package $pkgdir]
    }

    eval ::installkit::wrap $args
}

proc ::InstallJammer::Grab { command args } {
    variable GrabStack

    if {![info exists GrabStack]} {
        global info
        set GrabStack [list]
        if {[info exists info(Wizard)]} { lappend GrabStack $info(Wizard) }
        bind GrabWindow <Destroy> [list ::InstallJammer::Grab release %W]
    }

    ## Cleanup the stack before we do anything.
    set stack {}
    foreach w $GrabStack {
        if {[winfo exists $w]} { lappend stack $w }
    }
    set GrabStack $stack

    switch -- $command {
        "current" {
            return [grab current]
        }

        "stack" {
            return $GrabStack
        }

        "release" {
            set window [lindex $args 0]
            grab release $window
            set GrabStack [lremove $GrabStack $window]
            if {[llength $GrabStack] && [grab current] eq ""} {
                grab [lindex $GrabStack end]
            }
        }

        "set" {
            set window [lindex $args 0]
            grab $window
            set tags [bindtags $window]
            if {[lsearch -exact $tags GrabWindow] < 0} {
                bindtags $window [concat $tags GrabWindow]
            }
            set x [lsearch -exact $GrabStack $window]
            if {$x > -1} { set GrabStack [lreplace $GrabStack $x $x] }
            lappend GrabStack $window
        }

        default {
            ::InstallJammer::Grab set $command
        }
    }

    return
}

proc ::InstallJammer::HasKDEDesktop {} {
    global info

    set home [::InstallJammer::HomeDir]
    set kde  [file join $home .kde]

    if {![file exists $kde]} { return 0 }

    if {![info exists info(KDEDesktop)] || [lempty $info(KDEDesktop)]} {
	set globals [file join $kde share config kdeglobals]
	set desktop [file join $home Desktop]
	if {[catch {open $globals} fp]} { return 0 }
	while {[gets $fp line] != -1} {
	    if {[regexp {^Desktop=([^\n].*)\n} $line\n trash desktop]} {
		regsub -all {\$([A-Za-z0-9]+)} $desktop {$::env(\1)} desktop
		break
	    }
	}
	close $fp
	set info(KDEDesktop) $desktop
    }

    return [file exists $info(KDEDesktop)]
}

proc ::InstallJammer::HasGnomeDesktop {} {
    global info

    set home [::InstallJammer::HomeDir]

    foreach dir [list .gnome-desktop Desktop] {
        set desktop [file join $home $dir]
        if {[file exists $desktop]} {
            set info(GnomeDesktop) $desktop
            break
        }
    }

    if {[info exists info(GnomeDesktop)] && [file exists $info(GnomeDesktop)]} {
        return 1
    }
    return 0
}

proc ::InstallJammer::GetDesktopEnvironment {} {
    global env

    ## KDE
    if {[info exists env(DESKTOP)] && $env(DESKTOP) eq "kde"} { return KDE }
    if {[info exists env(KDE_FULL_SESSION)]} { return KDE }

    ## Gnome
    if {[info exists env(GNOME_DESKTOP_SESSION_ID)]} { return Gnome }

    if {[info exists env(DESKTOP_SESSION)]} {
        switch -glob -- $env(DESKTOP_SESSION) {
            "*KDE*"   { return KDE }
            "*GNOME*" { return Gnome }
        }
    }

    return "Unknown"
}

proc ::InstallJammer::GetLinuxDistribution {} {
    set lsb_release [auto_execok lsb_release]
    if {[file executable $lsb_release]} {
        if {![catch { exec $lsb_release -i -s } distrib]} { return $distrib }
    }

    foreach lsb_release [list /etc/lsb-release /etc/lsb_release] {
	if {[file readable $lsb_release]} {

	}
    }

    set check {
	/etc/mandrake-release    Mandrake
	/etc/fedora-release      Fedora
	/etc/SuSE-release        SuSE
	/etc/debian_version      Debian
	/etc/gentoo-release      Gentoo
	/etc/slackware-version   Slackware
	/etc/turbolinux-release  TurboLinux
	/etc/yellowdog-release   YellowDog
	/etc/connectiva-release  Connectiva
	/etc/redhat-release      Redhat
    }
}

proc ::InstallJammer::GetFreeDiskSpace { dir } {
    global conf

    if {$conf(windows)} {
        set drive [lindex [file split $dir] 0]
        return [::installkit::Windows::drive freespace $drive]
    }

    set df [auto_execok df]
    if {[file exists $df]} {
        while {![file exists $dir]} {
            set dir [file dirname $dir]
        }
        catch { exec $df -k $dir } output

        set line [join [lrange [split $output \n] 1 end] " "]
        if {![catch { expr {[lindex $line 3] * wide(1024)} } avail]} {
            return $avail
        }
    }

    return -1
}

proc ::InstallJammer::FormatDiskSpace { space } {
    if {$space < 1048576} {
        return [format "%2.2f KB" [expr {$space / 1024.0}]]
    }
    if {$space < 1073741824} {
        return [format "%2.2f MB" [expr {$space / 1048576.0}]]
    }
    return [format "%2.2f GB" [expr {$space / 1073741824.0}]]
}

proc ::InstallJammer::unpack { src dest {permissions ""} } {
    if {![string length $permissions]} { set permissions "0666" }

    # Extract the file and copy it to its location.
    set fin [open $src r]
    if {[catch {open $dest w $permissions} fout]} {
	close $fin
	return -code error $fout
    }

    set intrans  binary
    set outtrans binary
    if {[info exists ::conf(eol,[file extension $dest])]} {
        set trans $::conf(eol,[file extension $dest])
        if {[llength $trans] == 2} {
            set intrans  [lindex $trans 0]
            set outtrans [lindex $trans 1]
        } else {
            set outtrans [lindex $trans 0]
        }
    }

    fconfigure $fin  -translation $intrans
    fconfigure $fout -translation $outtrans

    fcopy $fin $fout

    close $fin
    close $fout
}

proc ::InstallJammer::ExecAsRoot { command args } {
    global conf
    global info

    array set _args {
        -title   ""
        -message "<%PromptForRootText%>"
    }
    array set _args $args

    set wait 0
    if {[info exists _args(-wait)]} { set wait $_args(-wait) }

    set cmd   [list]
    set msg   [sub $_args(-message)]
    set title [sub $_args(-title)]

    set i 0
    set x [llength $command]
    foreach arg $command {
        if {[string first " " $arg] > -1} {
            append cmdline '$arg'
        } else {
            append cmdline $arg
        }
        if {[incr i] < $x} { append cmdline " " }
    }

    if {$info(GuiMode)} {
        ## Try to find a graphical SU utility we can use.
        if {[::InstallJammer::GetDesktopEnvironment] eq "Gnome"} {
            set list {gksudo gksu gnomesu kdesudo kdesu xsu}
        } else {
            set list {kdesudo kdesu gksudo gksu gnomesu xsu}
        }

        foreach app $list {
            if {[auto_execok $app] eq ""} { continue }
            
            set cmd [list $app $cmdline]
            catch {exec $app --help} help
            if {$app eq "kdesu" || $app eq "kdesudo"} {
                set cmd [linsert $cmd 1 -d -c]
                if {$msg ne "" && [string match "*--comment*" $help]} {
                    set cmd [linsert $cmd 1 --comment $msg]
                }
            } elseif {$app eq "gksu" || $app eq "gksudo"} {
                if {$msg ne "" && [string match "*--message*" $help]} {
                    set cmd [linsert $cmd 1 --message $msg]
                }
            }

            if {!$wait} { lappend cmd & }
            catch { eval exec $cmd }
            return 1
        }
    }

    ## If we didn't find a GUI we could use, and we don't have a
    ## terminal to talk to, we really can't do anything.
    if {!$info(HaveTerminal)} { return 0 }

    ## We never found a good GUI to ask for the root password,
    ## so we'll just ask on the command line.

    if {[string is punct [string index $msg end]]} {
        set msg [string range $msg 0 end-1]
    }

    if {[auto_execok sudo] ne ""} {
        ## Always invalidate the sudo timestamp.  We don't want
        ## someone running an installer as root without knowing it.
        if {[catch {exec sudo -k} err]} { return 0 }

        set cmd [list sudo]
        if {$msg ne ""} { lappend cmd -p "\[sudo\] $msg: " }
        if {$wait} {
            eval exec $cmd $command
        } else {
            if {[catch {eval exec $cmd -v} err]} { return 0 }
            set res [catch {eval system sudo $cmdline &} err]
        }
    } else {
        puts  stdout "$msg\n\[su root\] "
        flush stdout
        if {!$wait} { append cmdline " &" }
        set res [system su -c \"$cmdline\"]
    }

    return 1
}

proc ::InstallJammer::GetFilesForPattern { patternString args } {
    set relative    1
    set patterns    [list]
    set installdir  [::InstallJammer::SubstText <%InstallDir%>]
    set patternlist [split [::InstallJammer::SubstText $patternString] \;]

    foreach pattern $patternlist {
        set pattern [string trim [::InstallJammer::SubstText $pattern]]
        if {$pattern eq ""} { continue }

        if {[file pathtype $pattern] ne "relative"} {
            set relative 0
            set pattern [::InstallJammer::Normalize $pattern]
        }

        lappend patterns $pattern
    }

    if {![llength $patterns]} { return }

    if {$relative} {
        ## All of our patterns are relative, so we can do a single, quick
        ## glob to find everything relative to the <%InstallDir%>.
        set opts $args
        lappend opts -dir $installdir

        set files [eval glob -nocomplain $opts $patterns]
    } else {
        set files [list]
        foreach pattern $patterns {
            set opts $args
            if {[file pathtype $pattern] eq "relative"} {
                lappend opts -dir $installdir
            }
            eval lappend files [eval glob -nocomplain $opts [list $pattern]]
        }
    }

    return $files
}

proc ::InstallJammer::StartProgress { varName total {current 0} } {
    global conf
    set conf(ProgressCurr)    0
    set conf(ProgressLast)    0
    set conf(ProgressTotal)   $total
    set conf(ProgressVarName) $varName
}

proc ::InstallJammer::ResetProgress {} {
    global conf
    set conf(ProgressLast) 0
}

proc ::InstallJammer::UpdateProgress { args } {
    set total   $::conf(ProgressTotal)
    set varName $::conf(ProgressVarName)
    set current [lindex $args end]

    set bytes [expr {$current - $::conf(ProgressLast)}]
    set ::conf(ProgressLast) $current

    incr ::conf(ProgressCurr) $bytes

    if {$varName ne ""} {
        set $varName [expr {round( ($::conf(ProgressCurr) * 100.0) / $total )}]
    }
}

proc ::InstallJammer::ReadProperties { data arrayName } {
    upvar 1 $arrayName array

    foreach line [split [string trim $data] \n] {
        set line [string trim $line]
        if {[set x [string first : $line]] >= 0} {
            set var [string trim [string range $line 0 [expr {$x-1}]]]
            set val [string trim [string range $line [expr {$x+1}] end]]
            set array($var) $val
        }
    }
}

proc ::InstallJammer::ReadPropertyFile { file arrayName } {
    upvar 1 $arrayName array
    ::InstallJammer::ReadProperties [read_textfile $file] array
}

proc ::InstallJammer::ShowUsageAndExit { {message ""} {title ""} } {
    global conf
    global info

    variable ::InstallJammer::CommandLineOptions

    ::InstallJammer::InitializeCommandLineOptions

    set head --
    if {$conf(windows)} { set head / }

    set usage ""

    if {$message ne ""} { append usage "$message\n\n" }
    append usage "Usage: [file tail [info nameofexecutable]] \[options ...\]"
    append usage "\n\nAvailable Options:"

    set len 0
    foreach option [array names CommandLineOptions] {
        if {$option eq "PREFIX"} { continue }

        lassign $CommandLineOptions($option) name var type x hide values desc

        if {$type eq "Boolean"} {
            set desc "$name <Yes or No>"
        } elseif {$type eq "Prefix"} {
            set desc "$name<OPTION> \[ARG\]"
        } elseif {$type eq "Switch"} {
            set desc $name
        } else {
            set desc "$name \[ARG\]"
        }

        set options($option) $desc

        if {[string length $desc] > $len} {
            set len [string length $desc]
        }
    }

    incr len 4
    set  pad [expr {$len + 3}]

    foreach option [lsort -dict [array names options]] {
        lassign $CommandLineOptions($option) name var type x hide values desc

        if {$hide} { continue }

        set desc   [::InstallJammer::SubstText $desc]
        set values [::InstallJammer::SubstText $values]

        set line "  [format %-${len}s $head$options($option)] $desc"

        append usage "\n[::InstallJammer::WrapText $line 0 $pad]"

        if {$type eq "Choice"} {
            set values  [lsort -dict $values]
            set last    [lindex $values end]
            set values  [lrange $values 0 end-1]
            set choices [string tolower "[join $values ", "] or $last"]

            set line "[string repeat " " $pad]Available values: $choices"
            append usage "\n[::InstallJammer::WrapLine $line 0 $pad]"
        }
    }

    append usage \n

    if {$conf(windows) || !$info(HaveTerminal)} {
        if {$title eq ""} { set title "Invalid Arguments" }
        ::InstallJammer::MessageBox -icon error -font "Courier 8" \
            -title $title -message $usage
    } else {
        puts $usage
    }

    ::exit [expr {$message eq "" ? 0 : 1}]
}

proc ::InstallJammer::ParseCommandLineArguments { argv } {
    global conf
    global info

    variable ::InstallJammer::CommandLineOptions
    variable ::InstallJammer::PassedCommandLineOptions
    variable ::InstallJammer::VirtualTextSetByCommandLine

    ::InstallJammer::ExecuteActions "Command Line Actions"

    ::InstallJammer::InitializeCommandLineOptions

    set i 0
    foreach arg $argv {
        if {[string tolower [string trimleft $arg -/]] eq "response-file"} {
            ::InstallAPI::ResponseFileAPI -do read -file [lindex $argv [incr i]]
            break
        }
        incr i
    }

    set len [llength $argv]
    for {set i 0} {$i < $len} {incr i} {
        set arg [lindex $argv $i]
        set opt [string tolower [string trimleft $arg -/]]

        ## The first argument of argv can be the name of our
        ## executable, so we need to check and skip it.
        if {$i == 0 && [file normalize $arg] eq [file normalize [info name]]} {
            continue
        }

        if {$opt eq "help" || $opt eq "?"} {
            ::InstallJammer::ShowUsageAndExit "" "Help"
        }

        if {$opt eq "v" || $opt eq "version"} {
            set message "InstallJammer Installer version $conf(version)\n\n"
            if {$info(RunningInstaller)} {
                append message "<%VersionHelpText%>"
            } else {
                append message "<%AppName%> <%Version%>"
            }

            if {$conf(windows)} {
                ::InstallJammer::MessageBox -default ok \
                    -title "InstallJammer Installer" -message [sub $message]
            } else {
                puts [sub "<%Version%> (<%InstallVersion%>)"]
                puts ""
                puts [sub $message]
            }

            ::exit 0
        }

        if {![info exists CommandLineOptions($opt)]} {
            set found 0

            if {[info exists CommandLineOptions(PREFIX)]} {
                foreach prefix $CommandLineOptions(PREFIX) {
                    if {[string match -nocase $prefix* $opt]} {
                        set found 1

                        set opt       [string trimleft $arg -/]
                        set xlen      [string length $prefix]
                        set prefixopt [string range $opt $xlen end]

                        set opt $prefix
                        break
                    }
                }
            }

            if {!$found} {
                ::InstallJammer::ShowUsageAndExit "invalid option '$arg'"
                return
            }
        }

        lassign $CommandLineOptions($opt) name var type debug hide value desc
        set choices [::InstallJammer::SubstText $value]

        if {$type eq "Switch"} {
            if {$value eq ""} {
                set val 1
            } else {
                set val $value
            }
        } else {
            if {[incr i] == $len} {
                ## Option without an argument.
                ::InstallJammer::ShowUsageAndExit \
                    "no argument given for option '$arg'"
            }

            set val [lindex $argv $i]

            if {$type eq "Choice"} {
                set val  [string tolower $val]
                set vals [string tolower $choices]
                if {[set x [lsearch -exact $vals $val]] < 0} {
                    ::InstallJammer::ShowUsageAndExit \
                        "invalid value given for option '$arg'"
                }

                set val [lindex $choices $x]
            } elseif {$type eq "Boolean"} {
                if {![string is boolean -strict $val]} {
                    ::InstallJammer::ShowUsageAndExit \
                        "invalid value given for option '$arg'"
                }

                if {$value ne ""} {
                    if {[string is true $val]} {
                        set val [lindex $value 0]
                    } else {
                        set val [lindex $value 1]
                    }
                }
            } elseif {$type eq "Prefix"} {
                if {![info exists prefixopt]}  {
                    ::InstallJammer::ShowUsageAndExit \
                        "no option specified for '$arg'"
                }

                set suffix $prefixopt

                if {$value ne ""} {
                    set opt     [string tolower $prefixopt]
                    set choices [string tolower $choices]
                    if {[set x [lsearch -exact $choices $opt]] < 0} {
                        ::InstallJammer::ShowUsageAndExit \
                            "invalid option '$prefixopt'"
                    }

                    set suffix [lindex $value $x]
                }

                append var $suffix
            }
        }

        set info($var) $val
        set PassedCommandLineOptions($opt) $val
        set VirtualTextSetByCommandLine($var) $val
    }

    ::InstallJammer::SetupModeVariables

    ::InstallJammer::ExecuteActions "Setup Actions"

    if {$info(ShowConsole)} {
        ::InstallJammer::InitializeGui
        if {!$conf(windows)} { SourceCachedFile console.tcl }
        console show
        debugging on
    }

    if {!$info(GuiMode) && !$conf(windows)} {
        if {![catch { exec stty size } result]
            && [scan $result "%d %d" height width] == 2} {
            set conf(ConsoleWidth)  $width
            set conf(ConsoleHeight) $height
        }
    }
}

proc ::InstallJammer::SetupModeVariables {} {
    global conf
    global info

    ## If the command-line arguments have given us a mode that
    ## doesn't exist in our list of possible modes, use whatever
    ## the default mode is (Standard).
    if {[lsearch -exact $conf(modes) $info($conf(mode))] < 0} {
        set mode [lindex $conf(modes) 0]
        debug "Bad $conf(mode) \"$info($conf(mode))\": using $mode mode"
        set info($conf(mode)) $mode
    }

    set mode $info($conf(mode))
    set info(GuiMode)     [expr {$mode eq "Default" || $mode eq "Standard"}]
    set info(SilentMode)  [string equal $mode "Silent"]
    set info(DefaultMode) [string equal $mode "Default"]
    set info(ConsoleMode) [string equal $mode "Console"]
}

proc ::InstallJammer::CommonExit { {cleanupTmp 1} } {
    global conf

    catch { 
        if {$conf(windows) && $conf(UpdateWindowsRegistry)} {
            registry broadcast Environment -timeout 1
        }
    }

    catch {
        if {$conf(RestartGnomePanel)
            && [::InstallJammer::GetDesktopEnvironment] eq "Gnome"} {
            set pid [::InstallAPI::FindProcesses -name gnome-panel]
            if {$pid ne ""} { catch {exec kill -HUP $pid} }
        }
    }

    catch { ::InstallJammer::ExecuteActions "Exit Actions" }

    catch {
        foreach chan [file channels] {
            if {[string match "std*" $chan]} { continue }
            catch {close $chan}
        }
    }

    if {$cleanupTmp} {
        catch {
            ::InstallJammer::WriteDoneFile
            ::InstallJammer::CleanupTmpDirs
        }
    }

    if {[info exists ::debugfp]} { catch { close $::debugfp } }
}

proc ::InstallJammer::WrapText { string {width 0} {start 0} } {
    global conf

    if {$width == 0} { set width $conf(ConsoleWidth) }

    set splitstring {}
    foreach line [split $string "\n"] {
	lappend splitstring [::InstallJammer::WrapLine $line $width $start]
    }
    return [join $splitstring "\n"]
}

proc ::InstallJammer::WrapLine { line {width 0} {start 0} } {
    global conf

    if {$width == 0} { set width $conf(ConsoleWidth) }

    set slen  0
    set words [split $line " "]
    set line  [lindex $words 0]
    set lines [list]
    foreach word [lrange $words 1 end] {
	if {[string length $line] + [string length " $word"] > $width} {
	    lappend lines $line

            set slen $start
	    set line [string repeat " " $slen]$word
	} else {
            append line " $word"
        }
    }

    if {$line ne ""} { lappend lines $line }

    return [join $lines "\n"]
}

proc ::InstallJammer::DisplayConditionFailure { id } {
    set string [::InstallJammer::SubstText [$id get FailureMessage]]
    set list   [split $string |]

    set icon    ""
    set title   ""
    set message [string trim $string]

    if {[llength $list] == 2} {
        set title   [string trim [lindex $list 0]]
        set message [string trim [lindex $list 1]]
    } elseif {[llength $list] >= 3} {
        set icon    [string trim [lindex $list 0]]
        set title   [string trim [lindex $list 1]]
        set message [string trim [join [lrange $list 2 end] |]]
    }

    if {$icon eq ""} { set icon "error" }
    if {$title eq ""} { set title [sub "<%ErrorTitle%>"] }

    if {$message ne ""} {
        ::InstallJammer::Message -icon $icon -title $title -message $message
    }

    set focus [string trim [$id get FailureFocus]]
    if {$focus ne "" && [::InstallJammer::InGuiMode]} {
        set focus [::InstallAPI::GetWidgetPath -widget $focus]
        if {[winfo exists $focus]} { focus -force $focus }
    }
}

proc ::InstallJammer::GetAllTreeNodes { tree {parent "root"} } {
    set nodes {}
    foreach node [$tree nodes $parent] {
        lappend nodes $node
        eval lappend nodes [::InstallJammer::GetAllTreeNodes $tree $node]
    }
    return $nodes
}

proc ::InstallJammer::IsValidFilename {name} {
    return [expr {[regexp {[:\*\?\"<>|]} $name] == 0}]
}

proc ::InstallJammer::IsValidPath {path} {
    global conf

    set list [file split $path]
    if {$conf(windows) && [string match {[a-zA-Z]:/} [lindex $list 0]]} {
        set list [lrange $list 1 end]
    }
    foreach name $list {
        if {![::InstallJammer::IsValidFilename $name]} { return 0 }
    }
    return 1
}

proc ::InstallJammer::InGuiMode {} {
    return [info exists ::tk_patchLevel]
}

proc ::InstallJammer::WizardExists {} {
    global info
    if {![::InstallJammer::InGuiMode]} { return 0 }
    return [expr {[info exists info(Wizard)] && [winfo exists $info(Wizard)]}]
}

proc ::InstallJammer::ConsoleClearLastLine { {len 0} } {
    global conf
    if {!$len} {
        if {[info exists conf(ConsoleProgressLastLen)]} {
            set len $conf(ConsoleProgressLastLen)
            if {!$len} { return }
        } else {
            return
        }
    }
    puts -nonewline [string repeat   $len]
    puts -nonewline [string repeat " " $len]
    puts -nonewline [string repeat   $len]
}

proc ::InstallJammer::ConsoleProgressBar { percent } {
    global conf

    if {![info exists conf(ConsoleProgressWidth)] || $percent == 0} {
        SafeSet conf(ConsoleProgressNewline) 0
	SafeSet conf(ConsoleProgressFormat) {[%s%s] %d%%}
	set s [string map {%s "" %d "" %% %} $conf(ConsoleProgressFormat)]
	set conf(ConsoleProgressWidth) [string length $s]
        set conf(ConsoleProgressLastLen) 0
	SafeSet conf(ConsoleProgressCompletedHash) =
	SafeSet conf(ConsoleProgressIncompleteHash) -
    }

    set len  0
    set cols $conf(ConsoleWidth)
    ::InstallJammer::ConsoleClearLastLine

    set width [expr {$cols - 2 - $conf(ConsoleProgressWidth)}]
    if {[string match "*%d*" $conf(ConsoleProgressFormat)]} { incr width -3 }
    set pct   [expr {(100 * $percent) / 100}]
    set cnt   [expr {($width * $percent) / 100}]
    set done  [expr {$width - $cnt}]
    set args  [list $conf(ConsoleProgressFormat)]
    if {$conf(ConsoleProgressCompletedHash) ne ""} {
	lappend args [string repeat $conf(ConsoleProgressCompletedHash) $cnt]
    }
    if {$conf(ConsoleProgressIncompleteHash) ne ""} {
	lappend args [string repeat $conf(ConsoleProgressIncompleteHash) $done]
    }
    if {[string match "*%d*" $conf(ConsoleProgressFormat)]} {
	lappend args $pct
    }

    set string [eval format $args]
    puts -nonewline $string
    set conf(ConsoleProgressLastLen) [string length $string]

    if {$percent == 100} {
        ::InstallJammer::ConsoleClearLastLine
        if {$conf(ConsoleProgressNewline)} { puts "" }
    }
    flush stdout
}

proc ::InstallJammer::MountSetupArchives {} {
    global conf
    global info

    set found 0
    if {[info exists info(ArchiveFileList)]} {
        foreach file $info(ArchiveFileList) {
            set file [file join $info(InstallSource) $file]
            if {[file exists $file]} {
                set found 1
                installkit::Mount $file $conf(vfs)
            }
        }
    }
    return $found
}

proc ::InstallJammer::GetCommonInstallkit { {base ""} } {
    global info
    ::InstallJammer::InstallInfoDir
    set kit [file join $info(InstallJammerRegistryDir) \
        $info(Platform) installkit$info(Ext)]
    set opts [list -noinstall -o $kit]
    if {$base ne ""} { lappend opts -w $base }
    file mkdir [file dirname $kit]

    set main [::InstallJammer::TmpDir main[pid].tcl]
    set fp [open $main w]
    puts $fp {
        if {[llength $argv]} {
            uplevel #0 [list source [lindex $argv end]]
        }
    }
    close $fp
    return  [eval ::InstallJammer::Wrap $opts [list $main]]
}

proc ::InstallJammer::GetAllWidgets {parent} {
    set widgets [list $parent]
    foreach w [winfo children $parent] {
        lappend widgets $w
        eval lappend widgets [::InstallJammer::GetAllWidgets $w]
    }
    return $widgets
}

package require Itcl

proc ::InstallJammer::Class { name body } {
    set matches [regexp -all -inline {\s+writable attribute\s+([^\s]+)} $body]
    foreach {match varName} $matches {
        append body "method $varName {args} { cfgvar $varName \$args }\n"
    }

    set matches [regexp -all -inline {\s+readable attribute\s+([^\s]+)} $body]
    foreach {match varName} $matches {
        append body "method $varName {args} { set $varName }\n"
    }

    set map [list]
    lappend map "writable attribute" "public variable"
    lappend map "readable attribute" "private variable"

    set body [string map $map $body]

    itcl::class ::$name $body
}

::itcl::class Object {
    constructor {args} {
        eval configure $args
        set ::InstallJammer::ObjMap([namespace tail $this]) [incr objc]
    }

    destructor {
        unset ::InstallJammer::ObjMap([namespace tail $this])
    }

    method destroy {} {
        ::itcl::delete object $this
    }

    method cfgvar { args } {
        set option -[lindex $args 0]
        if {[llength $args] == 2} {
            configure $option [lindex $args 1]
            if {![catch {$this type} type] && $type eq "file"} {
                lappend ::conf(modifiedFiles) $this
            }
        }
        return [cget $option]
    }

    method serialize {} {
        set return [list]
        foreach list [configure] {
            set opt [lindex $list 0]
            set def [lindex $list end-1]
            set val [lindex $list end]
            if {$def == $val} { continue }
            lappend return $opt $val
        }
        return $return
    }

    common objc 0
} ; ## ::itcl::class Object

::itcl::class TreeObject {
    inherit Object

    constructor { args } {
        set id [namespace tail $this]

        eval configure $args

        if {!$temp && $parent ne ""} {
            if {![::InstallJammer::ObjExists $parent]} {
                ## If our parent doesn't exist, we don't exist.
                destroy
            } else {
                $parent children insert $index $id
            }
        }
        if {$name ne ""} { set ::InstallJammer::names($name) $id }
    }

    destructor {
        if {!$temp && $parent ne "" && [::InstallJammer::ObjExists $parent]} {
            $parent children remove $id
        }

        foreach child $children {
            $child destroy
        }

        if {!$temp} { CleanupAlias }
    }

    method serialize {} {
        set return [list]
        foreach list [configure] {
            set opt [lindex $list 0]
            if {$opt eq "-id" || $opt eq "-index"} { continue }
            set def [lindex $list end-1]
            set val [lindex $list end]
            if {$opt eq "-name" && $val eq [string tolower $id]} { continue }
            if {$def == $val} { continue }
            lappend return $opt $val
        }
        return $return
    }

    method CleanupAlias {} {
        variable ::InstallJammer::aliases
        variable ::InstallJammer::aliasmap

        if {[info exists aliasmap($id)]} {
            unset -nocomplain aliases($aliasmap($id))
            unset aliasmap($id)
            set ::InstallJammer::Properties($id,Alias) ""
        }
    }

    method parent { args } {
        if {[lempty $args]} { return $parent }

        if {![string equal $args "recursive"]} {
            return [set parent [lindex $args 0]]
        }

        set x    $parent
        set list [list]
        while {[string length $x]} {
            set list [linsert $list 0 $x]
            set x [$x parent]
        }
        return $list
    }

    method reparent { newParent } {
        ## If this is already our parent, don't do anything.
        if {$parent eq $newParent} { return }

        ## If we have an old parent, remove us from their children.
        if {$parent ne ""} { $parent children remove $id }

        ## Add ourselves to the new parent.
        set parent $newParent
        if {$parent ne ""} { $parent children add $id }
    }

    method children { args } {
        if {![llength $args]} { return $children }

        lassign $args command obj
        switch -- $command {
            "add" {
                children insert end $obj
            }

            "index" {
                return [lsearch -exact $children $obj]
            }

            "insert" {
                lassign $args command index obj
                if {$index eq "end"} {
                    lappend children $obj
                } else {
                    set children [linsert $children $index $obj]
                }
            }

            "remove" - "delete" {
                set children [lremove $children $obj]
            }

            "reorder" {
                if {[llength $obj]} { set children $obj }
            }

            "recursive" {
                return [::InstallJammer::ObjectChildrenRecursive $this]
            }
        }
    }

    method is { args } {
        if {[llength $args] == 1} {
            return [string equal [type] [lindex $args 0]]
        } else {
            return [expr {[lsearch -exact $args [type]] > -1}]
        }
    }

    method index {} {
        if {[string length $parent]} { return [$parent children index $id] }
    }

    method component {} {
        return "ClassObject"
    }

    method id        { args } { eval cfgvar id        $args }
    method name      { args } { eval cfgvar name      $args }
    method type      { args } { eval cfgvar type      $args }
    method alias     { args } { eval cfgvar alias     $args }
    method active    { args } { eval cfgvar active    $args }
    method comment   { args } { eval cfgvar comment   $args }
    method platforms { args } { eval cfgvar platforms $args }

    public variable id      ""
    public variable temp    0
    public variable name    ""
    public variable type    ""
    public variable index   "end"
    public variable active  1
    public variable parent  ""
    public variable comment ""

    public variable platforms [list]

    protected variable children [list]

    private variable oldalias ""
    public variable alias "" {
	if {$oldalias ne ""} {
	    $this CleanupAlias
	}
	set oldalias $alias

	if {$alias ne ""} {
	    set ::InstallJammer::aliases($alias) $id
	    set ::InstallJammer::aliasmap($id) $alias
            set ::InstallJammer::Properties($id,Alias) $alias
	}
    }
}

::itcl::class InstallType {
    inherit TreeObject

    constructor { args } {
        eval configure $args
    } {
        set type installtype
        eval configure $args
    }

    method class {} {
        return ::InstallType
    }

    method widget { args } {}
    method setup  { args } { eval cfgvar setup $args }
    method component {} {}

    public variable setup  ""
}

itcl::class File {
    inherit TreeObject

    constructor {args} {
	eval configure $args
    } {
        eval configure $args
    }

    method class {} {
        return ::File
    }

    method srcfile {} {
        if {$srcfile eq ""} { ::set srcfile [file join $::conf(vfs) $id] }
        return $srcfile
    }

    method checkFileMethod { dest } {
        ::set method [filemethod]
        if {$method eq ""} { ::set method [$parent filemethod] }

        ::set doInstall 1

        if {![info exists exists] && $method ne "Always overwrite"} {
            ::set exists [file exists $dest]
        }

        switch -- $method {
            "Update files with more recent dates" {
                ## We only want to overwrite if the file we have is newer
                ## than the one already installed.  If the one we have is
                ## older, skip it.
                if {$exists && [file mtime $dest] >= $mtime} {
                    ::set doInstall 0
                }
            }

            "Update files with a newer version" {
                ## We want to overwrite the file if we have a newer version
                ## than the one stored.  If there isn't one stored, we'll go
                ## ahead and store ours.
                global versions
                if {$exists && [info exists versions($dest)]} {
                    ::set c [package vcompare $version $versions($dest)]
                    if {$c == 0 || $c == -1} { ::set doInstall 0 }
                }
            }

            "Always overwrite files" {
                ## We want to always overwrite the file.
                ## This is the default action, so we do nothing.
            }

            "Never overwrite files" {
                ## We don't want to overwrite.  If the file exists, skip it.
                if {$exists} { ::set doInstall 0 }
            }

            "Prompt user" {
                if {$exists} {
                    ::set txt "<%FileOverwriteText%>"
                    ::set msg [::InstallJammer::SubstText $txt]
                    ::set ans [::InstallJammer::MessageBox -type yesno \
                        -name FileOverwrite -title "File Exists" \
                        -message $msg]
                    ::set doInstall [expr {$ans eq "yes"}]
                }
            }
        }

        return $doInstall
    }

    method destdir {} {
        return [::InstallJammer::SubstText [destdirname]]
    }

    method destdirname {} {
        return $directory
    }

    method destfile {} {
	return [file join [destdir] [destfilename]]
    }

    method destfilename {} {
	if {$targetfilename eq ""} {
	    return [file tail $name]
	} else {
	    return [::InstallJammer::SubstText $targetfilename]
	}
    }

    method srcfilename {} {
    	return [file tail $name]
    }

    method createdir {} {
	::InstallJammer::CreateDir [destdir]
    }

    method install {} {
	global conf

	if {![::InstallJammer::PauseCheck]} { return 0 }

        ::set dest [install[type]]

	if {![::InstallJammer::PauseCheck]} { return 0 }

        if {$conf(windows)} {
            ::InstallJammer::SetPermissions $dest $attributes
        } else {
            if {$permissions eq ""} {
                ::set permissions $::info(DefaultDirectoryPermission)
            }

            if {[type] eq "dir" && [info commands output] eq "output"} {
                output [list :DIR $dest $permissions]
                ::InstallJammer::SetPermissions $dest 00777
            } else {
                ::InstallJammer::SetPermissions $dest $permissions
            }
        }

        return 1
    }

    method installdir {} {
        createdir
    }

    method installlink {} {
        ::set dest [destfile]

        if {![checkFileMethod $dest]} { return }

        createdir

        if {[file exists $dest] && [catch { file delete -force $dest } error]} {
            return -code error $error
        }

        if {[catch { exec ln -s $linktarget $dest } error]} {
            return -code error $error
        }

        if {$version eq ""} {
            ::set version $::info(InstallVersion)
        } else {
            ::set version [::InstallJammer::SubstText $version]
        }

        ::InstallJammer::LogFile $dest
        ::InstallJammer::SetVersionInfo $dest $version

        return $dest
    }

    method installfile { {dest ""} {createDir 1} {checkMethod 1} {logFile 1} } {
	global conf
	global info

        if {$createDir} {
            createdir
        }

	::set src [srcfile]
        if {![file exists $src] && [info exists info(ArchiveFileList)]} {
            while {![file exists $src]} {
                ::InstallJammer::PauseInstall
                output [list :DISC [[parent] name]]
                ::InstallJammer::MountSetupArchives
            }
        }

        if {$dest eq ""} { ::set dest [destfile] }

        if {$version eq ""} {
            ::set version $::info(InstallVersion)
        } else {
            ::set version [::InstallJammer::SubstText $version]
        }

        ::set doInstall 1
        if {$checkMethod} {
            ::set doInstall [checkFileMethod $dest]
        }

	::set info(FileSize) $size
	if {!$doInstall} {
            ::set progress ::InstallJammer::IncrProgress
            if {[::InstallJammer::CommandExists $progress]} { $progress $size }
	    return $dest
	}

        if {$permissions eq ""} {
            if {$conf(windows)} {
                ::set permissions 0666
            } else {
                ::set permissions $info(DefaultFilePermission)
            }
        }

	if {!$size} {
            ## Empty file.
	    if {[catch { open $dest w $permissions } err]} {
		return -code error $err
	    }
	    close $err
	} else {
	    ::InstallJammer::unpack $src $dest $permissions
	}

        if {$info(InstallStopped)} { return }

        ## Set the modified time to the one we have stored.
        if {$mtime} {
            file mtime $dest $mtime
        }

        if {$logFile} {
            ::InstallJammer::LogFile $dest
            ::InstallJammer::SetVersionInfo $dest $version
        }

	return $dest
    }

    method group {} {
        return [lindex [parent recursive] 1]
    }

    method set { args } {
        return [eval ::InstallJammer::SetObjectProperties $id $args]
    }

    method get { property {varName ""} } {
        if {[string length $varName]} {
            upvar 1 $varName var
            return [::InstallJammer::GetObjectProperty $id $property var]
        } else {
            return [::InstallJammer::GetObjectProperty $id $property]
        }
    }

    method isfile {} {
        return [is file link]
    }

    method object {} {
        return ::FileObject
    }

    method filemethod { {newMethod ""} } {
        if {$newMethod ne ""} {
            if {![info exists ::InstallJammer]} {
                variable ::InstallJammer::PropertyMap
                ::set n [lsearch -exact $PropertyMap(FileUpdateMethod) \
                    $newMethod]
                if {$n < 0} {
                    return -code error [BWidget::badOptionString method \
                        $newMethod $PropertyMap(FileUpdateMethod)]
                }
                ::set newMethod $n
            }
            ::set filemethod $newMethod
        }

        if {[string is integer -strict $filemethod]} {
            return [lindex $::InstallJammer::PropertyMap(FileUpdateMethod) \
                $filemethod]
        }
        return $filemethod
    }

    method component {} {}

    method name               { args } { eval cfgvar name              $args }
    method size               { args } { eval cfgvar size              $args }
    method mtime              { args } { eval cfgvar mtime             $args }
    method version            { args } { eval cfgvar version           $args }
    method location           { args } { eval cfgvar location          $args }
    method directory          { args } { eval cfgvar directory         $args }
    method savefiles          { args } { eval cfgvar savefiles         $args }
    method linktarget         { args } { eval cfgvar linktarget        $args }
    method attributes         { args } { eval cfgvar attributes        $args }
    method permissions        { args } { eval cfgvar permissions       $args }
    method targetfilename     { args } { eval cfgvar targetfilename    $args }
    method compressionmethod  { args } { eval cfgvar compressionmethod $args }

    public variable type               "file"
    public variable name               ""
    public variable size               0
    public variable mtime              0
    public variable srcfile            ""
    public variable version            ""
    public variable location           ""
    public variable directory          ""
    public variable savefiles          ""
    public variable linktarget         ""
    public variable filemethod         ""
    public variable attributes         ""
    public variable permissions        ""
    public variable targetfilename     ""
    public variable compressionmethod  ""

    private variable exists

} ; ## itcl::class File

::itcl::class InstallComponent {
    inherit TreeObject

    constructor { args } { 
        eval configure $args
    } {
        ::set name [string tolower $id]

        eval configure $args

        ## If this is a temporary object, we don't want to append
        ## it to the lists or do any further setup.
        if {$temp} {
            if {[string length $parent]} { $parent children remove $id }
            return
        }

        if {![info exists ::InstallJammer] && [get Include incl]} {
            if {$::info(Testing) && $incl eq "Include only when not testing"
                || !$::info(Testing) && $incl eq "Include only when testing"} {
                destroy
                return
            }
        }

        if {[info exists ::InstallJammer::Properties($id,Alias)]
            && [string length $::InstallJammer::Properties($id,Alias)]} {
            $this set Alias $::InstallJammer::Properties($id,Alias)
        }

        ## Do some special setup if this is a pane, and we're
        ## building it from within an installer.
        if {![info exists ::InstallJammer] && [ispane]} {
            ::set install $parent
            ::set wizard  $::info(Wizard)

            ::set node $parent
            if {[$parent is installtype]} { ::set node root }

            if {[string equal $install "Common"]} {
                ::InstallJammer::CreateWindow $wizard $id
            } elseif {[string equal $install $::info($::conf(mode))]} {
                ::set create \
                    [list ::InstallJammer::CreateWindow $wizard $id]

                get WizardOptions stepopts
                eval [list $wizard insert step end $node $id \
                    -createcommand $create] $stepopts

                if {[is window]} {
                    $wizard itemconfigure $id -appendorder 0
                }
            }
        }
    }

    destructor {
        if {!$temp} {
            array unset ::InstallJammer::Properties $id,*

            foreach lang [::InstallJammer::GetLanguageCodes] {
                ::msgcat::mcunset $lang $id,*
            }

            foreach condition $conditions {
                catch { $condition destroy }
            }
        }
    }

    method class {} {
        return ::InstallComponent
    }

    method set { args } {
        if {[llength $args] == 0} { return }
        if {[llength $args] == 1} { ::set args [lindex $args 0] }
        eval [list ::InstallJammer::SetObjectProperties $id] $args
    }

    method get { property {varName ""} } {
        if {[string length $varName]} {
            upvar 1 $varName var
            return [::InstallJammer::GetObjectProperty $id $property var]
        } else {
            return [::InstallJammer::GetObjectProperty $id $property]
        }
    }

    method getText { field args } {
        eval [list ::InstallJammer::GetText $id $field] $args
    }

    method setText { languages args } {
        if {[llength $args] == 0} { return }
        if {[llength $args] == 1} { ::set args [lindex $args 0] }
        eval [list ::InstallJammer::SetVirtualText $languages $id] $args
    }

    method properties { arrayName args } {
        upvar 1 $arrayName array
        return [eval ::InstallJammer::ObjectProperties $id array $args]
    }

    method ispane {} {
        return [expr {[is "pane"] || [is "window"]}]
    }

    method object {} {
        if {[ispane]} {
            variable ::InstallJammer::panes
            return $panes($component)
        } elseif {[is action]} {
            variable ::InstallJammer::actions
            return $actions($component)
        } elseif {[is actiongroup]} {
            return ActionGroupObject
        }
    }

    method initialize {} {
        [object] initialize $id
    }

    method widget { command widget args } {
        switch -- $command {
            "get" {
                if {[info exists widgetData($widget,widget)]} {
                    return $widgetData($widget,widget)
                }
            }

            "set" {
                if {[lsearch -exact $widgets $widget] < 0} {
                    lappend widgets $widget
                }

                foreach [list opt val] $args {
                    ::set widgetData($widget,[string range $opt 1 end]) $val
                }
            }
            
            "type" {
                if {[info exists widgetData($widget,type)]} {
                    return $widgetData($widget,type)
                }
                return text
            }
        }
    }

    method widgets {} {
        return $widgets
    }

    method conditions { args } {
        if {[lempty $args]} { return $conditions }

        lassign $args command obj
        switch -- $command {
            "add" {
                conditions insert end $obj
            }

            "index" {
                return [lsearch -exact $conditions $obj]
            }

            "insert" {
                lassign $args command index obj
                if {[lsearch -exact $conditions $obj] > -1} { return }

                if {$index eq "end"} {
                    lappend conditions $obj
                } else {
                    ::set conditions [linsert $conditions $index $obj]
                }
            }

            "remove" - "delete" {
                ::set conditions [lremove $conditions $obj]
            }

            "reorder" {
                ::set conditions $obj
            }
        }

        return
    }

    method checkConditions { {when ""} } {
        if {[ispane]} {
            global info
            ::set info(CurrentPane) $id
        }

        ::set return 1
        if {[llength $conditions]} {
            ::set conditionlist [list]

            foreach cid $conditions {
                if {![::InstallJammer::ObjExists $cid]} { continue }

                if {$when eq "" || [$cid get CheckCondition] eq $when} {
                    lappend conditionlist $cid
                }
            }

            if {[llength $conditionlist]} {
                ::set msg "Checking conditions for $id - $title"
                if {$when ne ""} { append msg " - $when" }
                debug $msg $id

                foreach cid $conditionlist {
                    if {![$cid active]} {
                        debug "Skipping condition $cid - [$cid title] -\
                                condition is inactive" $cid
                        continue
                    }

                    debug "Checking condition $cid - [$cid title]" $cid
                    ::set result [$cid check 0]

                    if {!$result} {
                        debug "Condition failed"
                        ::set return 0
                        lappend failures $cid
                        if {$operator eq "AND"} {
                            break
                        }
                    } else {
                        debug "Condition passed"
                        if {$operator eq "OR"} {
                            ::set return 1
                            break
                        }
                    }
                }
            }
        }

        if {!$return} {
            ::InstallJammer::DisplayConditionFailure [lindex $failures 0]
        }

        return $return
    }

    method execute {} {
        if {$type ne "action"} { return }

        ::set executed 1

        debug "Executing action $id - [$id title]" $id

        ::set ::info(CurrentAction) $id
        ::InstallJammer::CurrentObject push $id

        if {[info exists ::InstallJammer::tests(before,$id)]} {
            inject run before,$id
        } elseif {[info exists ::InstallJammer::tests(before,$type)]} {
            inject run before,$type
        }

        ## Remember our current directory.
        if {[file exists .]} { ::set pwd [pwd] }

        ::set err [catch {::InstallJammer::actions::$component $this} res]

        ## Actions can sometimes change to a directory.  We want
        ## to make sure to change back if the action didn't do
        ## that itself.
        if {[info exists pwd] && [file exists .]
            && [file exists $pwd] && $pwd ne [pwd]} {
            cd $pwd
        }

        if {[info exists ::InstallJammer::tests(after,$id)]} {
            inject run after,$id
        } elseif {[info exists ::InstallJammer::tests(after,$type)]} {
            inject run after,$type
        }

        ::InstallJammer::CurrentObject pop

        if {$err && ![get IgnoreErrors]} {
            ::set msg "Error in action $component\n\n$::errorInfo"
            return -code error $msg
        }

        return $res
    }

    method setup       { args } { eval cfgvar setup       $args }
    method title       { args } { eval cfgvar title       $args }
    method window      { args } { eval cfgvar window      $args }
    method created     { args } { eval cfgvar created     $args }
    method command     { args } { eval cfgvar command     $args }
    method executed    { args } { eval cfgvar executed    $args }
    method operator    { args } { eval cfgvar operator    $args }
    method component   { args } { eval cfgvar component   $args }
    method arguments   { args } { eval cfgvar arguments   $args }
    method description { args } { eval cfgvar description $args }

    public variable type        "installcomponent"
    public variable setup       ""
    public variable title       ""
    public variable window      ""
    public variable created     0
    public variable executed    0
    
    public variable operator    "AND"
    public variable component   ""
    public variable arguments   ""
    public variable conditions  [list]
    public variable description ""

    private variable widgets    [list]
    private variable widgetData
} ; ## ::itcl::class InstallComponent

::itcl::class FileGroup {
    inherit InstallComponent

    constructor { args } {
        eval configure $args
    } {
        eval configure $args
        ::set setup Install
    }

    method class {} {
        return ::FileGroup
    }

    method install {} {
        global conf

        ::set dir [directory]

        ::InstallJammer::CreateDir $dir

        if {$conf(windows)} {
            ::InstallJammer::SetPermissions $dir [get Attributes]
        } else {
            ::InstallJammer::SetPermissions $dir [get Permissions]
        }
    }

    method destdirname {} {
        return [get Destination]
    }

    method directory {} {
        return [::InstallJammer::SubstText [destdirname]]
    }

    method version {} {
        return [get Version]
    }

    method filemethod {} {
        return [get FileUpdateMethod]
    }

    method object {} {
        return ::FileGroupObject
    }

    method compressionmethod {} {
        return [get CompressionMethod]
    }

    public variable type "filegroup"
} ; ## ::itcl::class FileGroup

::itcl::class Component {
    inherit InstallComponent

    constructor { args } {
        eval configure $args
    } {
        eval configure $args
        ::set setup Install
    }

    method class {} {
        return ::Component
    }

    method object {} {
        return ::ComponentObject
    }

    public variable type "component"
} ; ## ::itcl::class Component

::itcl::class SetupType {
    inherit InstallComponent

    constructor { args } {
        eval configure $args
    } {
        eval configure $args
        ::set setup Install
    }

    method class {} {
        return ::SetupType
    }

    method object {} {
        return ::SetupTypeObject
    }

    public variable type "setuptype"
} ; ## ::itcl::class SetupType

::itcl::class Condition {
    inherit TreeObject

    constructor { args } {
        ::set id [namespace tail $this]
        eval configure $args

        if {[::InstallJammer::ObjExists $parent]} {
            $parent conditions add $id
        }
    }

    destructor {
        if {[::InstallJammer::ObjExists $parent]} {
            $parent conditions remove $id
        }
    }

    method class {} {
        return ::Condition
    }

    method serialize {} {
        ::set return [list]
        foreach list [configure] {
            ::set opt [lindex $list 0]
            if {$opt eq "-id"} { continue }

            ::set def [lindex $list end-1]
            ::set val [lindex $list end]
            if {$def == $val} { continue }
            lappend return $opt $val
        }
        return $return
    }

    method set { args } {
        return [eval ::InstallJammer::SetObjectProperties $id $args]
    }

    method get { property {varName ""} } {
        if {[string length $varName]} {
            upvar 1 $varName var
            return [::InstallJammer::GetObjectProperty $id $property var]
        } else {
            return [::InstallJammer::GetObjectProperty $id $property]
        }
    }

    method properties { arrayName args } {
        upvar 1 $arrayName array
        return [eval ::InstallJammer::ObjectProperties $id array $args]
    }

    method object {} {
        return $::InstallJammer::conditions($component)
    }

    method check { {showError 1} } {
        ::set ::info(CurrentCondition) $id
        ::InstallJammer::CurrentObject push $id

        if {[info exists ::InstallJammer::tests(before,$id)]} {
            inject run before,$id
        } elseif {[info exists ::InstallJammer::tests(before,$component)]} {
            inject run before,$component
        }

        ::set res [string is true [::InstallJammer::conditions::$component $id]]
        if {!$res && $showError} {
            ::InstallJammer::DisplayConditionFailure $id
        }

        if {[info exists ::InstallJammer::tests(after,$id)]} {
            inject run after,$id
        } elseif {[info exists ::InstallJammer::tests(after,$component)]} {
            inject run after,$component
        }

        ::InstallJammer::CurrentObject pop

        ::set passed $res
    }

    method name {} {
    }

    method type {} {
        return $type
    }

    method id        { args } { eval cfgvar id        $args }
    method title     { args } { eval cfgvar title     $args }
    method active    { args } { eval cfgvar active    $args }
    method passed    { args } { eval cfgvar passed    $args }
    method parent    { args } { eval cfgvar parent    $args }
    method component { args } { eval cfgvar component $args }

    public variable id        ""
    public variable type      "condition"
    public variable title     ""
    public variable active    1
    public variable passed    -1
    public variable parent    ""
    public variable component ""
} ; ## ::itcl::class Condition
Added lib/conditions.tcl.










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::InstallJammer::LoadConditions {} {
    global conf
    global preferences

    if {[string length $preferences(CustomConditionDir)]} {
        set dir $preferences(CustomConditionDir)
        lappend dirs $dir
        eval lappend dirs [glob -nocomplain -type d -dir $dir *]
    }

    set dir [file join $conf(lib) Conditions]
    eval lappend dirs [glob -nocomplain -type d -dir $dir *]

    foreach dir $dirs {
        if {$dir eq $preferences(CustomConditionDir)} {
            set group "Custom Conditions"
        } else {
            set group [file tail $dir]
        }
        set name [::InstallJammer::StringToTitle $group]
        foreach file [glob -nocomplain -directory $dir *.condition] {
            set ::InstallJammer::loadconditions::group     $name
            set ::InstallJammer::loadconditions::condition ""
            catch {
                namespace eval ::InstallJammer::loadconditions [read_file $file]
            }
        }
    }
}

proc ::InstallJammer::loadconditions::Condition { name {title ""} } {
    variable group
    variable condition
    variable ::InstallJammer::conditions

    if {[info exists conditions($name)]} {
        return -code error "Condition $name already exists"
    }

    if {![string length $title]} {
        set title [::InstallJammer::StringToTitle $name]
    }

    set condition [::InstallJammer::Condition ::#auto \
        -title $title -name $name -group $group]
}

proc ::InstallJammer::loadconditions::Property { args } {
    variable condition
    eval $condition property $args
}

proc ::InstallJammer::loadconditions::Text { args } {
    variable condition
    lassign $args name pretty subst
    if {![string length $subst]}  { set subst 1 }
    if {![string length $pretty]} { set pretty $name }
    $condition text $name $pretty $subst
}

proc ::InstallJammer::loadconditions::Help { property text } {
    variable condition
    $condition help $property $text
}

proc ::InstallJammer::loadconditions::Group { groupName } {
    variable condition
    variable group [::InstallJammer::StringToTitle $groupName]
    if {$condition ne ""} { $condition group $group }
}

proc ::InstallJammer::loadconditions::Include { args } {
    variable condition
    eval $condition includes $args
}

proc ::InstallJammer::ConditionsWizard { id } {
    global conf
    global widg
    global preferences

    variable ::InstallJammer::conditiongroups

    variable ::InstallJammer::conditions::top
    variable ::InstallJammer::conditions::prop
    variable ::InstallJammer::conditions::listbox
    variable ::InstallJammer::conditions::afterId ""
    variable ::InstallJammer::conditions::operator
    variable ::InstallJammer::conditions::currentTree $conf(TreeFocus)

    set top [::InstallJammer::TopName .conditionsWizard]

    if {$id eq "active"} { set id $::InstallJammer::ActiveComponent }

    set ::InstallJammer::conditions::id $id

    if {[$id operator] eq "OR"} {
        set operator "Match any of the following"
    } else {
        set operator "Match all of the following"
    }

    if {![winfo exists $top]} {
        StandardDialog $top -title "Conditions for [$id title]" \
            -parent $widg(InstallJammer) -applybutton 0 -cancelbutton 0
        wm protocol $top WM_DELETE_WINDOW [list $top ok]

        bind $top <<DialogEnd>> {
            ::InstallJammer::conditions::CloseWindow
        }

        set frame [$top getframe]

        frame $frame.buttons
        pack  $frame.buttons -anchor w

        WinMenuButton $frame.buttons.new -image [GetImage foldernew16] \
            -menu $frame.buttons.new.menu
        pack $frame.buttons.new -side left
        DynamicHelp::add $frame.buttons.new -text "Add New Condition"

        WinButton $frame.buttons.delete -image [GetImage buttoncancel16] \
            -command ::InstallJammer::conditions::DeleteCondition
        pack $frame.buttons.delete -side left -padx 2
        DynamicHelp::add $frame.buttons.delete -text "Delete Condition"

        set menu [menu $frame.buttons.new.menu]

        $menu add cascade -label "All Conditions" -menu $menu.all
        MENU $menu.all

        set command ::InstallJammer::conditions::AddCondition

        foreach group [lsort [array names conditiongroups]] {
            set m    [menu $menu.[NewNode]]
            set text "[::InstallJammer::StringToTitle $group]   "
            $menu add cascade -label $text -menu $m
            foreach condition $conditiongroups($group) {
                set allconditions([$condition condition]) $condition
                $m add command -label [$condition title] \
                    -command [list $command [$condition condition]]
            }
        }

        foreach condition [lsort [array names allconditions]] {
            $menu.all add command -label [$allconditions($condition) title] \
                -command [list $command $condition]
        }

        ttk::combobox $frame.buttons.match -width 25 -state readonly \
            -textvariable ::InstallJammer::conditions::operator \
            -values {"Match all of the following" "Match any of the following"}
        pack $frame.buttons.match -side left -padx 5
        bind $frame.buttons.match <<ComboboxSelected>> \
            ::InstallJammer::conditions::ChangeConditionOperator

        PANEDWINDOW $frame.pw
        pack $frame.pw -expand 1 -fill both

        ScrolledWindow $frame.sw

        $frame.pw add $frame.sw -width 200 -stretch never

        set listbox $frame.list
        LISTBOX $listbox -padx 0 -dragenabled 1 -dropenabled 1
        $frame.sw setwidget $listbox

        set widg(ConditionsListBox) $listbox

        bind $listbox <FocusIn>  { set ::conf(TreeFocus) %W }
        bind $listbox <FocusOut> { set ::conf(TreeFocus) "" }

        $listbox bindText  <1> ::InstallJammer::conditions::RaiseConditionNode
        $listbox bindImage <1> ::InstallJammer::conditions::RaiseConditionNode

        set canvas [$listbox getcanvas]
        bind $canvas <F2>     ::InstallJammer::conditions::Rename
        bind $canvas <Delete> ::InstallJammer::conditions::DeleteConditions
        bind $canvas <B1-Motion> {
            after cancel $::InstallJammer::conditions::afterId
        }

        set propframe [$frame.pw add]

        set prop [PROPERTIES $propframe.prop]
        pack $prop -expand 1 -fill both

        $prop insert end root standard -text "Standard Properties" -open 1

        $prop insert end root advanced -text "Advanced Properties" -open 1

        $prop insert end root text -text "Text Properties" -open 1
    }

    set conf(TreeFocus) $widg(ConditionsListBox)

    $prop itemconfigure standard -state hidden
    $prop itemconfigure advanced -state hidden
    $prop itemconfigure text     -state hidden

    eval [list $listbox delete] [$listbox items]

    set conditions [$id conditions]
    foreach condition $conditions {
        $listbox insert end $condition -text [$condition title] -data $condition
    }

    if {[llength $conditions]} {
        ::InstallJammer::conditions::RaiseConditionNode [lindex $conditions 0]
    }

    set geometry [::InstallJammer::GetWindowGeometry conditions 600x400]
    $top configure -geometry $geometry

    after 0 [list $top draw]
    return 0
}

proc ::InstallJammer::conditions::Rename {} {
    variable listbox

    set node [$listbox selection get]
    set text [$listbox itemcget $node -text]

    $listbox edit $node $text [list ::InstallJammer::conditions::DoRename $node]
}

proc ::InstallJammer::conditions::DoRename { node newtext } {
    variable listbox
    $listbox itemconfigure $node -text $newtext
    $node title $newtext
    Modified
    return 1
}

proc ::InstallJammer::conditions::SaveConditionProperties {} {
    variable active
    variable ActiveCondition

    if {![info exists ActiveCondition]} { return }

    set id $ActiveCondition

    if {![::InstallJammer::ObjExists $id]} { return }

    set obj [$id object]

    set props [list]
    foreach [list prop value] [array get active] {
        if {$prop ne "ID" && $prop ne "Component"} {
            lappend props $prop $value
        }
    }

    foreach prop [$obj textfields] {
        lappend props $prop,subst $active($prop,subst)
    }

    eval [list ::InstallJammer::SetObjectProperties $id] $props
}

proc ::InstallJammer::conditions::RaiseConditionNode { node } {
    global conf

    variable prop
    variable active
    variable afterId
    variable listbox
    variable ActiveCondition

    set id [$listbox itemcget $node -data] 

    if {[info exists afterId]} { after cancel $afterId }

    if {[info exists ActiveCondition]} {
        SaveConditionProperties

        if {$id == $ActiveCondition} {
            set afterId [after 800 ::InstallJammer::conditions::Rename]
            return
        }
    }

    $listbox selection set $node

    set ActiveCondition $id

    set obj [$id object]

    eval [list $prop delete] [$prop nodes standard] \
        [$prop nodes advanced] [$prop nodes text]

    unset -nocomplain active

    foreach property [$obj properties] {
        set active($property) [::InstallJammer::GetObjectProperty $id $property]
    }

    foreach property [$obj textfields] {
        set text  [::InstallJammer::GetText $id $property -subst 0 -label 1]
        set subst [::InstallJammer::GetObjectProperty $id $property,subst]
        set active($property)       $text
        set active($property,subst) $subst
    }

    set active(ID) $id
    set active(Component) [[$id object] title]

    $prop itemconfigure standard -state normal

    if {![llength [$prop nodes standard]]} {
        $obj addproperties $prop condition -advanced 0 \
            -array ::InstallJammer::conditions::active
    }

    foreach n [$prop nodes standard] {
        if {[$prop itemcget $n -data] eq "CheckCondition"} {
            if {[$::InstallJammer::conditions::id ispane]} {
                $prop itemconfigure $n -values $conf(PaneCheckConditions)
            } else {
                $prop itemconfigure $n -values $conf(ActionCheckConditions)
            }
            break
        }
    }

    if {![llength [$obj properties 0]]} {
        $prop itemconfigure advanced -state hidden
    } else {
        $prop itemconfigure advanced -state normal

        $obj addproperties $prop condition -standard 0 -advanced 1 \
            -array ::InstallJammer::conditions::active
    }

    if {![llength [$obj textfields]]} {
        $prop itemconfigure text -state hidden
    } else {
        $prop itemconfigure text -state normal
        $obj addtextfields $prop text $id ::InstallJammer::conditions::active
    }
}

proc ::InstallJammer::conditions::AddCondition { condition } {
    variable id
    variable listbox

    variable ::InstallJammer::conditions

    set obj $conditions($condition)

    set idx end
    #set sel [$listbox selection get] 
    #if {[string length $sel]} { set idx [$listbox index $sel] }

    set cid [::InstallJammer::AddCondition $condition -parent $id -index $idx]
}

proc ::InstallJammer::conditions::DeleteCondition {} {
    variable id
    variable top
    variable prop
    variable listbox

    set sel [$listbox selection get]

    if {![llength $sel]} { return }

    if {![::InstallJammer::AskYesNo -parent $top \
        -message "Are you sure you want to delete the selected conditions?"]} {
        return
    }

    foreach cid $sel {
        $cid destroy
    }

    eval [list $listbox delete] $sel

    foreach node [$prop nodes root] {
        $prop itemconfigure $node -state hidden
    }

    ::InstallJammer::SetActiveComponentConditions
    ::InstallJammer::RefreshComponentTitles $id

    Modified
}

proc ::InstallJammer::conditions::ChangeConditionOperator {} {
    variable id
    variable operator

    if {$operator eq "Match all of the following"} {
        $id operator "AND"
    } elseif {$operator eq "Match any of the following"} {
        $id operator "OR"
    } else {
        return -code error "bad operator $operator"
    }
}

proc ::InstallJammer::conditions::CloseWindow {} {
    global conf
    global preferences

    variable id
    variable top
    variable listbox

    set preferences(Geometry,conditions) [wm geometry $top]

    ::InstallJammer::conditions::SaveConditionProperties
    unset -nocomplain ::InstallJammer::conditions::ActiveCondition

    $id conditions reorder [$listbox items]

    set conf(TreeFocus) $::InstallJammer::conditions::currentTree
}

proc ::InstallJammer::AddCondition { condition args } {
    global widg

    variable ::InstallJammer::conditions

    if {![info exists conditions($condition)]} {
        ## If we're trying to add an condition that doesn't exist,
        ## it's probably because we no longer support the condition.

        ## We need to destroy the object that references this condition.
        array set _args $args
        if {[info exists _args(-id)]} { $_args(-id) destroy }

        return
    }

    set obj $conditions($condition)

    array set _args {
        -id     ""
        -index  end
        -title  ""
        -parent ""
    }
    set _args(-title) [$obj title]
    array set _args $args

    set cid    $_args(-id)
    set parent $_args(-parent)

    if {$parent eq ""} {
        set parent $::InstallJammer::conditions::id
    }

    if {$cid eq ""} {
        set cid [::InstallJammer::uuid]
        $parent conditions insert $_args(-index) $cid
        ::Condition ::$cid -parent $parent -component $condition \
            -title $_args(-title)

        if {[$parent is action actiongroup]} {
            $cid set CheckCondition "Before Action is Executed"
        }
    }

    $obj initialize $cid

    Modified

    ::InstallJammer::RefreshComponentTitles $parent

    if {[info exists widg(ConditionsListBox)]
        && [winfo viewable $widg(ConditionsListBox)]} {
        $widg(ConditionsListBox) insert end $cid \
                -text [$obj title] -data $cid -fill blue
        ::InstallJammer::SetActiveComponentConditions
    }

    return $cid
}

proc ::InstallJammer::GetActiveCondition {} {
    if {[info exists ::InstallJammer::conditions::ActiveCondition]} {
        return $::InstallJammer::conditions::ActiveCondition
    }
}

proc ::InstallJammer::SetActiveComponentConditions {} {
    variable active

    set id  [::InstallJammer::GetActiveComponent]
    set len [llength [$id conditions]]
    set active(Conditions) "$len condition[expr {$len != 1 ? "s" : ""}]"
}
Added lib/console.tcl.














































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

if {![info exists tk_patchLevel]} { return }
if {$::tcl_platform(platform) ne "unix"} { return }

set consoleInterp [interp create]
$consoleInterp eval [list set tk_library $tk_library]
$consoleInterp alias exit exit
load "" Tk $consoleInterp

# 2. A command 'console' in the application interpreter
;proc console { sub {optarg {}} } [subst -nocommands {
    switch -exact -- \$sub {
       title {
	   $consoleInterp eval wm title . [list \$optarg]
       }
       hide {
	   $consoleInterp eval wm withdraw .
       }
       show {
	   $consoleInterp eval wm deiconify .
       }
       eval {
	   $consoleInterp eval \$optarg
       }
       default {
	   error "bad option \\\"\$sub\\\": should be hide, show, or title"
       }
   }
}]

# 3. Alias a command 'consoleinterp' in the console window interpreter
#       to cause evaluation of the command 'consoleinterp' in the
#       application interpreter.
;proc consoleinterp {sub cmd} {
   switch -exact -- $sub {
       eval {
	   uplevel #0 $cmd
       }
       record {
	   history add $cmd
	   catch {uplevel #0 $cmd} retval
	   return $retval
       }
       default {
	   error "bad option \"$sub\": should be eval or record"
       }
   }
}
if {[package vsatisfies [package provide Tk] 4]} {
   $consoleInterp alias interp consoleinterp
} else {
   $consoleInterp alias consoleinterp consoleinterp
}

# 4. Bind the <Destroy> event of the application interpreter's main
#    window to kill the console (via tkConsoleExit)
bind . <Destroy> [list +if {[string match . %W]} [list catch \
       [list $consoleInterp eval tkConsoleExit]]]

# 5. Redefine the Tcl command 'puts' in the application interpreter
#    so that messages to stdout and stderr appear in the console.
rename puts tcl_puts
;proc puts {args} [subst -nocommands {
   switch -exact -- [llength \$args] {
       1 {
	   if {[string match -nonewline \$args]} {
	       if {[catch {uplevel 1 [linsert \$args 0 tcl_puts]} msg]} {
		   regsub -all tcl_puts \$msg puts msg
		   return -code error \$msg
	       }
	   } else {
	       $consoleInterp eval [list tkConsoleOutput stdout \
		       "[lindex \$args 0]\n"]
	   }
       }
       2 {
	   if {[string match -nonewline [lindex \$args 0]]} {
	       $consoleInterp eval [list tkConsoleOutput stdout \
		       [lindex \$args 1]]
	   } elseif {[string match stdout [lindex \$args 0]]} {
	       $consoleInterp eval [list tkConsoleOutput stdout \
		       "[lindex \$args 1]\n"]
	   } elseif {[string match stderr [lindex \$args 0]]} {
	       $consoleInterp eval [list tkConsoleOutput stderr \
		       "[lindex \$args 1]\n"]
	   } else {
	       if {[catch {uplevel 1 [linsert \$args 0 tcl_puts]} msg]} {
		   regsub -all tcl_puts \$msg puts msg
		   return -code error \$msg
	       }
	   }
       }
       3 {
	   if {![string match -nonewline [lindex \$args 0]]} {
	       if {[catch {uplevel 1 [linsert \$args 0 tcl_puts]} msg]} {
		   regsub -all tcl_puts \$msg puts msg
		   return -code error \$msg
	       }
	   } elseif {[string match stdout [lindex \$args 1]]} {
	       $consoleInterp eval [list tkConsoleOutput stdout \
		       [lindex \$args 2]]
	   } elseif {[string match stderr [lindex \$args 1]]} {
	       $consoleInterp eval [list tkConsoleOutput stderr \
		       [lindex \$args 2]]
	   } else {
	       if {[catch {uplevel 1 [linsert \$args 0 tcl_puts]} msg]} {
		   regsub -all tcl_puts \$msg puts msg
		   return -code error \$msg
	       }
	   }
       }
       default {
	   if {[catch {uplevel 1 [linsert \$args 0 tcl_puts]} msg]} {
	       regsub -all tcl_puts \$msg puts msg
	       return -code error \$msg
	   }
       }
   }
}]
$consoleInterp alias puts puts

# 6. No matter what Tk_Main says, insist that this is an interactive  shell
set tcl_interactive 1

########################################################################
# Evaluate the Tk library script console.tcl in the console interpreter
########################################################################
$consoleInterp eval source [list [file join $tk_library console.tcl]]

console hide

$consoleInterp eval {
   if {![llength [info commands tkConsoleExit]]} {
       tk::unsupported::ExposePrivateCommand tkConsoleExit
   }
}
$consoleInterp eval {
   if {![llength [info commands tkConsoleOutput]]} {
       tk::unsupported::ExposePrivateCommand tkConsoleOutput
   }
}
if {[string match 8.3.4 $tk_patchLevel]} {
   # Workaround bug in first draft of the tkcon enhancments
   $consoleInterp eval {
       bind Console <Control-Key-v> {}
   }
}
# Restore normal [puts] if console widget goes away...
proc Oc_RestorePuts {slave} {
    rename puts {}
    rename tcl_puts puts
    interp delete $slave
}
$consoleInterp alias Oc_RestorePuts Oc_RestorePuts $consoleInterp
$consoleInterp eval {
    bind Console <Destroy> +Oc_RestorePuts
}

unset consoleInterp

console title "[wm title .] Console"
Added lib/convert.tcl.


























































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ConvertTheme {} {
    global conf
    global info

    ::InstallJammer::LoadThemeConfig theme

    ## If the version is the same or higher, we don't need to do anything.
    if {$info(ThemeVersion) >= $theme(Version)} { return 0 }

    set msg    "The theme for this install has been updated.\n"
    append msg "Would you like to restore the install theme to take "
    append msg "advantage of new features?"
    set ans [tk_messageBox -type yesno -title "Theme Updated" -message $msg]

    if {$ans eq "no"} { return 0 }

    set info(ThemeVersion) $theme(Version)
    RestoreTheme -noload

    return 1
}

proc ConvertProject {} {
    global conf
    global info

    variable ::InstallJammer::Properties

    set modified 0

    if {$info(ProjectVersion) eq "0.9.1.0"} {
        if {$conf(cmdline)} { return 1 }

        ## 1.0a1
        ##
        ## SetupFile class was removed in favor of using File.
        ##    This will be handled by the SetupFile proc defined below.
        ##
        ## ModifyButton action was removed in favor of ModifyWidget.
        ##
        ## File Group handling of directories was changed.

        Status "Converting project from 1.0a1..."
        update

        incr modified

        ## Convert ModifyButton actions to ModifyWidget.
        foreach id [itcl::find object -class InstallComponent] {
            if {[$id component] eq "ModifyButton"} {
                $id component ModifyWidget
                set button [$id get Button]
                $id set Widget "$button Button"
            }
        }

        ## Handle File Group changes.  Each directory that is a
        ## direct child of a file group must be removed and all of
        ## their subdirectories moved up a level.
        foreach group [FileGroups children] {
            foreach parent [$group children] {
                if {[$parent is dir]} {
                    ::InstallJammer::RecursiveGetFiles $parent
                    foreach id [$parent children] {
                        $id reparent $group
                    }
                    $parent destroy
                }
            }
        }
        
        set info(ProjectVersion) "0.9.2.0"
    }

    if {$info(ProjectVersion) eq "0.9.2.0"} {
        if {$conf(cmdline)} { return 1 }

        ## 1.0b1
        ##
        ## Multi-language support was added.  We need to update all of
        ## the text in the project.

        Status "Converting project from 1.0b1..."
        update

        incr modified

        set resetText [::InstallJammer::MessageBox \
            -type yesno -title "Converting Project" \
            -message "Your project must be converted to the new version of\
                InstallJammer.\nDo you want to convert all of your text\
                to the new version?\nWithout this change, your project will\
                not support the new multi-language features properly."]

        ## Remove variables that are no longer used.
        unset -nocomplain info(UseVersions)
        unset -nocomplain info(PaneList,install)
        unset -nocomplain info(PaneList,uninstall)

        ## Anything in VirtualTextData needs to be set in
        ## the info array, and then we need to get rid of
        ## the VirtualTextData variable.  Virtual text is
        ## now all stored in message catalogs.
        if {[info exists info(VirtualTextData)]} {
            array set info $info(VirtualTextData)
            unset info(VirtualTextData)
        }

        set map [list]
        lappend map <%FileBeingInstalledText%> <%Status%>
        lappend map <%FileBeingUninstalledText%> <%Status%>

        ## Load the engligh message catalog into an array
        ## and then clear it.  We're going to rebuild it.
        array set msgs [::msgcat::mcgetall en]
        ::msgcat::mcclear en

        ## Walk through all of the InstallComponents and map
        ## their properties.  Some components need to have their
        ## text properties converted to advanced properties.
        foreach id [itcl::find object -class InstallComponent] {
            foreach var [array names Properties $id,*] {
                set Properties($var) [string map $map $Properties($var)]
                if {$resetText} {
                    if {[string match *Button*,subst $var]} {
                        set Properties($var) 1
                    }
                }
            }

            switch -- [$id component] {
                "ExecuteAction" {
                    ## Remove the Execute Action actions that
                    ## refer to Startup Actions.  Startup Actions
                    ## are automatically executed by InstallJammer now.
                    if {[$id get Action] eq "Startup Actions"} {
                        $id destroy
                    }
                }

                "ExecuteScript" {
                    ## Convert the tcl script from a text property
                    ## to a regular property.
                    if {[info exists msgs($id,TclScript)]} {
                        $id set TclScript $msgs($id,TclScript)
                        unset msgs($id,TclScript)
                    }
                }

                "ExecuteExternalProgram" {
                    ## Convert the command line from a text property
                    ## to a regular property.
                    if {[info exists msgs($id,ProgramCommandLine)]} {
                        $id set ProgramCommandLine $msgs($id,ProgramCommandLine)
                        unset msgs($id,ProgramCommandLine)
                    }
                }

                "Exit" {
                    ## The Exit actions that are part of the silent
                    ## installs need to be a Finish exit.
                    if {[string match "Silent*" [$id parent]]} {
                        $id set ExitType Finish
                    }
                }
            }
        }

        ## Walk through all of the conditions and look for ones
        ## that were modified in this release.  We need to change
        ## their text properties to advanced properties.
        foreach id [itcl::find objects -class Condition] {
            switch -- [$id component] {
                "ScriptCondition" {
                    if {[info exists msgs($id,Script)]} {
                        $id set Script $msgs($id,Script)
                        unset msgs($id,Script)
                    }
                }

                "StringEqualCondition" {
                    if {[info exists msgs($id,String1)]} {
                        $id set String1 $msgs($id,String1)
                        unset msgs($id,String1)
                    }

                    if {[info exists msgs($id,String2)]} {
                        $id set String2 $msgs($id,String2)
                        unset msgs($id,String2)
                    }
                }

                "StringMatchCondition" {
                    if {[info exists msgs($id,String)]} {
                        $id set String $msgs($id,String)
                        unset msgs($id,String)
                    }

                    if {[info exists msgs($id,Pattern)]} {
                        $id set Pattern $msgs($id,Pattern)
                        unset msgs($id,Pattern)
                    }
                }
            }
        }

        ## Walk through all of the strings in the english message
        ## catalog and map them all.  Any that we've converted
        ## have been removed from the array, so they won't be in
        ## the new message catalog.
        if {!$resetText} {
            foreach var [array names msgs] {
                ::msgcat::mcset en $var [string map $map $msgs($var)]
            }
        } else {
            ::InstallJammer::LoadMessages
        }

        set info(ProjectVersion) "0.9.3.0"
    }

    if {[package vcompare $info(ProjectVersion) 1.1.0.1] < 0} {
        if {$conf(cmdline)} { return 1 }

        ## 1.1b1
        ##
        ## Added the new command-line options, so we need to setup
        ## the default options for a 1.0 project.

        ## Walk through all of the conditions on our actions and
        ## set their CheckCondition property.  Previously, conditions
        ## on actions were only checked before the action was executed.
        ##
        ## We also want to check panes to see if we need to add our new
        ## Populate actions.  Previously, these panes were auto-populated
        ## by code in the pane itself.  That code has been broken out into
        ## actions instead.

        Status "Converting project to version 1.1b1..."
        update

        incr modified

        foreach id [itcl::find objects -class InstallComponent] {
            if {[$id is action]} {
                foreach cid [$id conditions] {
                    $cid set CheckCondition "Before Action is Executed"
                }
            } elseif {$info(Theme) eq "Modern_Wizard" && [$id ispane]} {
                ## Add the new Populate Components and Populate Setup Types
                ## actions to the correct panes.
                if {[$id component] eq "SetupType"} {
                    ::InstallJammer::AddAction [$id setup] PopulateSetupTypes \
                        -parent $id
                } elseif {[$id component] eq "ChooseComponents"} {
                    ::InstallJammer::AddAction [$id setup] PopulateComponents \
                        -parent $id
                }
            }
        }

        ## We now save files without their full paths, so we want to
        ## alter the names of each file that is not a direct child
        ## of a filegroup.

        foreach file [itcl::find objects -class File] {
            if {![[$file parent] is filegroup]} {
                $file name [file tail [$file name]]
            }
        }

        ## Add the new default command-line options plus the old ones
        ## to keep compatibility.

        ::InstallJammer::AddDefaultCommandLineOptions

        array set ::InstallJammer::InstallCommandLineOptions {
            D { {} Prefix No No {}
                "set the value of an option in the installer"
            }

            S { InstallMode Switch No No "Silent"
                "run the installer in silent mode"
            }

            T { Testing Switch Yes No {}
                "run installer without installing any files"
            }

            Y { InstallMode Switch No No "Default"
                "accept all defaults and run the installer"
            }
        }

        array set ::InstallJammer::UninstallCommandLineOptions {
            S { UninstallMode Switch No No "Silent"
                "run the uninstaller in silent mode"
            }

            Y { UninstallMode Switch No No "Default"
                "accept all defaults and run the uninstaller"
            }
        }

        ## 1.1 added Console installs.  Setup a basic Console install
        ## when converting the project.

        ::NewInstall::AddConsoleInstall

        set info(ProjectVersion) "1.1.0.2"
    }

    if {[package vcompare $info(ProjectVersion) 1.1.0.3] < 0} {
        if {$conf(cmdline)} { return 1 }

        ## 1.1b3

        Status "Converting project to version 1.1b3..."
        update

        ## Walk through and find any Modify Widget actions on
        ## a License pane.  We need to check for their broken
        ## conditions and fix them.
        set str1 {[<%CurrentPane%> get UserMustAcceptLicense]}
        set str2 {<%Property UserMustAcceptLicense%>}
        set str3 {<%Property <%CurrentPane%> UserMustAcceptLicense%>}
        foreach id [itcl::find objects -class InstallComponent] {
            if {$info(Theme) eq "Modern_Wizard" && [$id is action]
                && [$id component] eq "ModifyWidget"
                && [[$id parent] ispane]
                && [[$id parent] component] eq "License"} {

                foreach cid [$id conditions] {
                    if {[$cid component] eq "StringIsCondition"} {
                        set str [$cid get String]
                        if {$str eq $str1 || $str eq $str2} {
                            $cid set String $str3
                            incr modified
                        }
                    }
                }
            }
        }

        set info(ProjectVersion) "1.1.0.3"
    }

    if {[package vcompare $info(ProjectVersion) 1.2.0.3] < 0} {
        ## The VFS format changed for the installkits in the final
        ## 1.2 release.  We need to require a full rebuild.

        incr modified

        set conf(fullBuildRequired) 1

        set info(ProjectVersion) "1.2.0.3"
    }

    if {[package vcompare $info(ProjectVersion) 1.2.5.1] < 0} {
        ## 1.2.5 added the ability to specify the Size of a file
        ## group, but InstallJammer already saves this attribute.
        ## The one saved is auto-generated, and the user never
        ## really sees it, so we want to get rid of it because they
        ## can now actually set it.
        ##
        ## Note that this doesn't actually require any action from
        ## the user, so we don't modify the state of the project.

        foreach id [itcl::find objects -class FileGroup] {
            unset -nocomplain Properties($id,Size)
        }

        set info(ProjectVersion) "1.2.5.1"
    }

    if {$modified && !$conf(cmdline)} {
        ::InstallJammer::BackupProjectFile "<%Project%>-<%ProjectVersion%>.mpi"
    }

    return $modified
}

if {[info commands ::_installComponentClass] eq ""} {
    rename ::InstallComponent ::_installComponentClass
    proc ::InstallComponent {id args} {
        array set _args $args
        unset -nocomplain _args(-command)
        eval ::_installComponentClass $id [array get _args]
    }
}
Added lib/dobuild.tcl.






























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

if {[info exists ::InstallJammer]} { return }

set len [llength $argv]
for {set i 0} {$i < $len} {incr i} {
    set opt [lindex $argv $i]
    if {[string match "--*" $opt]} {
        set _argv($opt) [lindex $argv [incr i]]
    } else {
        lappend args $opt
    }
}

unset -nocomplain _args
installkit::ParseWrapArgs _args $args

set pwd         [file dirname $_args(executable)]
set conf(pwd)   [file dirname [info script]]
set conf(stop)  [file join $pwd .stop]
set conf(pause) [file join $pwd .pause]

file delete -force $conf(stop) $conf(pause)

if {[info exists ::parentThread]} {
    proc echo { string } {
        thread::send $::parentThread [list ::InstallJammer::BuildOutput $string]
        return
    }
} else {
    proc echo { string } {
        puts  stdout $string
        flush stdout
    }

    foreach file {common.tcl installkit.tcl} {
        set file [file join $conf(pwd) $file]
        if {[catch { source $file } error]} {
            echo $::errorInfo
        }
    }
}

proc CheckForBuildStop {} {
    global conf

    while {[file exists $conf(pause)]} {
        if {[file exists $conf(stop)]} { Exit }
        after 500
    }
    return 1
}

proc Progress { file in out } {
    CheckForBuildStop

    if {$file ne $::lastfile} {
        echo [list :FILE $file]
        set ::lastin    0.0
        set ::lastfile  $file
        set ::filetotal 0.0
    }

    iincr ::total     [expr {$in - $::lastin}]
    iincr ::filetotal [expr {$in - $::lastin}]
    set ::lastin $in

    set x [expr {round( ($::filetotal * 100.0) / $::sizes($file) )}]
    if {$x != $::lastfiletotal} {
        set ::lastfiletotal $x
        echo [list :FILEPERCENT $x]
    }

    if {$::totalSize == 0} {
        echo [list :PERCENT 100]
    } else {
        set x [expr {round( ($::total * 100.0) / $::totalSize )}]
        if {$x != $::lasttotal} {
            set ::lasttotal $x
            echo [list :PERCENT $x]
        }
    }
}

proc Progress { file } {
    CheckForBuildStop

    if {[string length $::lastfile]} {
        iincr ::total $::sizes($::lastfile)
        if {$::totalSize == 0} {
            echo [list :PERCENT 100]
        } else {
            set x [expr {round( ($::total * 100.0) / $::totalSize )}]
            echo [list :PERCENT $x]
        }
    }
    echo [list :FILE $file]
    set ::lastfile $file
}

proc Exit {} {
    if {![info exists ::parentThread]} {
        exit
    } else {
        thread::release [thread::id]
    }
}

catch { 
    set total         0
    set lastfile      ""
    set lasttotal     0
    set totalSize     0
    set lastfiletotal 0

    ## FIXME: Remove this once the SHA1 code is fixed for large installers.
    if {[info commands ::sha1_real] eq ""} {
        rename ::sha1 ::sha1_real
        proc ::sha1 {args} {
            if {[lindex $args 0] eq "-string"} {
                return [eval ::sha1_real $args]
            }

            if {[lindex $args 0] eq "-update"} {
                array set _args $args
                while {[set data [read $_args(-chan) 4096]] ne ""} {}
            }
        }
    }

    if {[info exists _args(wrapFiles)] && [llength $_args(wrapFiles)]} {
        unset -nocomplain sizes
        foreach file $_args(wrapFiles) {
            set sizes($file) [file size $file].0
            iincr totalSize $sizes($file)
        }
    }

    set build  $_argv(--build)
    set output $_argv(--output)

    if {[info exists _argv(--archive-manifest)]} {
        echo [list :ECHO "Building archives..."]

        set i 0
        file mkdir $output
        set manifest [read_textfile $_argv(--archive-manifest)]
        foreach {id file group size mtime method} $manifest {
            set sizes($file) $size
            iincr totalSize $size
        }

        set opts {}
        if {[info exists _args(password)] && $_args(password) ne ""} {
            lappend opts -password $_args(password)
        }

        foreach {id file group size mtime method} $manifest {
            if {![info exists fps($group)]} {
                set archive [file join $output setup[incr i].ijc]
                set fps($group) \
                    [eval miniarc::open crap [list $archive] w $opts]
            }
            Progress $file
            miniarc::addfile $fps($group) $file -name $id -method $method
        }

        foreach f [array names fps] {
            miniarc::close $fps($f)
        }
    }

    ## FIXME:  Remove this crud when all of the installkits get the ability
    ## to do this in the next version.  This is renaming the main.tcl script
    ## to main2.tcl and replacing main.tcl with a version that sources main2
    ## in utf-8 encoding, which is what it's stored in.
    set newMain [file join $build main.tcl]

    set fp [open $newMain w]
    puts $fp {set enc [encoding system]}
    puts $fp {encoding system utf-8}
    puts $fp {source [file join $::installkit::root main2.tcl]}
    puts $fp {encoding system $enc}
    close $fp

    set x [lsearch -exact $args $_args(mainScript)]
    set args [lreplace $args $x $x $newMain]

    echo [list :ECHO "Building install executable..."]
    if {[catch {eval ::installkit::wrap -command ::Progress $args}]} {
        echo $::errorInfo
    } else {
        installkit::addfiles $_args(executable) [list $_args(mainScript)] \
            -name main2.tcl -corefile 1
    }
} error

if {$error ne ""} { echo $::errorInfo }

echo ":DONE"

Exit
Added lib/edit.tcl.
































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
proc ::InstallJammer::EditGetSelectedItems {} {
    global conf
    global widg

    set tree $conf(TreeFocus)
    if {$tree eq ""} { return }

    set items [list]

    if {$tree eq $widg(FileGroupTree)} {

    } elseif {$tree eq $widg(ComponentTree)} {

    } elseif {$tree eq $widg(SetupTypeTree)} {

    } elseif {$tree eq $widg(InstallTree) || $tree eq $widg(UninstallTree)} {
        foreach node [$tree selection get] {
            if {![::InstallJammer::Tree::IsInstallType $tree $node]} {
                lappend items $node
            }
        }
    } elseif {[info exists widg(ConditionsListBox)]
                && $tree eq $widg(ConditionsListBox)} {
        set items [$tree selection get]
    }

    return $items
}

proc ::InstallJammer::EditGetSetup {} {
    global conf
    global widg

    set tree $conf(TreeFocus)
    if {$tree eq $widg(InstallTree)} { return "Install" }
    if {$tree eq $widg(UninstallTree)} { return "Uninstall" }
}

proc ::InstallJammer::EditGetTree {} {
    global conf
    global widg

    set tree $conf(TreeFocus)

    if {$tree eq $widg(FileGroupTree)
        || $tree eq $widg(ComponentTree)
        || $tree eq $widg(SetupTypeTree)
        || $tree eq $widg(InstallTree)
        || $tree eq $widg(UninstallTree)
        || ([info exists widg(ConditionsListBox)]
                && $tree eq $widg(ConditionsListBox))} {
        if {[winfo viewable $tree]} { return $tree }
    }
}

proc ::InstallJammer::EditCut {} {
    if {$::edit::widget ne ""} {
        #return [::edit::cut $::edit::widget]
        return
    }

    set tree [::InstallJammer::EditGetTree]

    if {$tree ne ""} {
        ::InstallJammer::EditCopy
        ::InstallJammer::Tree::Delete $tree 0
    }
}

proc ::InstallJammer::EditCopy {} {
    global conf

    if {$::edit::widget ne ""} {
        #return [::edit::copy $::edit::widget]
        return
    }

    set tree [::InstallJammer::EditGetTree]

    if {$tree ne ""} {
        set list [list ##IJCV1##]
        foreach item [::InstallJammer::EditGetSelectedItems] {
            lappend list [::InstallJammer::DumpObject $item]
        }
        clipboard clear
        clipboard append $list
    }
}

proc ::InstallJammer::EditPaste {} {
    global conf

    if {$::edit::widget ne ""} {
        #return [::edit::paste $::edit::widget]
        return
    }

    set tree [::InstallJammer::EditGetTree]

    if {$tree ne ""} {
        set setup [::InstallJammer::EditGetSetup]

        if {[catch {clipboard get} list]} { return }
        if {[lindex $list 0] ne "##IJCV1##"} { return }
        foreach list [lrange $list 1 end] {
            ::InstallJammer::CreateComponentFromDump $setup $list
        }
    }
}

proc ::InstallJammer::EditDelete {} {
    if {$::edit::widget ne ""} {
        #return [::edit::delete $::edit::widget]
        return
    }

    set tree [::InstallJammer::EditGetTree]

    if {$tree ne ""} {
        ::InstallJammer::Tree::Delete $tree 0
    }
}

proc ::InstallJammer::EditSelectAll {} {
    set widget $::edit::widget
    if {$widget eq ""} { set widget [focus] }
    return [::edit::selectall $widget]
}
Added lib/editor.tcl.
































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

namespace eval ::editor { 
    variable base .editor
    variable varName ""
    variable textBox ""

proc new { args } {
    global conf
    global info
    global widg
    global preferences

    variable base
    variable result
    variable varName
    variable textBox $base.middle.text

    variable lang     ""
    variable lastlang ""

    array set _args {
        -text            ""
        -font            "TkTextFont"
        -title           "Editor"
        -command         ""
        -variable        ""

        -language        "English"
        -languages       0
        -languagecommand ""
    }
    array set _args $args

    set varName $_args(-variable)

    toplevel     $base
    wm withdraw  $base
    wm transient $base $widg(InstallJammer)
    wm title     $base $_args(-title)
    wm protocol  $base WM_DELETE_WINDOW ::editor::cancel

    set geometry [::InstallJammer::GetWindowGeometry Editor 400x300]
    wm geometry $base $geometry
    if {$geometry eq "400x300"} { ::InstallJammer::CenterWindow $base 400 300 }

    bind $base <Escape>         ::editor::cancel
    bind $base <Control-Return> ::editor::ok

    frame $base.top -height 24

    WinButton $base.top.cut -image [GetImage editcut16] \
	-command "::edit::cut $textBox"
    pack $base.top.cut -side left
    DynamicHelp::register $base.top.cut balloon Cut

    WinButton $base.top.copy -image [GetImage editcopy16] \
	-command "::edit::copy $textBox"
    pack $base.top.copy -side left
    DynamicHelp::register $base.top.copy balloon Copy

    WinButton $base.top.paste -image [GetImage editpaste16] \
	-command "::edit::paste $textBox"
    pack $base.top.paste -side left
    DynamicHelp::register $base.top.paste balloon Paste

    WinButton $base.top.delete -image [GetImage editdelete16] \
	-command "::edit::delete $textBox"
    pack $base.top.delete -side left
    DynamicHelp::register $base.top.delete balloon Delete

    WinButton $base.top.undo -image [GetImage actundo16] \
        -command "::edit::undo $textBox"
    pack $base.top.undo -side left
    DynamicHelp::register $base.top.undo balloon Undo

    WinButton $base.top.redo -image [GetImage actredo16] \
        -command "::edit::redo $textBox"
    pack $base.top.redo -side left
    DynamicHelp::register $base.top.redo balloon Redo

    Separator $base.top.sp1 -orient vertical -relief ridge
    pack $base.top.sp1 -side left -fill y -pady 4 -padx 4

    WinButton $base.top.import -image [GetImage fileopen16] \
	-command ::editor::import
    pack $base.top.import -side left
    DynamicHelp::register $base.top.import balloon "Import a File"

    if {$_args(-languages)} {
        set ::editor::lang $_args(-language)
        set ::editor::lastlang $_args(-language)

        Separator $base.top.sp2 -orient vertical -relief ridge
        pack $base.top.sp1 -side left -fill y -pady 4 -padx 4

        ::ttk::combobox $base.top.lang \
            -state readonly -textvariable ::editor::lang \
            -values [concat All [::InstallJammer::GetLanguages]]
        pack $base.top.lang -side left

        bind $base.top.lang <<ComboboxSelected>> $_args(-languagecommand)
    }

    WinButton $base.top.cancel -image [GetImage buttoncancel16] \
	-command ::editor::cancel
    pack $base.top.cancel -side right
    DynamicHelp::register $base.top.cancel balloon "Cancel Changes"

    WinButton $base.top.ok -image [GetImage buttonok16] \
	-command ::editor::ok
    pack $base.top.ok -side right
    DynamicHelp::register $base.top.ok balloon "Save Changes"

    ScrolledWindow $base.middle
    text $base.middle.text -undo 1 -font $_args(-font)
    $base.middle setwidget $textBox

    bind $base.middle.text <Control-Return> "::editor::ok; break"
    bind $base.middle.text <<Selection>> [list ::editor::AdjustSelection]

    pack $base.top -fill x
    pack $base.middle -expand 1 -fill both

    if {[string length $_args(-variable)]} {
        upvar #0 $_args(-variable) var
        if {[info exists var]} { $textBox insert 1.0 $var }
    } else {
        $textBox insert 1.0 $_args(-text)
    }

    $textBox edit reset
    $textBox edit modified 0

    focus $textBox

    AdjustSelection

    wm deiconify $base

    raise $base

    BWidget::grab set $base

    tkwait window $base

    return $result
}

proc language { {language ""} } {
    if {[string length $language]} {
        set ::editor::lastlang $::editor::lang
        set ::editor::lang $language
    }
    return $::editor::lang
}

proc lastlanguage {} {
    if {[info exists ::editor::lastlang]} { return $::editor::lastlang }
}

proc settext { text } {
    variable textBox
    variable varName

    if {[string length $varName]} { set $varName $text }

    $textBox delete 1.0 end
    $textBox insert 1.0 $text

    $textBox edit reset
    $textBox edit modified 0

    focus $textBox

    AdjustSelection
}

proc gettext {} {
    variable textBox
    $textBox get 1.0 end
}

proc modified {} {
    variable textBox
    $textBox edit modified
}

proc cancel {} {
    global preferences

    variable base
    variable textBox

    variable result 0

    if {[$textBox edit modified]} {
        set ans [::InstallJammer::MessageBox \
            -type yesnocancel -title "Text Modified" \
            -message "Text has been modified.  Do you want to save changes?"]

        if {$ans eq "cancel"} {
            focus $textBox
            return
        }

        if {$ans eq "yes"} { return [ok] }
    }

    set preferences(Geometry,Editor) [wm geometry $base]

    destroy $base
}

proc ok {} {
    global preferences

    variable base
    variable varName
    variable textBox

    variable result 1

    upvar #0 $varName var
    set var [string range [$textBox get 1.0 end] 0 end-1]

    set preferences(Geometry,Editor) [wm geometry $base]

    destroy $base
}

proc import {} {
    variable base
    variable textBox
    set file [mpi_getOpenFile -parent $base]
    if {[lempty $file]} { return }

    ## If anything is selected, we're replacing the selection with the imported
    ## file.  Delete the selection first.
    set sel [$textBox tag ranges sel]
    if {![lempty $sel]} { eval $textBox delete $sel }

    $textBox insert insert [read_file $file]
}

proc AdjustSelection {} {
    variable base
    variable textBox

    if {[lempty [::edit::curselection $textBox]]} {
	$base.top.cut    configure -state disabled
	$base.top.copy   configure -state disabled
	$base.top.delete configure -state disabled
    } else {
	$base.top.cut    configure -state normal
	$base.top.copy   configure -state normal
	$base.top.delete configure -state normal
    }
}

} ; ## namespace eval ::editor

namespace eval ::edit {

proc ::edit::cut {w} {
    if {![string length $w]} { return }
    ::edit::copy $w
    ::edit::delete $w
}

proc ::edit::copy {w} {
    if {![string length $w]} { return }
    clipboard clear
    clipboard append [::edit::curselection $w]
}

proc ::edit::paste {w} {
    if {![string length $w]} { return }
    ::edit::delete $w
    $w insert insert [clipboard get]
}

proc ::edit::delete {w} {
    if {![string length $w]} { return }
    catch { $w delete sel.first sel.last }
}

proc ::edit::selectall {w} {
    if {![string length $w]} { return }
    switch -- [winfo class $w] {
	"Entry" {
	    $w selection range 0 end
	}

	"Text" {
	    if {![lempty [curselection $w]]} {
		eval $w tag remove sel [$w tag ranges sel]
	    }
	    $w tag add sel 1.0 end
	}
    }
}

proc ::edit::undo {w} {
    if {![string length $w]} { return }
    catch { $w edit undo }
}

proc ::edit::redo {w} {
    if {![string length $w]} { return }
    catch { $w edit redo }
}

proc ::edit::curselection {w} {
    if {![string length $w]} { return }
    switch -- [winfo class $w] {
	"Entry" {
	    if {![$w selection present]} { return }
	    set idx1 [$w index sel.first]
	    set idx2 [$w index sel.last]
	    set text [string range [$w get] $idx1 $idx2]
	}

	"Text" {
	    if {[catch {$w get sel.first sel.last} text]} { return }
	}
    }
    return $text
}

} ; ## namespace eval ::editor
Added lib/file.tcl.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc Open { {filename ""} } {
    global conf
    global info
    global widg

    variable ::InstallJammer::Properties

    if {$conf(loading)} { return }

    if {$filename eq ""} {
	set types {
	    {"InstallJammer Project Files"  .mpi}
	    {"All Files"                    *}
	}

	set filename [mpi_getOpenFile -filetypes $types]

        if {$filename eq ""} { return }

	update
    }

    if {![file exists $filename]} {
        return -code error "invalid file '$filename' specified"
    }

    if {!$conf(cmdline)} {
        set ext [file extension $filename]
        switch -- $ext {
            ".action" {
                ::InstallJammer::InstallNewActionFile $filename
                return
            }

            ".condition" {
                ::InstallJammer::InstallNewConditionFile $filename
                return
            }
        }
    }

    set conf(loading) 1

    if {![Close]} {
        set conf(loading) 0
        return
    }

    ## Set the project defaults.  Any variables that already exists
    ## in the info array will not be overwritten.
    Status "Setting project defaults..."
    ::InstallJammer::SetProjectDefaults 1

    Status "Opening project file..."

    ::InstallJammer::InitializeObjects

    set modified 0

    if {[info commands ::_fileClass] eq ""} {
        rename ::File ::_fileClass
        proc File { args } { lappend ::filesLoaded $args }
    }
    set ::filesLoaded {}

    if {[catch { eval [read_file $filename -encoding utf-8] } error]} {
        if {[vercmp $info(ProjectVersion) $conf(InstallJammerVersion)] == 1} {
            ::InstallJammer::Error -message "This project file was made with\
                a newer version ($info(ProjectVersion)) of InstallJammer and\
                cannot be loaded in this version."
        } else {
            ::InstallJammer::Error -message "Could not open '$filename': $error"
        }
        set conf(loading) 0
        ClearStatus
        return
    }

    set info(Project)     [file root [file tail $filename]]
    set info(ProjectDir)  [file dirname $filename]
    set info(ProjectFile) [file normalize $filename]

    ::InstallJammer::StatusPrefix "Loading $info(Project)...  "

    rename ::File ""
    rename ::_fileClass ::File

    Status "Loading files..."
    foreach file $::filesLoaded {
        eval ::File $file
    }
    unset -nocomplain ::filesLoaded

    ## Rebuild the file map before project conversion.
    Status "Rebuilding file map..."
    ::InstallJammer::RebuildFileMap

    ## Rebuild a list of aliases.
    Status "Rebuilding aliases..."
    ::InstallJammer::RebuildAliases

    ## Convert the project from lower version numbers.
    ## This only occurs if there are format changes in the projects
    ## between versions.
    incr modified [ConvertProject]

    if {$conf(cmdline) && $modified} {
        ::InstallJammer::Message -message "\nThis project must be converted\
            to the new version of\nInstallJammer before it can be built\
            from the command-line.\nPlease load the project in the\
	    InstallJammer builder\nand save the project after it has been\
	    converted.\n"
        ::exit 1
    }

    ## Check the theme for this install and see if it has been updated.
    ConvertTheme

    set conf(ActiveProject) $info(Project)

    if {!$conf(cmdline)} {
        Status "Initializing Trees..."

        AddToRecentProjects $filename

        InitComponentTrees
    }

    Status "Loading [::InstallJammer::StringToTitle $info(Theme)] Theme..."
    if {![LoadTheme $info(ProjectDir)]} {
	Close 1
        set conf(loading) 0
        ClearStatus
	return
    }

    ::InstallJammer::LoadVirtualText

    ::InstallJammer::LoadCommandLineOptions

    if {!$conf(cmdline)} {
        Status "Adding Files to tree..."

        ## Add files and directories that are a direct descendent
        ## of a file group to the tree.  The rest will be created
        ## as the user opens tree nodes.
        foreach filegroup [FileGroups children] {
            ::FileGroupTree::New -id $filegroup
            foreach file [$filegroup children] {
                AddToFileGroup -id $file
            }

            ::FileGroupTree::SortNodes [::InstallJammer::NodeName $filegroup]
        }
    }

    ## Now that everything is all in place, rebuild the file map
    ## again, just incase anything changed in the conversion process.
    if {$modified} {
        Status "Rebuilding file map after conversion..."
        ::InstallJammer::RebuildFileMap
    }

    Status "Adding Components..."
    ::InstallJammer::LoadInstallComponents

    Status "Initializing conditions..."
    ::InstallJammer::LoadInstallConditions

    if {!$conf(cmdline)} {
        Status "Loading Project Preferences..."
        ::InstallJammer::LoadProjectPreferences

        ::InstallJammer::Tree::FinishOpenProject

        tag configure project -state normal
    }

    ## Look for any platforms that didn't previously exist
    ## in our project file and build a list of them.  Set
    ## new platforms to inactive by default.

    Status "Initializing platforms..."
    set newplatforms [list]
    foreach platform [AllPlatforms] {
        if {[$platform get Active] eq "NEW"} {
            $platform set Active "No"
            lappend newplatforms $platform
        }
    }

    ## If we're not building from the command-line we want
    ## to add any new platforms to all of our File Groups,
    ## Components and Setup Types.
    ##
    ## This doesn't make these platforms active, but it does
    ## mean that if they are set to active, all of the install
    ## components will include the new platform by default.

    if {!$conf(cmdline) && [llength $newplatforms]} {
        foreach class {FileGroup Component SetupType} {
            foreach obj [itcl::find objects -class $class] {
                $obj platforms [concat [$obj platforms] $newplatforms]
            }
        }
    }

    set conf(loading)       0
    set conf(projectLoaded) 1

    ::InstallJammer::FilesModified 0

    if {!$conf(cmdline)} {
        Modified $modified

        BuildInstall
        update

        if {$modified} {
            Save
            ::InstallJammer::MessageBox -message "Your project has been\
                automatically converted to a new version.\nA backup of your\
                previous project file has been saved in the project directory."
        }

        Status "$info(Project) loaded" 3000
        ::InstallJammer::StatusPrefix
    } else {
        set platforms [concat [AllPlatforms] $conf(Archives)]
        foreach pf $platforms { set conf(build,$pf) 1 }

        if {[info exists conf(platformBuildList)]} {
            foreach pf $platforms { set conf(build,$pf) 0 }
            foreach pf $conf(platformBuildList) {
                if {$pf eq "tar"} { set pf "TarArchive" }
                if {$pf eq "zip"} { set pf "ZipArchive" }
                set conf(build,$pf) 1
            }
        }

        set buildPlatforms {}
        foreach pf $platforms {
            if {$conf(build,$pf)} {
                $pf properties props
                lappend buildPlatforms $pf
            }
        }

        if {[info exists conf(CommandLineOptions)]} {
            set platformVars [array names props]

            foreach {var val} $conf(CommandLineOptions) {
                if {[lsearch -exact $platformVars $var] < 0} {
                    set info($var) $val
                } else {
                    foreach pf $buildPlatforms {
                        $pf set $var $val
                    }
                }
            }
        }

        if {[info exists conf(CommandLineOptionFiles)]} {
            foreach optfile $conf(CommandLineOptionFiles) {
                uplevel #0 source [list $optfile]
            }
        }
    }

    lassign [split $info(InstallVersion) .] a b c d
    SafeArraySet info \
        [list MajorVersion $a MinorVersion $b PatchVersion $c BuildVersion $d]
    set    info(InstallVersion) "$info(MajorVersion).$info(MinorVersion)"
    append info(InstallVersion) ".$info(PatchVersion).$info(BuildVersion)"
    return
}

proc Save {} {
    global conf
    global info
    global widg

    if {!$conf(projectLoaded)} {
	::InstallJammer::Message -message "No project loaded!"
	return
    }

    if {![info exists info(ProjectFile)]
        || ![string length $info(ProjectFile)]} {
    	SaveAs
	return
    }

    if {[file exists $info(ProjectFile)]
        && ![file writable $info(ProjectFile)]} {
        set ans [::InstallJammer::MessageBox -type yesno -message \
            "Your project file cannot be written because it is read-only.\nDo\
            you want to make the file writable and save anyway?"]
        if {$ans eq "no"} { return }
        if {[catch {
            if {$conf(windows)} {
                file attributes $info(ProjectFile) -readonly 0
            } else {
                file attributes $info(ProjectFile) -permissions u+w
            }
        } error]} {
            ::InstallJammer::MessageBox -message "Failed to make your project\
                file writable.  Your project could not be saved."
            return
        }
    }

    ::InstallJammer::StatusPrefix "Saving $info(Project)...  "

    set info(ProjectVersion) $conf(InstallJammerVersion)

    ::InstallJammer::SaveActiveComponent

    set dir [file dirname $info(ProjectFile)]
    if {![file exists $dir]} { file mkdir $dir }

    ## Store a copy of all of the properties before we start
    ## saving because some of the save procedures might
    ## manipulate the properties.
    variable  ::InstallJammer::SaveProperties
    array set SaveProperties [array get ::InstallJammer::Properties]

    set    data ""

    Status "Storing project info..."
    append data [::InstallJammer::SaveInfoArray]\n

    append data [::InstallJammer::GetCommandLineOptionData -setup Install]\n
    append data [::InstallJammer::GetCommandLineOptionData -setup Uninstall]\n

    Status "Saving file groups..."
    append data [::InstallJammer::SaveFileGroupsAndComponents]\n

    Status "Saving interface components..."
    append data [::InstallJammer::SaveInstallComponents]\n

    Status "Saving properties..."
    append data [::InstallJammer::SaveProperties]\n

    Status "Saving text properties..."
    append data [::InstallJammer::GetTextData]\n

    set fp [open $info(ProjectFile) w]
    fconfigure $fp -translation lf -encoding utf-8
    puts -nonewline $fp $data
    close $fp

    Status "Saving project preferences..."
    ::InstallJammer::SaveProjectPreferences

    AddToRecentProjects $info(ProjectFile)

    ::InstallJammer::SetLastSaved

    Status "Done saving." 3000
    ::InstallJammer::StatusPrefix

    Modified 0
}

proc SaveAs {} {
    global info
    set file [mpi_getSaveFile]
    if {[lempty $file]} { return }
    set info(ProjectFile) [file normalize $file]
    Save
}

proc Close { {force 0} {message ""} } {
    global conf
    global info
    global widg

    if {!$conf(projectLoaded)} { return 1 }

    if {$conf(building)} {
        ::InstallJammer::MessageBox -icon error -title "Build in progress" \
            -message "A build is in progress.  You cannot close this project."
	return 0
    }

    if {!$force && $conf(modified)} {
    	if {$message eq ""} {
	    set message "Project has been modified.  Do you wish to save?"
	}

        set ans [::InstallJammer::MessageBox -type yesnocancel \
            -title "Project Modified" -message $message]
	if {$ans eq "yes"} { Save }
	if {$ans eq "cancel"} { return 0 }
    }

    if {$conf(exiting)} { return 1 }

    Status "Closing $info(Project)..."

    if {!$conf(loading)} {
        $widg(Main) tab $widg(InstallDesignerTab) -state disabled
    }

    ClearComponentTrees

    ::InstallJammer::ClearInstallComponents

    ::InstallJammer::CleanupObjects

    set vars {
        ::info
        ::InstallJammer::aliases
        ::InstallJammer::aliasmap
        ::InstallJammer::FileMap
        ::InstallJammer::Properties
        ::InstallJammer::ActiveComponent
        ::InstallJammer::ActiveComponents
    }

    foreach var $vars {
	unset -nocomplain $var
    }

    set conf(building)      0
    set conf(ActiveProject) ""

    UpdateRecentProjects

    ::InstallJammer::LoadMessages

    ::InstallJammer::ClearBuildLog

    ::InstallJammer::preview::Cleanup

    ::InstallJammer::SetActiveComponent

    unset -nocomplain ::InstallJammer::NewFiles

    if {[info exists widg(BuildTree)]} {
        eval [list $widg(BuildTree) delete] [$widg(BuildTree) nodes root]
    }

    ::InstallJammer::ClearVirtualText

    ::InstallJammer::ClearCommandLineOptions

    tag configure project -state disabled

    $widg(Product) reset
    ::InstallJammer::SetHelp <default>

    set conf(projectLoaded) 0

    if {!$conf(loading)} { $widg(Main) select $widg(InstallDesignerTab) }

    unset -nocomplain info

    Modified 0
    ::InstallJammer::FilesModified 0

    ClearStatus

    ::InstallJammer::SetMainWindowTitle

    return 1
}

proc ReadableArrayGet { arrayName {newname ""} {arrayset ""} } {
    upvar 1 $arrayName array

    if {![string length $newname]} { set newname $arrayName }
    if {![string length $arrayset]} { set arrayset "array set $newname" }

    append string "$arrayset \{\n"
    foreach elem [lsort [array names array]] {
	append string "[list $elem]\n"
        if {[catch {array set x "x \{$array($elem)\}"}]} {
            append string "[list $array($elem)]\n\n"
        } else {
            append string "\{$array($elem)\}\n\n"
        }
    }
    append string "\}"
    return $string
}

proc ProcDefinition { proc {tail 1} } {
    if {[lempty [info procs $proc]]} { return }
    set args [list]
    foreach arg [info args $proc] {
	if {[info default $proc $arg def]} {
	    lappend args [list $arg $def]
	} else {
	    lappend args $arg
	}
    }

    set body [info body $proc]

    if {$tail} { set proc [namespace tail $proc] }

    append str "proc $proc \{$args\} \{"
    append str $body
    append str "\}\n"
    return $str
}

proc ::InstallJammer::GetWindowProcData { args } {
    global info
    global conf

    variable ::InstallJammer::panes
    
    array set _args {
        -build          0
        -setups         {}
        -activeonly     0
    }
    array set _args $args

    if {![llength $_args(-setups)]} { set _args(-setups) $conf(ThemeDirs) }

    set data ""

    foreach setup $_args(-setups) {
        foreach pane $conf(PaneList,$setup) {
            uplevel #0 [list source [$panes($pane) tclfile]]
        }

        set panelist [GetPaneComponentList $setup $_args(-activeonly)]

        foreach id $panelist {
            uplevel #0 [list source [::InstallJammer::GetPaneSourceFile $id]]

            set obj [$id object]
            foreach include [$obj includes] {
                if {![info exists panes($include)]} { continue }
                if {[lsearch -exact $panelist $include] < 0} {
                    lappend panelist $include
                }
            }
        }

	set procs [list]
	foreach id $panelist {
            if {[info exists panes($id)]} {
                set pane $id
            } else {
                set pane [$id component]
            }

            set proc1  CreateWindow.$pane
            set proc2  CreateWindow.$id
            set exists [::InstallJammer::CommandExists $proc1]
            set done  0

            if {$exists} {
                set body1 [string trim [info body $proc1]]
            }

            if {[::InstallJammer::CommandExists $proc2]} {
                set body2 [string trim [info body $proc2]]
                if {!$exists || ![string equal $body1 $body2]} {
                    set done 1
                    append data [ProcDefinition $proc2]\n
                }
            }

            if {$exists && !$done && $_args(-build)} {
                ## If we're in build mode and no proc exists for
                ## this component, store the original pane proc.
                append data [ProcDefinition $proc1]\n
            }
	}
    }

    return $data
}

proc ::InstallJammer::GetTextData { args } {
    global info
    global conf

    array set _args {
        -build          0
        -setups         {}
        -activeonly     0
    }
    array set _args $args

    variable ::InstallJammer::panes

    if {![llength $_args(-setups)]} { set _args(-setups) $conf(ThemeDirs) }

    set data ""

    set languages [::InstallJammer::GetLanguageCodes]

    foreach lang $languages {
        upvar #0 ::InstallJammer::Msgs_$lang messages
        upvar 0 msgs_$lang langdata

        if {$_args(-build)} {
            array set langdata [::msgcat::mcgetall $lang]
        } else {
            array set msgs [::msgcat::mcgetall $lang]

            foreach var [array names msgs] {
                ## If we're not building, we only want to save
                ## messages that have changed from their original
                ## default values.
                if {![info exists messages($var)]
                    || $msgs($var) ne $messages($var)} {
                    set langdata($var) $msgs($var)
                }
            }
        }

        unset -nocomplain msgs
    }

    foreach lang $languages {
        if {[info exists msgs_$lang] && [llength [array names msgs_$lang]]} {
            append data \
                [ReadableArrayGet msgs_$lang $lang "::msgcat::mcmset $lang"]\n
        }
    }

    return $data
}

proc ::InstallJammer::SaveInfoArray {} {
    global conf

    set remove {
        Date
        DateFormat
        Platform
        Project
        ProjectDir
        ProjectFile

        MajorVersion
        MinorVersion
        PatchVersion
        BuildVersion
    }

    array set tmp [array get ::info]
    foreach var $remove {
        unset -nocomplain tmp($var)
    }

    return [ReadableArrayGet tmp info]\n
}

proc ::InstallJammer::SaveProperties { args } {
    global conf

    variable ::InstallJammer::PropertyMap

    array set _args {
        -build       0
        -array       "Properties"
        -activeonly  0
        -includecomments 1
    }
    set _args(-setup) $conf(ThemeDirs)
    array set _args $args

    ## FIXME: The properties saved to uninstall data do not
    ## include any changes made for the install.

    ## Use the SaveProperties array instead of the real
    ## Properties array since some properties may have
    ## changed over the course of saving.
    if {[info exists ::InstallJammer::SaveProperties]} {
        upvar #0 ::InstallJammer::SaveProperties Properties
    } else {
        variable ::InstallJammer::Properties
    }

    set build $_args(-build)

    foreach platform [AllPlatforms] {
        array set props [array get Properties $platform,*]
    }

    foreach archive $conf(Archives) {
        array set props [array get Properties $archive,*]
    }

    foreach setup $_args(-setup) {
        foreach id [GetComponentList $setup $_args(-activeonly)] {
            set obj [$id object]
            if {$obj eq ""} { continue }

            foreach prop [$obj properties] {
                ## Skip standard properties that are empty.
                if {($prop eq "Comment" || $prop eq "Data" || $prop eq "Alias")
                    && $Properties($id,$prop) eq ""} { continue }

                set value $Properties($id,$prop)
                if {$build && [info exist PropertyMap($prop)]} {
                    set value [lsearch -exact $PropertyMap($prop) $value]
                }

                if {$build || [$obj default $prop] ne $Properties($id,$prop)} {
                    set props($id,$prop) $value
                }
            }

            foreach field [$obj textfields] {
                set props($id,$field,subst) $Properties($id,$field,subst)
            }

            foreach cid [$id conditions] {
                set condobj [$cid object]

                foreach prop [$condobj properties] {
                    ## Skip standard properties that are empty.
                    if {($prop eq "Comment" || $prop eq "Data"
                        || $prop eq "Alias") && $Properties($cid,$prop) eq ""} {
                        continue
                    }

                    set value $Properties($cid,$prop)
                    if {$build && [info exist PropertyMap($prop)]} {
                        set value [lsearch -exact $PropertyMap($prop) $value]
                    }

                    set default [$condobj default $prop]
                    if {$build || $Properties($cid,$prop) ne $default} {
                        set props($cid,$prop) $value
                    }
                }

                foreach field [$condobj textfields] {
                    set props($cid,$field,subst) $Properties($cid,$field,subst)
                }
            }
        }
    }

    unset -nocomplain ::InstallJammer::SaveProperties

    if {!$_args(-includecomments)} {
        array unset props *,Comment
    }

    return [ReadableArrayGet props $_args(-array)]\n
}

proc ::InstallJammer::SaveBuildInformation { args } {
    set data ""

    ## Store a copy of all of the properties before we start
    ## saving because some of the save procedures might
    ## manipulate the properties.
    variable  ::InstallJammer::SaveProperties
    array set SaveProperties [array get ::InstallJammer::Properties]

    foreach type [list FileGroup Component SetupType] {
        append data "$type ::${type}s\n"
    }
    lappend args -build 1
    append data [eval ::InstallJammer::SaveFileGroupsAndComponents $args]

    return $data
}

proc ::InstallJammer::SavePlatforms { args } {
    global conf

    set data ""

    foreach platform [AllPlatforms] {
        append data "Platform ::$platform [$platform serialize]\n"
    }

    foreach archive $conf(Archives) {
        append data "Platform ::$archive [$archive serialize]\n"
    }

    return $data
}

proc ::InstallJammer::SaveFileGroups { args } {
    variable save

    array set _args {
        -build     0
        -savefiles 1
    }
    array set _args $args

    set data ""

    foreach id [FileGroups children] {
        if {[info exists _args(-platform)]
            && [lsearch -exact [$id platforms] $_args(-platform)] < 0} {
            continue
        }

        if {$_args(-build) && ![$id active]} { continue }

        set save($id) 1

        append data "FileGroup ::$id [$id serialize]\n"
        if {!$_args(-build) && $_args(-savefiles)} {
            append data [::InstallJammer::SaveSetupFiles $id]
        }
    }

    return $data
}

proc ::InstallJammer::SaveSetupFiles { id } {
    global info

    set data ""

    set parent [$id parent]
    if {[$parent is filegroup] && ($info(SaveOnlyToplevelDirs)
        || [string is false -strict [$parent get SaveFiles]])} { return }

    foreach id [$id children] {
        append data "File ::$id [$id serialize]\n"
        if {[$id is dir] && [string is false -strict [$id savefiles]]} {
            continue
        }
        append data [::InstallJammer::SaveSetupFiles $id]
    }

    return $data
}

proc ::InstallJammer::SaveComponents { args } {
    variable save

    variable ::InstallJammer::SaveProperties

    array set _args {
        -build  0
    }

    array set _args $args

    set data ""

    set save(Components) 1
    foreach id [Components children recursive] {
        if {[info exists _args(-platform)]
            && [lsearch -exact [$id platforms] $_args(-platform)] < 0} {
            continue
        }

        if {$_args(-build) && ![$id active]} { continue }

        set parent [$id parent]
        if {$_args(-build) && ![info exists save($parent)]} {
            BuildLog "Removing [$id name] component: parent not included"
            continue
        }

        set save($id) 1

        foreach filegroup [$id get FileGroups] {
            if {![info exists save($filegroup)]} {
                set SaveProperties($id,FileGroups) \
                    [lremove $SaveProperties($id,FileGroups) $filegroup]
                BuildLog "Removing [$filegroup name] file group from\
                    [$id name] component." -logtofile 0
            }
        }

        append data "Component ::$id [$id serialize]\n"
    }

    return $data
}

proc ::InstallJammer::SaveSetupTypes { args } {
    variable save

    variable ::InstallJammer::SaveProperties

    array set _args {
        -build  0
    }

    array set _args $args

    set data ""

    foreach id [SetupTypes children] {
        if {[info exists _args(-platform)]
            && [lsearch -exact [$id platforms] $_args(-platform)] < 0} {
            continue
        }

        if {$_args(-build) && ![$id active]} { continue }

        set save($id) 1

        foreach component [$id get Components] {
            if {![info exists save($component)]} {
                set SaveProperties($id,Components) \
                    [lremove $SaveProperties($id,Components) $component]
                BuildLog "Removing [$component name] component from\
                    [$id name] setup type." -logtofile 0
            }
        }

        append data "SetupType ::$id [$id serialize]\n"
    }

    return $data
}

proc ::InstallJammer::SaveFileGroupsAndComponents { args } {
    variable save

    unset -nocomplain save

    set data ""

    Status "Saving file groups..."
    append data [eval SaveFileGroups $args]

    Status "Saving components..."
    append data [eval SaveComponents $args]

    Status "Saving setup types..."
    append data [eval SaveSetupTypes $args]

    unset -nocomplain save

    return $data
}

proc ::InstallJammer::IgnoreDir {dir} {
    foreach pattern $::info(IgnoreDirectories) {
        if {[regexp -- $pattern $dir]} { return 1 }
    }
    return 0
}

proc ::InstallJammer::IgnoreFile {file} {
    set tail [file tail $file]
    foreach pattern $::info(IgnoreFiles) {
        if {[regexp -- $pattern $tail]} { return 1 }
    }
    return 0
}

proc ::InstallJammer::RecursiveGetFiles { parent {followLinks 1}
                                            {linkParent ""} } {
    global conf
    variable LinkDirs

    set first 0
    if {$linkParent eq ""} {
        set first 1
        set linkParent $parent
        set LinkDirs($linkParent) ""
    }

    set ids [list $parent]
    set dir [::InstallJammer::GetFileSource $parent]

    set files [glob -type f -nocomplain -directory $dir *]
    eval lappend files [glob -type {f hidden} -nocomplain -directory $dir *]

    foreach file [lsort -dict $files] {
        if {[::InstallJammer::IgnoreFile $file]} { continue }
        set id [::InstallJammer::FileObj $parent $file -type file]
        if {[$id active]} { lappend ids $id }
    }

    set dirs [glob -type d -nocomplain -directory $dir *]
    eval lappend dirs [glob -type {d hidden} -nocomplain -directory $dir *]

    foreach dir [lsort -dict $dirs] {
        if {[::InstallJammer::IgnoreDir $dir]} { continue }

        set tail [file tail $dir]
        if {$tail eq "." || $tail eq ".."} { continue }

        if {[file type $dir] eq "link"} {
            if {$followLinks} {
                set link $tail,[file normalize [file readlink $dir]]
                if {[lsearch -exact $LinkDirs($linkParent) $link] > -1} {
                    continue
                }
                lappend LinkDirs($linkParent) $link
            } else {
                set id [::InstallJammer::FileObj $parent $dir -type file]
                if {[$id active]} { lappend ids $id }
                continue
            }
        }

        set id [::InstallJammer::FileObj $parent $dir -type dir]
        if {[$id active]} {
            eval lappend ids [::InstallJammer::RecursiveGetFiles \
                $id $followLinks $linkParent]
        }
    }

    if {$first} { unset -nocomplain LinkDirs }

    return $ids
}

proc ::InstallJammer::RefreshFileGroups {} {
    global conf
    global info
    global widg

    set msg "Refreshing file groups..."

    if {$conf(building)} {
        BuildLog $msg
    } else {
        Status $msg
    }

    set conf(SortTreeNodes) {}

    if {$info(IgnoreFiles) ne $info(LastIgnoreFiles)
        || $info(IgnoreDirectories) ne $info(LastIgnoreDirectories)} {
        set ids {}
        foreach group [FileGroups children] {
            foreach id [$group children recursive] {
                set path [::InstallJammer::GetFileSource $id]

                if {[$id is dir] && [::InstallJammer::IgnoreDir $path]} {
                    lappend ids $id
                    continue
                }

                if {[::InstallJammer::IgnoreFile $path]
                    || [::InstallJammer::IgnoreDir [file dirname $path]]} {
                    lappend ids $id
                }
            }
        }

        if {[llength $ids]} { ::InstallJammer::DeleteFilesFromTree $ids }
    }

    set info(LastIgnoreFiles)       $info(IgnoreFiles)
    set info(LastIgnoreDirectories) $info(IgnoreDirectories)

    foreach group [FileGroups children] {
        foreach id [$group children] {
            if {[$id is dir]} {
                set follow [$group get FollowDirLinks]
                ::InstallJammer::RecursiveGetFiles $id $follow
            }
        }
    }

    if {[info exists widg(FileGroupTree)]} {
	foreach node [lsort -unique $conf(SortTreeNodes)] {
	    ::FileGroupTree::SortNodes $node
	}

	::InstallJammer::RedrawFileTreeNodes
    }

    unset conf(SortTreeNodes)

    ClearStatus
}

proc ::InstallJammer::GetSetupFileList { args } {
    global conf
    global info

    variable save

    array set _args {
        -platform    ""
        -checksave   0
        -includedirs 0
        -listvar     ""
        -errorvar    ""
        -procvar     ""
    }
    array set _args $args

    set append 0
    if {[string length $_args(-listvar)]} {
        set append 1
        upvar 1 $_args(-listvar) filelist
    }

    set doproc 0
    if {[string length $_args(-procvar)]} {
        set doproc 1
        upvar 1 $_args(-procvar) procData
        set procData "proc ::InstallJammer::InitFiles {} \{\n"
    }

    if {$_args(-errorvar) ne ""} {
        upvar 1 $_args(-errorvar) missing
        set missing {}
    }

    set groups [FileGroups children]

    set platform $_args(-platform)

    if {$info(SkipUnusedFileGroups)} {
        set groups     [list]
        set components [Components children recursive]
        if {$platform ne "" && [::InstallJammer::IsRealPlatform $platform]} {
            foreach component $components {
                set platforms [$component platforms]
                if {[lsearch -exact $platforms $_args(-platform)] < 0} {
                    set components [lremove $components $component]
                }
            }
        }

        foreach component $components {
            foreach group [$component get FileGroups] {
                if {[lsearch -exact $groups $group] < 0} {
                    lappend groups $group
                }
            }
        }
    }

    set files {}
    foreach group $groups {
        if {$platform ne ""
            && [lsearch -exact [$group platforms] $platform] < 0} { continue }

        if {![$group active]
            || ($_args(-checksave) && ![info exists save($group)])} { continue }

        set ids {}
        set groupsize 0

        set preserveAttributes 0
        if {$conf(windows) && $platform eq "Windows"
            && $info(PreserveFileAttributes)} { set preserveAttributes 1 }

        set preservePermissions 0
        if {!$conf(windows) && $platform ne "Windows"
            && $info(PreserveFilePermissions)} { set preservePermissions 1 }

        set followDirs  [$group get FollowDirLinks]
        set followFiles [$group get FollowFileLinks]

        set parents($group) 1
        foreach id [$group children recursive] {
            if {![::InstallJammer::GetFileActive $id]} { continue }

            if {![info exists parents([$id parent])]} { continue }

            set file [::InstallJammer::GetFileSource $id]

            if {[catch { file lstat $file s }]} {
                lappend missing $file
                continue
            }
            
            set type $s(type)
            set doappend $append
            if {$type eq "link"} {
                file stat $file s
                set type $s(type)
                if {$platform ne "Windows"} {
                    if {($s(type) eq "file" && !$followFiles)
                        || ($s(type) eq "directory" && !$followDirs)} {
                        set type link
                        set doappend 0
                    }
                }
            }

            if {$type eq "directory"} {
                set parents($id) 1
                if {!$_args(-includedirs)} { set doappend 0 }
            }

            if {$doproc} {
                append procData "    File ::$id"
                append procData " -name [list [$id destfilename]]"
                append procData " -parent [list $group]"

                set alias [$id alias]
                if {$alias ne ""} {
                    append procData " -alias [list $alias]"
                }

                set dir [::InstallJammer::GetFileDestination $id]
                if {$type ne "directory"} { set dir [file dirname $dir] }
                append procData " -directory [list $dir]"

                if {$type eq "link"} {
                    append procData " -type link"
                    append procData " -linktarget [list [file link $file]]"
                } elseif {$type eq "directory"} {
                    append procData " -type dir"
                } else {
                    if {$s(size)} { append procData " -size $s(size)" }
                    append procData " -mtime $s(mtime)"
                }

                set version [::InstallJammer::GetFileVersion $id]
                if {$version ne ""} {
                    append procData " -version $version"
                }

                set attributes [$id attributes]
                if {$attributes eq "" && $preserveAttributes} {
                    array set a [file attributes $file]
                    append attributes $a(-archive) $a(-hidden) \
                        $a(-readonly) $a(-system)
                }

                if {$attributes ne ""} {
                    append procData " -attributes $attributes"
                }

                set permissions [$id permissions]
                if {$permissions eq "" && $preservePermissions} {
                    set permissions [file attributes $file -permissions]
                }

                if {$permissions ne ""} {
                    append procData " -permissions $permissions"
                }

                set method [::InstallJammer::GetFileMethod $id 1]
                if {$method ne ""} {
                    append procData " -filemethod $method"
                }

                append procData "\n"
            }

            if {$doappend} {
                lappend filelist [list $id $file $group $s(size) $s(mtime)]
            }

            incr groupsize $s(size)
        }

        $group set FileSize $groupsize
    }

    if {$doproc} { append procData "\n\}" }

    return
}

proc ::InstallJammer::ClearInstallComponents {} {
    global conf
    global widg

    foreach setup $conf(ThemeDirs) {
        set tree $widg($setup)
        $tree reset
        foreach node [$tree nodes root] {
            $tree close $node
            eval $tree delete [$tree nodes $node]
        }
    }
}

proc ::InstallJammer::ComponentIsActive { id } {
    if {![$id active]} { return 0 }

    set parent [$id parent]
    while {[string length $parent]} {
        if {![$parent active]} { return 0 }
        set parent [$parent parent]
    }
    return 1
}

proc ::InstallJammer::SaveInstallComponents { args } {
    global conf
    global info

    array set _args {
        -setup          ""
        -build          0
        -activeonly     0
        -actiongroupvar ""
    }
    array set _args $args

    if {$_args(-build) && $_args(-actiongroupvar) ne ""} {
        upvar 1 $_args(-actiongroupvar) actionGroupData
        set _args(-actiongroupvar) actionGroupData
        set actionGroupData ""
    }

    set data ""
    foreach type [InstallTypes children] {
        set var       data
        set setup     [$type setup]
        set storetype [string map [list $setup ""] $type]

        if {$_args(-setup) ne "" && $setup ne $_args(-setup)} { continue }

        if {$_args(-build)} {
            if {[info exists actionGroupData]} {
                append actionGroupData "InstallType ::$storetype\n"

                if {[string match "ActionGroups*" $type]} {
                    set var actionGroupData
                }
            } else {
                append data "InstallType ::$storetype\n"
            }
        }

        append $var [eval ::InstallJammer::SaveComponentData \
                -type $type -object $type [array get _args]]
    }

    return $data
}

proc ::InstallJammer::SaveComponentData { args } {
    array set _args {
        -type       ""
        -setup      ""
        -build      0
        -object     ""
        -activeonly 0
    }
    array set _args $args

    set data  ""
    set type  $_args(-type)
    set setup $_args(-setup)

    set storetype [string map [list [$type setup] ""] $type]
    foreach id [$_args(-object) children] {
        if {$_args(-activeonly) && ![ComponentIsActive $id]} { continue }
        if {[string length $setup] && [$id setup] ne $setup} { continue }

        set opts [$id serialize]

        if {$_args(-build) && [[$id parent] isa InstallType]} {
            set x [lsearch -exact $opts "-parent"]
            set opts [lreplace $opts $x [incr x] -parent $storetype]
        }

        append data "InstallComponent $id $opts\n"

        foreach cid [$id conditions] {
            if {$_args(-activeonly) && ![$cid active]} { continue }
            append data "Condition $cid [$cid serialize]\n"
        }

        append data [eval ::InstallJammer:::SaveComponentData $args -object $id]
    }

    return $data
}

proc ::InstallJammer::LoadInstallComponents {} {
    global conf
    global widg

    if {$conf(cmdline)} {
        foreach object [::itcl::find object -isa ::InstallComponent] {
            $object initialize
        }
    } else {
        foreach setup $conf(ThemeDirs) {
            foreach type $conf(InstallTypes) {
                set obj $type$setup
                foreach id [$obj children recursive] {
                    if {[$widg($setup) exists $id]} { continue }

                    AddComponent [$id setup] -id $id \
                        -parent [$id parent] -title [$id title]
                }
            }

            foreach node [$widg($setup) nodes root] {
                if {![llength [$widg($setup) nodes $node]]} {
                    $widg($setup) itemconfigure $node -open 1
                }
            }
        }
    }

    foreach platform [concat [AllPlatforms] $conf(Archives)] {
        $platform active [$platform get Active]
    }

    if {!$conf(cmdline)} {
        ::InstallJammer::RefreshComponentTitles
    }
}

proc ::InstallJammer::LoadInstallConditions {} {
    foreach id [::itcl::find objects -class ::Condition] {
        [$id object] initialize $id
    }
}

proc BuildInstall {} {
    global conf
    global info
    global widg

    if {![info exists info(Project)]} {
    	::InstallJammer::Error -message "No project selected."
	return
    }

    ::InstallJammer::SetMainWindowTitle

    $widg(Main) tab $widg(InstallDesignerTab) -state normal
    pack $widg(Product) -expand 1 -fill both -pady 2

    tag configure project -state normal

    $widg(StopBuildButton) configure -state disabled

    foreach pf [concat [AllPlatforms] $conf(Archives)] {
        ## Add a check box to the build platform tree.
        set text [PlatformText $pf]

        set conf(build,$pf) 1
        $widg(BuildTree) insert end root #auto -type checkbutton \
            -variable ::conf(build,$pf) -text $text
    }

    $widg(Main) select $widg(InstallDesignerTab)
    $widg(Product) raise general
}

proc ::InstallJammer::RebuildFileMap {} {
    global conf

    variable ::InstallJammer::FileMap

    unset -nocomplain FileMap
    set conf(locations) [list]

    ## Walk through all of the children in each file group
    ## and make sure that we've properly setup the file map.
    foreach obj [itcl::find objects -class ::File] {
        set key [::InstallJammer::FileKey [$obj parent] [$obj name]]
        set FileMap($key) [$obj id]

        set location [$obj location]
        if {$location ne ""} { lappend conf(locations) $location }
    }

    set conf(locations) [lsort -unique $conf(locations)]
    return
}

proc ::InstallJammer::RebuildLocations {} {
    global conf

    variable ::InstallJammer::Locations

    set conf(locations) [list]

    foreach id [itcl::find objects -class ::File] {
        set location [$id location]
        if {$location ne ""} { lappend conf(locations) $location }
    }

    foreach id [array names Locations] {
        lappend conf(locations) $Locations($id)
    }

    set conf(locations) [lsort -unique $conf(locations)]

    return
}

proc ::InstallJammer::RebuildAliases {} {
    unset -nocomplain ::InstallJammer::aliases
    unset -nocomplain ::InstallJammer::aliasmap

    foreach object [::itcl::find object -isa ::InstallComponent] {
        set id    [$object id]
        set alias [$object get Alias]
        if {$alias ne ""} {
            set ::InstallJammer::aliases($alias) $id
            set ::InstallJammer::aliasmap($id) $alias
        }
    }
}

proc ::InstallJammer::InitializeObjects {} {
    global conf

    ::InstallJammer::CleanupObjects

    ::TreeObject ::FileGroups
    ::TreeObject ::Components
    ::TreeObject ::SetupTypes
    ::TreeObject ::InstallTypes

    ::TreeObject ::Platforms
    foreach platform [AllPlatforms] {
        ::Platform ::$platform -parent Platforms
    }

    foreach archive $conf(Archives) {
        ::Platform ::$archive
    }

    if {[::InstallJammer::ArchiveExists TarArchive]} {
        ::TarArchive set \
            Active No \
            CompressionLevel 6 \
            DefaultDirectoryPermission 0755 \
            DefaultFilePermission 0755 \
            OutputFileName "<%ShortAppName%>-<%Version%>.tar.gz" \
            VirtualTextMap {<%InstallDir%> <%ShortAppName%>}
    }

    if {[::InstallJammer::ArchiveExists ZipArchive]} {
        ::ZipArchive set \
            Active No \
            CompressionLevel 6 \
            OutputFileName "<%ShortAppName%>-<%Version%>.zip" \
            VirtualTextMap {<%InstallDir%> <%ShortAppName%>}
    }

    foreach setup $conf(ThemeDirs) {
        foreach installtype $conf(InstallTypes) {
            ::InstallType ::${installtype}${setup} \
                -parent InstallTypes -setup $setup
        }
    }
}

proc ::InstallJammer::CleanupObjects {} {
    set objs {Platforms FileGroups Components SetupTypes InstallTypes}
    lappend objs TarArchive ZipArchive

    foreach obj $objs {
        if {[::InstallJammer::ObjExists ::$obj]} { ::$obj destroy }
    }

    eval ::itcl::delete obj [::itcl::find object -class ::InstallJammer::Pane]
}

proc ::InstallJammer::SavePreferences {} {
    global widg
    global preferences

    set dir  [::InstallJammer::InstallJammerHome]
    set file [::InstallJammer::InstallJammerHome preferences]

    if {![file exists $dir]} { file mkdir $dir }
    
    set preferences(Zoomed) [expr {[wm state $widg(InstallJammer)] eq "zoomed"}]

    if {$preferences(Zoomed)} { wm state $widg(InstallJammer) normal }
    set preferences(Geometry) [wm geometry $widg(InstallJammer)]

    set preferences(Geometry,FileGroupPref) \
        [list -pagewidth [$widg(FileGroupPref) cget -pagewidth]]

    foreach widget {Product ComponentPref SetupTypePref Install Uninstall} {
        set preferences(Geometry,$widget) \
            [list -treewidth [$widg($widget) cget -treewidth]]
    }

    set fp [open $file w]
    fconfigure $fp -translation lf
    puts $fp [string trim [lindex [ReadableArrayGet preferences] end]]
    close $fp
}

proc ::InstallJammer::LoadPreferences {} {
    global preferences

    set file [::InstallJammer::InstallJammerHome preferences]

    if {[file exists $file]} {
        if {[catch { array set preferences [read_file $file] } err]} {
            file delete $file
        }
    }
}

proc ::InstallJammer::SaveProjectPreferences {} {
    global info

    variable Locations

    set home [::InstallJammer::InstallJammerHome]

    if {![file exists $home]} { file mkdir $home }

    set file [::InstallJammer::InstallJammerHome $info(ProjectID).pref]

    set pref(Locations) [array get Locations]

    if {[llength $pref(Locations)]} {
        set fp [open $file w]
        fconfigure $fp -translation lf
        puts $fp [string trim [lindex [ReadableArrayGet pref] end]]
        close $fp
    }
}

proc ::InstallJammer::LoadProjectPreferences {} {
    global info

    set file [::InstallJammer::InstallJammerHome $info(ProjectID).pref]

    if {[file exists $file]} {
        array set preferences [read_file $file]

        if {[info exists preferences(Locations)]} {
            variable Locations
            array set Locations $preferences(Locations)
            unset preferences(Locations)
        }
    }
}

proc ::InstallJammer::InstallNewActionFile { file } {
    global conf

    set contents [read_file $file]
    if {![regexp {\nGroup ([^\n]+)\n} $contents -> group]} {
        set group "CustomActions"
    }

    set dir [file join $conf(lib) Actions $group]
    if {![file exists $dir]} { file mkdir $dir }

    set new [file join $dir [file tail $file]]
    if {[file exists $new]} { file rename $new $new.bak }

    file copy -force $file $new
}

proc ::InstallJammer::InstallNewConditionFile { file } {
    global conf

    set contents [read_file $file]
    if {![regexp {\nGroup ([^\n]+)\n} $contents -> group]} {
        set group "CustomConditions"
    }

    set dir [file join $conf(lib) Conditions $group]
    if {![file exists $dir]} { file mkdir $dir }

    set new [file join $dir [file tail $file]]
    if {[file exists $new]} { file rename $new $new.bak }

    file copy -force $file $new
}
Added lib/gui-common.tcl.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc BUTTON { path args } {
    eval [list ::ttk::button $path] $args
}

proc CHECKBUTTON { path args } {
    eval [list ::ttk::checkbutton $path] $args
}

proc COMBOBOX { path args } {
    array set _args $args
    if {[info exists _args(-editable)] && !$_args(-editable)} {
        unset _args(-editable)
        set _args(-state) readonly
    }

    unset -nocomplain _args(-autocomplete)

    eval [list ::ttk::combobox $path] [array get _args]
}

proc ENTRY { path args } {
    eval [list ::ttk::entry $path] $args
}

proc LISTBOX { path args } {
    eval ListBox $path -background #FFFFFF $args
}

proc MENU { path args } {
    eval [list menu $path -bd 1 -relief groove] $args
}

proc OPTIONTREE { path args } {
    eval [list OptionTree $path] $args \
        -radioimage [GetImage radio-off] -radioselectimage [GetImage radio-on] \
        -checkimage [GetImage check-off] -checkselectimage [GetImage check-on]
}

proc PANEDWINDOW { path args } {
    eval [list ::PanedWindow $path] \
        -sashpad 2 -sashwidth 4 -sashrelief ridge $args
}

proc POPUP { path args } {
    eval [list MENU $path] $args
}

proc PREFERENCES { path args } {
    eval [list ::Preferences $path] -padx 5 -treebackground #FFFFFF $args
}

proc PROGRESSBAR { path args } {
    eval [list ::ttk::progressbar $path] $args
}

proc PROPERTIES { path args } {
    eval ::Properties $path -expand 1 $args

    $path bindValue <<RightClick>> {
    	::InstallJammer::PostPropertiesRightClick %W %n %X %Y
    }

    bind $path <<PropertiesEditStart>> \
        "::InstallJammer::SetActivePropertyNode %W"

    return $path
}

proc RADIOBUTTON { path args } {
    eval [list ::ttk::radiobutton $path] $args
}

proc SPINBOX { path args } {
    eval ::spinbox $path -bg #FFFFFF $args
}

proc TREE { path args } {
    eval Tree $path -linesfill #CACACA -bg #FFFFFF -highlightthickness 0 $args
}

proc BIND { window args } {
    eval [list bind $window] $args
    if {$::conf(osx) && [string match "*Control-*" [lindex $args 0]]} {
        set event [string map {Control- Command-} [lindex $args 0]]
        eval [list bind $window] [lreplace $args 0 0 $event]
    }
}

proc ::InstallJammer::PostPropertiesRightClick { prop node x y } {
    global conf
    global widg

    set conf(x)    $x
    set conf(y)    $y
    set conf(prop) $prop
    set conf(node) $node
    $widg(PropertiesRightClick) post $x $y
}

proc mpi_chooseDirectory {args} {
    global conf
    global widg

    set data(-parent)     $widg(InstallJammer)
    set data(-initialdir) $conf(lastdir)

    array set data $args

    switch -- $::tcl_platform(platform) {
	"windows" {
	    if {[info exists data(-initialdir)]
                && [file exists $data(-initialdir)]} {
		set data(-initialdir) [file attributes $data(-initialdir) -long]
	    }
	}
    }

    if {![file exists $data(-initialdir)]} {
    	unset data(-initialdir)
    }

    set args [array get data]

    if {$conf(windows) || $conf(osx)} {
	set dir [eval tk_chooseDirectory $args]
    } else {
	set win [::InstallJammer::TopName .__chooseDirectory]
	set dir [eval [list ChooseDirectory $win -name ChooseDirectory] $args]
    }

    if {[string length $dir]} { set conf(lastdir) $dir }

    return $dir
}

proc mpi_getSaveFile {args} {
    global conf
    global widg

    set data(-parent)     $widg(InstallJammer)
    set data(-initialdir) $conf(lastdir)

    array set data $args

    if {![file exists $data(-initialdir)]} {
    	unset data(-initialdir)
    }

    if {$conf(windows) || $conf(osx)} {
        set file [eval tk_getSaveFile [array get data]]
    } else {
        set file [eval ChooseFile .__chooseFile -type save [array get data]]
    }

    if {[string length $file]} { set conf(lastdir) [file dirname $file] }

    return $file
}

proc mpi_getOpenFile {args} {
    global conf
    global widg

    set data(-parent)     $widg(InstallJammer)
    set data(-initialdir) $conf(lastdir)

    array set data $args

    if {![file exists $data(-initialdir)]} {
    	unset data(-initialdir)
    }

    if {$conf(windows) || $conf(osx)} {
        set file [eval tk_getOpenFile [array get data]]
    } else {
        set file [eval ChooseFile .__chooseFile [array get data]]
    }

    if {[string length $file]} { set conf(lastdir) [file dirname $file] }

    return $file
}

proc BrowseButton {w args} {
    eval WinButton $w -image [GetImage folderopen16] $args
    DynamicHelp::register $w balloon "Browse"
}

proc WinButton { path args } {
    return [eval [list Button $path -style Toolbutton] $args]

    eval [list button $path] -highlightthickness 0 $args -relief flat
    bind $path <Enter> {
	if {[%W cget -state] == "normal"} { %W configure -relief raised }
    }
    bind $path <Leave> [list %W configure -relief flat]
    return $path
}

proc WinMenuButton { path args } {
    return [eval [list ttk::menubutton $path] $args]

    eval [list menubutton $path] -highlightthickness 0 $args -relief flat
    bind $path <Enter> {
	if {[%W cget -state] == "normal"} { %W configure -relief raised }
    }
    bind $path <Leave> [list %W configure -relief flat]
    return $path
}

proc DirListComboBox {w platform args} {
    if {[winfo exists $w]} {
	$w configure -values [InstallDirList $platform]
	return $w
    }
    return [eval COMBOBOX $w -values [list [InstallDirList $platform]] $args]
}

proc WindowsIconComboBox { w args } {
    if {[winfo exists $w]} {
	$w configure -values [GetIconList]
	return $w
    }
    return [eval COMBOBOX $w -width 50 -values [list [GetIconList]] $args]
}

proc Window.installjammer { {base .installjammer} } {
    global conf
    global widg
    global preferences

    set widg(InstallJammer)      $base
    set widg(Main)               $base.main
    set widg(MainMenu)           $base.m
    set widg(MainEditMenu)       $base.m.edit
    set widg(MainFileMenu)       $base.m.file
    set widg(MainBuildMenu)      $base.m.build
    set widg(MainHelpMenu)       $base.m.helpm

    set geometry 800x600+50+0
    if {[info exists preferences(Geometry)]} {
        set geometry $preferences(Geometry)
    }

    if {[winfo exists $base]} {
        wm geometry  $base $geometry
        wm deiconify $base

        if {[info exists preferences(Zoomed)] && $preferences(Zoomed)} {
            wm state $base zoomed
        }

        return
    }

    toplevel    $base -class Installjammer
    wm withdraw $base
    update idletasks
    wm geometry $base $geometry
    wm protocol $base WM_DELETE_WINDOW Exit
    wm minsize  $base 640 480

    ::InstallJammer::SetMainWindowTitle

    if {[string length [package provide twapi]]} {
        set title "InstallJammer - Multiplatform Installer"
        set conf(hwin) [twapi::find_windows -text $title]
    }

    BIND all <F1> {Help $conf(HelpTopic)}

    BIND $base <F7> { Build }
    BIND $base <Control-F5> { TestInstall }

    BIND $base <Control-b> { ::InstallJammer::QuickBuild }
    BIND $base <Control-B> { ::InstallJammer::QuickBuild }
    BIND $base <Control-Shift-b> { Build }
    BIND $base <Control-Shift-B> { Build }
    BIND $base <Control-r> { TestInstall }
    BIND $base <Control-R> { TestInstall }

    BIND $base <Control-n> "NewFromWizard"
    BIND $base <Control-o> "Open"
    BIND $base <Control-s> "Save"

    InstallJammerIcons add blank -imageargs [list -width 16 -height 16]

    $base configure -menu $base.m

    ## Create the main menu
    set m [menu $widg(MainMenu)]
    MENU $widg(MainFileMenu)
    MENU $widg(MainEditMenu)
    MENU $widg(MainBuildMenu)
    MENU $widg(MainHelpMenu)

    $m add cascade -label File -menu $m.file -underline 0

    $m.file add command -label "New" -underline 0 -accel "Ctrl+N" \
    	-command New -image [GetImage filenew16] -compound left
    $m.file add command -label "New Project Wizard..." \
    	-command NewFromWizard -image [GetImage filenew16] -compound left
    $m.file add command -label "Open..." -underline 0 -accel "Ctrl+O" \
        -command Open -image [GetImage fileopen16] -compound left
    $m.file add command -label "Close" -underline 0 -command Close \
    	-image [GetImage fileclose16] -compound left
    $m.file add separator
    $m.file add command -label "Save" -underline 0 -accel "Ctrl+S" \
        -command Save -image [GetImage filesave16] -compound left
    $m.file add command -label "Save as..." -underline 5 -command SaveAs \
    	-image [GetImage filesaveas16] -compound left
    $m.file add separator
    $m.file add command -label Exit -underline 1 -command Exit \
    	-image [GetImage actexit16] -compound left
    
    tag add project [list $m.file "Save"]
    tag add project [list $m.file "Save as..."]
    tag add project [list $m.file "Close"]

    $m add cascade -label Edit -menu $m.edit -underline 0

    $m.edit add command -label Cut -underline 2 -accel "Ctrl+X" \
    	-command ::InstallJammer::EditCut \
    	-image [GetImage editcut16] -compound left
    $m.edit add command -label Copy -underline 0 -accel "Ctrl+C" \
    	-command ::InstallJammer::EditCopy \
    	-image [GetImage editcopy16] -compound left
    $m.edit add command -label Paste -underline 0 -accel "Ctrl+V" \
    	-command ::InstallJammer::EditPaste \
    	-image [GetImage editpaste16] -compound left
    $m.edit add command -label Delete -underline 0 -accel "Delete" \
    	-command ::InstallJammer::EditDelete \
    	-image [GetImage editdelete16] -compound left
    $m.edit add separator
    $m.edit add command -label "Select All" -underline 7 -accel "Ctrl+A" \
    	-command ::InstallJammer::EditSelectAll \
    	-image [GetImage blank] -compound left
    $m.edit add separator
    $m.edit add command -label "Preferences..." -underline 0 \
    	-command "Window show .preferences" \
    	-image [GetImage actconfigure16] -compound left

    tag addtag editMenu menuentries $m recursive

    $m add cascade -label Build -menu $m.build -underline 0

    $m.build add command -label "Quick Build Install" -underline 0 \
    	-accel "Ctrl+B" -command ::InstallJammer::QuickBuild \
    	-image [GetImage quickbuild16] -compound left
    $m.build add command -label "Build Install" -underline 0 \
    	-accel "Ctrl+Shift+B" -command "Build" \
    	-image [GetImage build16] -compound left
    $m.build add separator
    $m.build add command -label "Stop Build" -underline 0 \
    	-command ::InstallJammer::StopBuild \
        -image [GetImage actstop16] -compound left
    $m.build add separator
    $m.build add command -label "Run Install" -underline 0 \
    	-accel "Ctrl+R" -command "TestInstall" \
    	-image [GetImage actrun16] -compound left
    $m.build add command -label "Run Uninstall" -underline 4 \
        -command "TestUninstall" -image [GetImage edittrash16] -compound left
    tag add project [list $m.build "Build Install"]
    tag add project [list $m.build "Quick Build Install"]
    tag add project [list $m.build "Stop Build"]
    tag add project [list $m.build "Run Install"]
    tag add project [list $m.build "Run Uninstall"]

    $m add cascade -label Help -menu $m.helpm -underline 0

    if {[::InstallJammer::LocalHelpExists]} {
        $m.helpm add command -label "InstallJammer Help" \
            -underline 0 -accel "F1" -compound left \
            -image [GetImage acthelp16] -command {Help $conf(DefaultHelpTopic)}
        $m.helpm add command -label "Release Notes" -underline 0 \
            -command [list Help ReleaseNotes] -image [GetImage acthelp16] \
            -compound left
        $m.helpm add separator
    }
    $m.helpm add command -label "Online Help" -underline 0 \
        -image [GetImage acthelp16] -compound left \
    	-command [list ::InstallJammer::LaunchBrowser $conf(HelpURL)]
    $m.helpm add command -label "Online Support Forums" -underline 0 \
        -image [GetImage acthelp16] -compound left \
    	-command [list ::InstallJammer::LaunchBrowser $conf(ForumsURL)]
    $m.helpm add separator
    $m.helpm add command -label "Show Debug Console" \
	-underline 0 -command "console show" \
	-image [GetImage displayscreen16] -compound left
    $m.helpm add separator
    $m.helpm add command -label "About InstallJammer" \
        -underline 0 -command "::InstallJammer::AboutInstallJammer" \
        -image [GetImage about16] -compound left

    if {$conf(demo)} {
	$m.helpm add command -label "About Demo Mode" \
	    -underline 0 -command "Help Demo" \
	    -image [GetImage about16] -compound left
    }

    pack [Separator $base.sp1] -fill x
    set toolbar $base.toolbar
    set widg(MainToolbar) $toolbar
    pack [frame $toolbar -bd 1 -relief flat] -anchor w -fill x
    pack [Separator $base.sp2] -fill x
    pack [frame $base.sp3] -pady 5

    set b [WinButton $toolbar.new -image [GetImage filenew22] \
    	-command NewFromWizard]
    pack $b -side left
    DynamicHelp::register $b balloon "New Project Wizard"

    set b [WinButton $toolbar.open -image [GetImage fileopen22] -command Open]
    pack $b -side left
    DynamicHelp::register $b balloon "Open Install"

    set b [WinButton $toolbar.save -image [GetImage filesave22] -command Save]
    pack $b -side left
    DynamicHelp::register $b balloon "Save Install"
    tag add project $b

    set b [WinButton $toolbar.exploreProject \
        -image [GetImage filefind22] -command ::InstallJammer::ExploreProject]
    pack $b -side left
    DynamicHelp::register $b balloon "Explore Project"
    tag add project $b

    pack [Separator $toolbar.sp1 -orient vertical] \
    	-side left -fill y -padx 3 -pady 4

    set widg(BuildButton) [WinButton $toolbar.build \
        -image [GetImage build22] -command Build -state disabled]
    pack $widg(BuildButton) -side left
    DynamicHelp::register $widg(BuildButton) balloon "Build Install"
    tag add project $widg(BuildButton)

    set widg(BuildQuickButton) [WinButton $toolbar.qbuild -state disabled \
        -image [GetImage quickbuild22] -command ::InstallJammer::QuickBuild]
    pack $widg(BuildQuickButton) -side left
    DynamicHelp::register $widg(BuildQuickButton) balloon "Quick Build Install"
    tag add project $widg(BuildQuickButton)

    set widg(StopBuildButton) [WinButton $toolbar.stopbuild -state disabled \
        -image [GetImage actstop22] -command ::InstallJammer::StopBuild]
    pack $widg(StopBuildButton) -side left
    DynamicHelp::register $widg(StopBuildButton) balloon "Stop Build"
    tag add project $widg(StopBuildButton)

    set widg(TestButton) [WinButton $toolbar.test -image [GetImage actrun22] \
    	-command TestInstall -state disabled]
    pack $widg(TestButton) -side left
    DynamicHelp::register $widg(TestButton) balloon "Test Install"
    tag add project $widg(TestButton)

    WinButton $toolbar.exploreInstall -image [GetImage filefind22] \
        -command ::InstallJammer::ExploreTestInstall -state disabled
    pack $toolbar.exploreInstall -side left
    DynamicHelp::add $toolbar.exploreInstall -text "Explore Test Install"
    tag add project  $toolbar.exploreInstall

    WinButton $toolbar.uninstall -image [GetImage edittrash22] \
        -command TestUninstall -state disabled
    pack $toolbar.uninstall -side left
    DynamicHelp::add $toolbar.uninstall -text "Test Uninstall"
    tag add project  $toolbar.uninstall

    WinButton $toolbar.help \
    	-image [GetImage acthelp22] \
    	-command {Help $conf(HelpTopic)}
    pack $toolbar.help -side right
    DynamicHelp::register $toolbar.help balloon "Help"

    set status [StatusBar $base.status]
    set widg(Status) $status
    pack $status -fill x -side bottom
    set f [$status getframe]

    label $f.status -textvariable conf(status) -anchor w -width 1
    $status add $f.status -weight 1 -separator 0

    PROGRESSBAR $f.progress
    set widg(Progress) $f.progress
    $status add $f.progress -separator 0
    grid remove $widg(Progress)

    set n [ttk::notebook $widg(Main)]
    pack $widg(Main) -expand 1 -fill both

    set widg(StartPageTab) [ttk::frame $n.fProjects]
    $n add $widg(StartPageTab) -text "Start Page" \
        -compound left -image [GetImage startpage16]

    set widg(InstallDesignerTab) [ttk::frame $n.fProduct]
    $n add $widg(InstallDesignerTab) -text "Install Designer" -state disabled \
        -compound left -image [GetImage actwizard16]

    $n select $widg(InstallDesignerTab)

    ## Create the Projects tab.
    set widg(Projects) $widg(StartPageTab).c

    ScrolledWindow $widg(StartPageTab).sw
    pack $widg(StartPageTab).sw -expand 1 -fill both

    canvas $widg(Projects) -bg #FFFFFF -bd 2 -relief sunken
    $widg(StartPageTab).sw setwidget $widg(Projects)

    label  $widg(Projects).logo -image logo -background #FFFFFF
    pack   $widg(Projects).logo -side bottom -anchor se -padx 10 -pady 10

    set c $widg(Projects)
    $c bind project <1>     "::InstallJammer::LoadProject 1"
    $c bind project <3>     "::InstallJammer::ProjectPopup %X %Y"
    $c bind project <Enter> "::InstallJammer::EnterProjectItem %W"
    $c bind project <Leave> "::InstallJammer::LeaveProjectItem %W"

    ## Create the Project popup.

    set m [MENU $widg(Projects).rightClick]
    $m add command -label "Open Project" \
        -compound left -image [GetImage fileopen16] \
        -command "::InstallJammer::LoadProject"
    $m add command -label "Explore Project" \
        -compound left -image [GetImage filefind16] \
        -command "::InstallJammer::ExploreProject"
    $m add separator
    $m add command -label "Rename Project" \
        -compound left -image [GetImage editcopy16] \
        -command "::InstallJammer::RenameProject"
    $m add command -label "Duplicate Project" \
        -compound left -image [GetImage editcopy16] \
        -command "::InstallJammer::DuplicateProject"
    $m add separator
    $m add command -label "Delete Project" \
        -compound left -image [GetImage buttoncancel16] \
        -command "::InstallJammer::DeleteProject"

    ## Create the Product tab.
    set widg(Product) $widg(InstallDesignerTab).p

    set opts {}
    if {[info exists preferences(Geometry,Product)]} {
        set opts $preferences(Geometry,Product)
    }

    eval [list PREFERENCES $widg(Product) -showlines 0 -treewidth 215 \
    	-padx [list 10 0] -deltax 5 -deltay 18 -treepadx 5] $opts

    set main $widg(Product)

    $main insert end root general -text "General Information" \
        -font TkCaptionFont -haspage 0
    	$main insert end general applicationInformation \
	    -text "Application Information" \
	    -raisecommand Frame.applicationInformation
    	$main insert end general platformInformation \
	    -text "Platform Information" \
	    -raisecommand Frame.platformInformation
        $main insert end general packageAndArchiveInformation \
            -text "Package and Archive Information" \
            -raisecommand Frame.packageAndArchiveInformation

    $main insert end root groups  -text "Components and Files" \
    	-font TkCaptionFont -haspage 0
    	$main insert end groups groupsAndFiles \
	    -text "Groups and Files" \
	    -raisecommand Frame.groupsAndFiles
	$main insert end groups components \
	    -text "Components" \
	    -raisecommand Frame.components
        $main insert end groups setupTypes \
            -text "Setup Types" \
            -raisecommand Frame.setupTypes

    $main insert end root installInterface -text "Install User Interface" \
        -font TkCaptionFont -haspage 0
        $main insert end installInterface install \
            -text "Install Panes and Actions" \
            -raisecommand Frame.install
        $main insert end installInterface InstallCommandLine \
            -text "Install Command Line Options" \
            -raisecommand [list Frame.commandLine Install]

    $main insert end root uninstallInterface -text "Uninstall User Interface" \
        -font TkCaptionFont -haspage 0
        $main insert end uninstallInterface uninstall \
            -text "Uninstall Panes and Actions" \
            -raisecommand Frame.uninstall
        $main insert end uninstallInterface UninstallCommandLine \
            -text "Uninstall Command Line Options" \
            -raisecommand [list Frame.commandLine Uninstall]

    $main insert end root virtualDefinitions -text "Virtual Definitions" \
    	-font TkCaptionFont -haspage 0
    	$main insert end virtualDefinitions virtualText \
	    -text "Virtual Text Strings" \
	    -raisecommand Frame.virtualText

    $main insert end root builder -text "Run Build" \
        -font TkCaptionFont -haspage 0
    	$main insert end builder diskBuilder -text "Build Installers" \
            -raisecommand Frame.diskBuilder

    $main insert end root test -text "Test the Installation" \
        -font TkCaptionFont -haspage 0
    	$main insert end test testInstaller -text "Test Installer" \
            -raisecommand Frame.testInstaller
    	$main insert end test testUninstaller -text "Test Uninstaller" \
            -raisecommand Frame.testUninstaller

    #Frame.general
    #Frame.applicationInformation
    #Frame.platformInformation
    Frame.groupsAndFiles
    Frame.components
    Frame.setupTypes
    Frame.install
    Frame.commandLine Install
    Frame.uninstall
    Frame.commandLine Uninstall
    Frame.virtualText
    Frame.diskBuilder
    #Frame.testInstaller

    foreach node [$main nodes root] { $main open $node 1 }

    ## Create the standard right-click edit menu.
    set m [POPUP $base.editMenu -tearoff 0]
    set widg(RightClickEditMenu) $m
    $m add command -label Cut -underline 2 \
    	-command {::edit::cut $::edit::widget} \
    	-image [GetImage editcut16] -compound left
    $m add command -label Copy -underline 0 \
    	-command {::edit::copy $::edit::widget} \
    	-image [GetImage editcopy16] -compound left
    $m add command -label Paste -underline 0 \
    	-command {::edit::paste $::edit::widget} \
    	-image [GetImage editpaste16] -compound left
    $m add command -label Delete -underline 0 \
    	-command {::edit::delete $::edit::widget} \
    	-image [GetImage editdelete16] -compound left
    $m add command -label "Select All" -underline 7 \
    	-command {::edit::selectall $::edit::widget} \
    	-image [GetImage blank] -compound left
    tag addtag editMenu menuentries $m recursive

    ## Create the properties right-click menu.
    set m [POPUP $base.propertiesRightClick -tearoff 0]
    set widg(PropertiesRightClick) $m
    $m add command -label "Copy Value" \
        -command ::InstallJammer::CopyPropertiesValue \
    	-image [GetImage editcopy16] -compound left
    $m add command -label "Paste Value" \
        -command ::InstallJammer::PastePropertiesValue \
        -image [GetImage editpaste16] -compound left

    ::InstallJammer::SetHelp <default>
}

proc Frame.applicationInformation {} {
    global conf
    global widg

    set f1 [$widg(Product) getframe applicationInformation]
    set p  $f1.p

    set widg(ApplicationInformationPref) $p

    ::InstallJammer::SetHelp ApplicationInformation

    if {[winfo exists $p]} { return }

    ScrolledWindow $f1.sw -scrollbar vertical -auto vertical
    PROPERTIES $p -browseargs [list -style Toolbutton]
    $f1.sw setwidget $p
    pack $f1.sw -expand 1 -fill both

    $p insert end root standard -text "Application Information" \
        -helptext "This section describes general information about\
                your application and your project."

        $p insert end standard #auto -text "Application ID" \
            -variable info(ApplicationID) -helptext "The unique ID for this\
                application"
	$p insert end standard #auto -text "Application Name" \
	    -variable info(AppName) -helptext "The name of your application"

	$p insert end standard #auto -text "Application URL" \
	    -variable info(ApplicationURL) -helptext \
                "The main URL where people can find your application."

	$p insert end standard #auto -text "Company" \
	    -variable info(Company) -helptext "Your company name"

	$p insert end standard #auto -text "Copyright" \
	    -variable info(Copyright) -helptext "Copyright of your application"

	$p insert end standard #auto -text "Install Icon" \
	    -variable info(Icon) \
	    -browsebutton 1 -browsecommand [list GetImageFile ::info(Icon)] \
            -helptext "A standard icon to use for your install"

	$p insert end standard #auto -text "Install Image" \
	    -variable info(Image) \
	    -browsebutton 1 -browsecommand [list GetImageFile ::info(Image)] \
            -helptext "A standard image to use for your install"

	VersionFrame $f1.installVersion info -command [list $p edit finish]
	$p insert end standard #auto -text "Install Version" \
	    -variable info(InstallVersion) -editwindow $f1.installVersion \
            -editfinishcommand ::InstallJammer::FinishEditVersion -helptext \
                "The build version for your install"

	$p insert end standard #auto -text "Short Application Name" \
	    -variable info(ShortAppName) -helptext \
                "The short name of your application."

        $p insert end standard #auto -text "Upgrade Application ID" \
            -variable info(UpgradeApplicationID) -helptext "If this project\
                is an upgrade to another application, this is the unique ID\
                for that application"

	$p insert end standard #auto -text "Version String" \
	    -variable info(Version) -helptext "The version of your application"


    $p insert end root features -text "Install Features" \
        -helptext "This section defines different features that can be\
                enabled or disabled for your install project."

        $p insert end features #auto -text "Allow Language Selection" \
            -variable info(AllowLanguageSelection) -editable 0 \
            -values [list Yes No] -helptext "Allow the user to select\
                which language to use for installation"

	set actions [list "Cancel and Stop" "Continue to Next Pane"]
	lappend actions "Rollback and Stop" "Rollback and Continue to Next Pane"
	$p insert end features #auto -text "Cancelled Install Action" \
	    -variable info(CancelledInstallAction) -editable 0 \
            -values $actions -helptext "The action your install will take when\
                the user cancels in the middle of installing files"

        $p insert end features #auto -text "Default Language" \
            -variable info(DefaultLanguage) -editable 0 \
            -valuescommand ::InstallJammer::GetLanguages \
            -helptext "The default language to use during installation.  This\
                could change depending on system settings if the user is\
                allowed to select a language"

        $p insert end features #auto -text "Default to System Language" \
            -variable info(DefaultToSystemLanguage) -editable 0 \
            -values "Yes No" -helptext "Use whatever language is the\
                default on the installing system if the language has been\
                included in the installer.  If the system language is not\
                part of the installer, the Default Language will be used"

        $p insert end features #auto -text "Enable Response Files" \
            -variable info(EnableResponseFiles) -editable 0 \
            -values "Yes No" -helptext "Enable the response-file and\
                save-response-file command-line options that allow a user\
                to save responses in an installer and replay them later"

        $p insert end features #auto -text "Extract Solid Archives on Startup" \
            -variable info(ExtractSolidArchivesOnStartup) -editable 0 \
            -values [list Yes No] -helptext "Whether or not InstallJammer\
                should extract solid archives during startup or wait until\
                just before file installation"

        $p insert end features #auto -text "Install Password" \
            -variable info(InstallPassword) \
            -helptext "A password to encrypt the installer with.  The user\
                must then be prompted for a password to install"

        $p insert end features #auto -text "Wizard Height" \
            -variable info(WizardHeight) \
            -helptext "The height of the installation wizard window"

        $p insert end features #auto -text "Wizard Width" \
            -variable info(WizardWidth) \
            -helptext "The width of the installation wizard window"

    $p insert end root languages -text "Install Languages" \
        -helptext "This section defines which languages are supported by\
                        your installer."

    variable ::InstallJammer::languages
    foreach lang [::InstallJammer::GetLanguages] {
        set code $languages($lang)
        $p insert end languages #auto -text "$lang" \
            -variable info(Language,$code) -editable 0 \
            -values {Yes No} -helptext "Allow user to choose $lang as the\
                install language if Allow Language Selection is true"
    }

    $p insert end root preferences -text "Project Preferences" \
        -helptext "This section defines preferences about how InstallJammer\
                will save and build your project."

	set actions [list "Fail (recommended)" \
                "Continue without including missing files"]

	$p insert end preferences #auto -text "Build Failure Action" \
	    -variable info(BuildFailureAction) \
	    -editable 0 -values $actions -helptext "The action InstallJammer\
                will take when a file is missing while building installs from\
                within the builder"

	$p insert end preferences #auto -text "Command Line Failure Action" \
	    -variable info(CommandLineFailureAction) \
	    -editable 0 -values $actions -helptext "The action InstallJammer\
                will take when a file is missing while building installs from\
                the command line"

        for {set i 1} {$i <= 9} {incr i} { lappend levels $i }
	$p insert end preferences #auto -text "Compression Level" \
	    -variable info(CompressionLevel) -editable 0 \
            -values $levels -helptext "The level of compression to use when\
                storing files in your install with zlib compression\
                (1 = faster, 9 = smaller)"

	$p insert end preferences #auto -text "Compression Method" \
	    -variable info(CompressionMethod) -editable 0 \
            -values $conf(CompressionMethods) -helptext "The method of\
                compression to use when storing files in your install"

	$p insert end preferences #auto -text "Default Directory Location" \
	    -variable info(DefaultDirectoryLocation) -editable 1 \
            -helptext "The default location to look for files within the\
                file groups of the project."

	$p insert end preferences #auto -text "Ignore Directories" \
            -variable info(IgnoreDirectories) \
            -helptext "A list of regular expressions to match when searching\
                for new directories.  Each expression should be separated by\
                a space with patterns containing spaces wrapped in quotes"

	$p insert end preferences #auto -text "Ignore Files" \
            -variable info(IgnoreFiles) \
            -helptext "A list of regular expressions to match when searching\
                for new files.  Each expression should be separated by a space\
                with patterns containing spaces wrapped in quotes"

	$p insert end preferences #auto \
            -text "Include Install Debugging Options" \
	    -variable info(IncludeDebugging) -editable 0 \
            -values [list Yes No] -helptext "Turn install debugging options\
                on or off"

	$p insert end preferences #auto \
            -text "Preserve UNIX File Permissions" \
	    -variable info(PreserveFilePermissions) -editable 0 \
            -values [list Yes No] -helptext "Whether or not InstallJammer\
                should preserve the current UNIX file permissions when adding\
                files to an installer"

	$p insert end preferences #auto \
            -text "Preserve Windows File Attributes" \
	    -variable info(PreserveFileAttributes) -editable 0 \
            -values [list Yes No] -helptext "Whether or not InstallJammer\
                should preserve the current Windows file attributes when\
                adding files to an installer"

	$p insert end preferences #auto \
            -text "Refresh File List Before Building" \
	    -variable info(AutoRefreshFiles) -editable 0 \
            -values [list Yes No] -helptext "Whether or not InstallJammer\
                should look for new and deleted files in directories added\
                to file groups automatically before building"

	$p insert end preferences #auto -text "Save Only Toplevel Directories" \
	    -variable info(SaveOnlyToplevelDirs) -editable 0 \
            -values [list Yes No] -helptext "Do not recursively save all of the\
                files and subdirectories beneath a directory in a file\
                group.  Only save the directories and files that are direct\
                children of the file group."

	$p insert end preferences #auto -text "Skip Unused File Groups" \
	    -variable info(SkipUnusedFileGroups) -editable 0 \
            -values [list Yes No] -helptext "Do not pack file groups that are\
                not included in at least one component."

    return

    ## Build the restore buttons.
    set f [frame $f1.themes]
    pack $f -side bottom -anchor se -pady [list 10 0]

    BUTTON $f.restorewin -text "Restore Windows" -width 18 \
        -command RestoreThemeWindows
    pack $f.restorewin -side left

    BUTTON $f.restore -text "Restore Theme" -width 18 \
        -command [list RestoreTheme -prompt]
    pack $f.restore -side left -padx 5

    BUTTON $f.save -text "Save New Theme" -width 18 \
        -command SaveTheme
    pack $f.save -side left
}

proc Frame.platformInformation {} {
    global conf
    global info
    global widg

    set f [$widg(Product) getframe platformInformation]
    set p $f.sw.p

    ::InstallJammer::SetHelp PlatformInformation

    if {[winfo exists $p]} {
        foreach platform [AllPlatforms] {
            foreach node [$p nodes [PlatformName $platform]] {
                set var [$p itemcget $node -data]
                $p itemconfigure $node -value [$platform get $var]
            }
        }

        return
    }

    ScrolledWindow $f.sw -scrollbar vertical -auto vertical
    PROPERTIES $p
    $f.sw setwidget $p
    pack $f.sw -expand 1 -fill both

    set platforms [ActivePlatforms]
    foreach platform [AllPlatforms] {
	set open 0
	if {[lsearch -exact $platforms $platform] > -1} { set open 1 }

        set cmd [list ::InstallJammer::FinishEditPlatformPropertyNode %W %p %n]

	set node [PlatformName $platform]
	$p insert end root $node -text [PlatformText $platform] \
            -open $open -data $platform

        $p insert end $node #auto -text "Active" \
            -values [list Yes No] -editable 0 -data Active \
            -editfinishcommand $cmd -value [$platform get Active] \
            -helptext "Whether this platform is active for your project"

        $p insert end $node #auto -text "Build Separate Archives" \
            -values [list Yes No] -editable 0 -editfinishcommand $cmd \
            -data BuildSeparateArchives \
            -value [$platform get BuildSeparateArchives] \
            -helptext "Whether this platform should be built as a single\
                executable installer or that the files should be packaged\
                separately in archives to be distributed with the installer"

	$p insert end $node #auto \
	    -text "Default Destination Directory" \
            -valuescommand [list InstallDirList $platform] \
            -data InstallDir -editfinishcommand $cmd \
            -value [$platform get InstallDir] -helptext "The default\
                installation location for this application"

        if {$platform ne "Windows"} {
            $p insert end $node #auto \
                -text "Default Directory Permission Mask" \
                -data DefaultDirectoryPermission -editfinishcommand $cmd \
                -value [$platform get DefaultDirectoryPermission] \
                -helptext "The default permission mask for\
                    directories on a UNIX platform (in octal format)"

            $p insert end $node #auto \
                -text "Default File Permission Mask" \
                -data DefaultFilePermission -editfinishcommand $cmd \
                -value [$platform get DefaultFilePermission] \
                -helptext "The default permission mask for\
                    files on a UNIX platform (in octal format)"
        }

	$p insert end $node #auto -text "Default Install Mode" \
            -values [list Default Silent Standard] \
            -editable 0 -data InstallMode -editfinishcommand $cmd \
            -value [$platform get InstallMode] -helptext "The default install\
                mode when installing this application"

	$p insert end $node #auto -text "Default Program Folder" \
            -data ProgramFolderName -editfinishcommand $cmd \
            -value [$platform get ProgramFolderName] -helptext "The default\
                program folder on Windows to store shortcuts for this\
                application"

	$p insert end $node #auto -text "Default Setup Type" \
            -valuescommand [list ::InstallJammer::GetSetupTypeNames $platform] \
            -editable 0 -data InstallType -editfinishcommand $cmd \
            -value [$platform get InstallType] -helptext "The default setup\
                type when installing this application"

        if {$platform ne "Windows"} {
            $p insert end $node #auto -text "Fall Back to Console Mode" \
                -values [list Yes No] -editable 0 \
                -data FallBackToConsole -editfinishcommand $cmd \
                -value [$platform get FallBackToConsole] \
                -helptext "If a GUI mode is unavailable the installer will\
                    automatically fall back to a console mode to install"
        }

        if {$platform eq "Windows"} {
            $p insert end $node #auto -text "Include Windows API Extension" \
                -values [list Yes No] -editable 0 \
                -data IncludeTWAPI -editfinishcommand $cmd \
                -value [$platform get IncludeTWAPI] \
                -helptext "Whether or not to include the Tcl Windows API\
                    extension in your install (Windows NT 4.0 SP4 or later)"

            $p insert end $node #auto -text "Install Executable Description" \
                -data FileDescription -editfinishcommand $cmd \
                -value [$platform get FileDescription] \
                -helptext "The file description when someone examines the\
                    properties of the executable on the Windows platform"
        }

	$p insert end $node #auto -text "Install Executable Name" \
            -data Executable -editfinishcommand $cmd \
            -value [$platform get Executable] -helptext "The name of your\
                installer when it is built"

        if {$platform eq "Windows"} {
            $p insert end $node #auto \
                -text "Install Program Folder for All Users" \
                -values [list Yes No] -editable 0 \
                -data ProgramFolderAllUsers -editfinishcommand $cmd \
                -value [$platform get ProgramFolderAllUsers] -helptext \
                    "Whether or not to create the Program Folder for all or \
                     the current user by default"
        }

	$p insert end $node #auto \
	    -text "Program Executable" \
            -valuescommand [list InstallDirList $platform] \
            -data ProgramExecutable -editfinishcommand $cmd \
            -value [$platform get ProgramExecutable] -helptext "The path to\
                the main executable for your application on the target system"

	$p insert end $node #auto \
	    -text "Program License" \
            -valuescommand [list InstallDirList $platform] \
            -data ProgramLicense -editfinishcommand $cmd \
            -value [$platform get ProgramLicense] -helptext "The path to your\
                LICENSE file on the target system"

	$p insert end $node #auto \
	    -text "Program Readme" \
            -valuescommand [list InstallDirList $platform] \
            -data ProgramReadme -editfinishcommand $cmd \
            -value [$platform get ProgramReadme] -helptext "The path to your\
                README file on the target system"

        if {$platform eq "Windows"} {
            $p insert end $node #auto -text "Require Administrator" \
                -values "Yes No" -editable 0 -data RequireAdministrator \
                -editfinishcommand $cmd \
                -value [$platform get RequireAdministrator] \
                -helptext "Whether this install requires administrator\
                    privileges to install"
        } else {
            $p insert end $node #auto -text "Prompt for Root Password" \
                -values [list Yes No] -editable 0 -data PromptForRoot \
                -editfinishcommand $cmd -value [$platform get PromptForRoot] \
                -helptext "If root access is required, InstallJammer will\
                    prompt the user to login as root on startup if they are\
                    not already root"

            $p insert end $node #auto -text "Require Root User" \
                -values [list Yes No] -editable 0 -data RequireRoot \
                -editfinishcommand $cmd -value [$platform get RequireRoot] \
                -helptext "Whether this install requires the root user to\
                    install"

            $p insert end $node #auto \
                -text "Root Destination Directory" \
                -valuescommand [list InstallDirList $platform] \
                -data RootInstallDir -editfinishcommand $cmd \
                -value [$platform get RootInstallDir] -helptext "The\
                    default installation location for this application\
                    when being installed as root.  If this value is empty,\
                    the Default Destination Directory will be used"
        }

        if {$platform eq "Windows"} {
            $p insert end $node #auto -text "Use Uncompressed Binaries" \
                -values [list Yes No] -editable 0 \
                -data UseUncompressedBinaries -editfinishcommand $cmd \
                -value [$platform get UseUncompressedBinaries] \
                -helptext "If this property is true, the installer will be\
                    built with uncompressed binaries that make the install\
                    larger but sometimes avoid being erroneously detected by\
                    some virus scanning software"

            $p insert end $node #auto -text "Windows File Icon" \
                -browsebutton 1 -browsecommand [list GetIconFile %v] \
                -browseargs {-style Toolbutton} \
                -valuescommand GetIconList \
                -data WindowsIcon -editfinishcommand $cmd \
                -value [$platform get WindowsIcon] -helptext "The Windows\
                    icon to use for building the Windows installer"
        }
    }
}

proc Frame.packageAndArchiveInformation {} {
    global conf
    global info
    global widg

    set f [$widg(Product) getframe packageAndArchiveInformation]
    set p $f.sw.p

    ::InstallJammer::SetHelp PackageAndArchiveInformation

    if {[winfo exists $p]} {
        foreach archive $conf(Archives) {
            foreach node [$p nodes $archive] {
                set var [$p itemcget $node -data]
                $p itemconfigure $node -value [$archive get $var]
            }
        }

        return
    }

    ScrolledWindow $f.sw -scrollbar vertical -auto vertical
    PROPERTIES $p
    $f.sw setwidget $p
    pack $f.sw -expand 1 -fill both

    set cmd [list ::InstallJammer::FinishEditPlatformPropertyNode %W %p %n]

    $p insert end root package -text "Package Information" \
        -helptext "This section defines the information used by the\
                Register Package action if you want to register your\
                application with the local package database.\nIt is\
                highly recommended that you fill in all of the available\
                properties if you plan on registering your package."

        $p insert end package #auto -text "Package Description" \
            -variable info(PackageDescription) -browsebutton 1 \
            -browseargs [list -style Toolbutton] \
            -browsecommand [list ::editor::new \
                -title "Edit Package Description" \
                -variable ::info(PackageDescription)]

        $p insert end package #auto -text "Package License" \
            -variable info(PackageLicense)

        $p insert end package #auto -text "Package Maintainer" \
            -variable info(PackageMaintainer)

        $p insert end package #auto -text "Package Name" \
            -variable info(PackageName)

        $p insert end package #auto -text "Package Packager" \
            -variable info(PackagePackager)

        $p insert end package #auto -text "Package Release" \
            -variable info(PackageRelease)

        $p insert end package #auto -text "Package Summary" \
            -variable info(PackageSummary)

        $p insert end package #auto -text "Package Version" \
            -variable info(PackageVersion)

    set archive TarArchive
    if {[::InstallJammer::ArchiveExists $archive]} {
        $p insert end root $archive -text "Tar Archive Information" \
            -data $archive -editfinishcommand $cmd -open [$archive get Active] \
            -helptext "This section defines the attributes for creating a\
                TAR archive file of your install project."

            $p insert end $archive #auto -text "Active" \
                -values [list Yes No] -editable 0 \
                -data Active -value [$archive get Active] \
                -helptext "Whether this archive is active for your project"

            set levels [list]
            for {set i 0} {$i <= 9} {incr i} { lappend levels $i }
            $p insert end $archive #auto -text "Compression Level" \
                -data CompressionLevel -editable 0 -values $levels \
                -value [$archive get CompressionLevel] \
                -helptext "The level of gzip compression for the tar file.\
                    (0 = no compression, 9 highest compression)"

            $p insert end $archive #auto \
                -text "Default Directory Permission Mask" \
                -data DefaultDirectoryPermission \
                -value [$archive get DefaultDirectoryPermission] \
                -helptext "The default permission mask for directories on\
                    a UNIX platform (in octal format)"

            $p insert end $archive #auto -text "Default File Permission Mask" \
                -data DefaultFilePermission \
                -value [$archive get DefaultFilePermission] \
                -helptext "The default permission mask for files on a\
                    UNIX platform (in octal format)"

            $p insert end $archive #auto -text "Output File Name" \
                -data OutputFileName -value [$archive get OutputFileName] \
                -helptext "The name of the tar file to output to"

            $p insert end $archive #auto -text "Virtual Text Map" \
                -data VirtualTextMap -value [$archive get VirtualTextMap] \
                -helptext "A map of virtual text for filenames being stored in\
                    the tar file"
    }

    set archive ZipArchive
    if {[::InstallJammer::ArchiveExists $archive]} {
        $p insert end root ZipArchive -text "Zip Archive Information" \
            -data ZipArchive -editfinishcommand $cmd -open [$archive get Active]

            $p insert end $archive #auto -text "Active" \
                -values [list Yes No] -editable 0 \
                -data Active -value [$archive get Active] \
                -helptext "Whether this archive is active for your project"

            set levels [list]
            for {set i 1} {$i <= 9} {incr i} { lappend levels $i }
            $p insert end $archive #auto -text "Compression Level" \
                -data CompressionLevel -editable 0 -values $levels \
                -value [$archive get CompressionLevel] \
                -helptext "The level of compression for the zip file.\
                    (1 = lowest compression, 9 highest compression)"

            $p insert end $archive #auto -text "Output File Name" \
                -data OutputFileName -value [$archive get OutputFileName] \
                -helptext "The name of the zip file to output to"

            $p insert end $archive #auto -text "Virtual Text Map" \
                -data VirtualTextMap -value [$archive get VirtualTextMap] \
                -helptext "A map of virtual text for filenames being stored in\
                    the zip file"
    }
}

proc Frame.groupsAndFiles {} {
    global conf
    global widg
    global preferences

    set f1 [$widg(Product) getframe groupsAndFiles]
    set widg(FileGroupsMain) $f1

    ::InstallJammer::SetHelp GroupsAndFiles

    if {[winfo exists $f1.buttons]} {
        set conf(TreeFocus) $widg(FileGroupTree)

        variable ::InstallJammer::ActiveComponents
        if {[info exists ActiveComponents(filegroup)]} {
            ::InstallJammer::SetActiveComponent $ActiveComponents(filegroup)
        }

        return
    }

    set f [frame $f1.buttons]
    pack $f -anchor w

    WinButton $f.b1 -image [GetImage foldernew16] \
    	-command "::FileGroupTree::New"
    set widg(DeleteButton) [WinButton $f.b4 \
	-image [GetImage buttoncancel16] -command "::FileGroupTree::delete"]
    set widg(AddFilesButton) [WinButton $f.b2 \
    	-image [GetImage filedocument16] -command "AddFiles" -state disabled]
    set widg(AddDirButton) [WinButton $f.b3 \
    	-image [GetImage folder16] -command "AddFiles -isdir 1" -state disabled]
    WinButton $f.b5 -image [GetImage filefind16] \
        -command ::FileGroupTree::Explore
    WinButton $f.refresh -image [GetImage actreload16] \
    	-command "::InstallJammer::RefreshFileGroups"
    WinButton $f.filter -image [GetImage viewsidetree16] \
    	-command "Window show .filterFileGroups"

    pack $f.b1 $f.b4 $f.b2 $f.b3 $f.b5 $f.refresh $f.filter -side left

    DynamicHelp::register $f.b1 balloon "Add New File Group"
    DynamicHelp::register $widg(AddFilesButton) balloon \
        "Add Files to File Group"
    DynamicHelp::register $widg(AddDirButton) balloon \
        "Add Directory to File Group"
    DynamicHelp::register $f.b4 balloon "Delete"
    DynamicHelp::register $f.b5 balloon "File Explorer"
    DynamicHelp::add $f.refresh -text "Refresh File Groups"
    DynamicHelp::register $f.filter balloon \
    	"Filter file groups based on patterns"

    set widg(FileGroupPref) $f1.p

    set opts [list]
    if {[info exists preferences(Geometry,FileGroupPref)]} {
        set opts $preferences(Geometry,FileGroupPref)
    }

    eval [list PREFERENCES $widg(FileGroupPref) -treepadx 20 -showlines 1 \
        -deltay 17 -pagewidth 300 -treestretch always -pagestretch never] $opts
    pack $f1.p -expand 1 -fill both

    set widg(FileGroupTree) [$f1.p gettree]

    set tree $widg(FileGroupTree)
    ::FileGroupTree::setup $widg(FileGroupTree)

    set prop [PROPERTIES $f1.properties]
    set widg(FileGroupProperties) $prop
    $prop insert end root filegroup   -text "File Group Properties"
    $prop insert end root dir         -text "Directory Properties"
    $prop insert end root file        -text "File Properties"
    $prop insert end root fileunix    -text "File Permissions"
    $prop insert end root filewindows -text "File Permissions"

    dnd bindtarget $tree.c Files <Drop> "::Tree::DropFiles $tree %D"
    dnd bindtarget $tree.c Files <Drag> "::Tree::DragFiles $tree %x %y"

    ## Create the popup menus.
    set ::FileGroupTree::FilePopup      $f1.filePopup
    set ::FileGroupTree::MultiPopup     $f1.multiPopup
    set ::FileGroupTree::FileGroupPopup $f1.fileGroupPopup
    set ::FileGroupTree::DirectoryPopup $f1.directoryPopup

    set m [POPUP $::FileGroupTree::FilePopup]

    #$m add command -label "Select All" \
    	#-command {::FileTree::SelectAll $widg(FileGroupTree)}
    #$m add separator
    $m add command -label "Check" -underline 0 \
        -compound left -image [GetImage checkfiledocument16] \
    	-command {::FileGroupTree::Check}
    $m add command -label "Uncheck" -underline 0 \
        -compound left -image [GetImage filedocument16] \
    	-command {::FileGroupTree::Uncheck}
    $m add separator
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
    	-command {::FileGroupTree::delete}
    $m add separator
    $m add command -label "Add to Desktop" -underline 0 \
    	-command {::FileGroupTree::AddToDesktop}
    $m add command -label "Add to Program Folder" -underline 0 \
    	-command {::FileGroupTree::AddToProgramFolder}
    #$m add command -label "Add Windows Shortcut" -underline 0 \
    	#-command {::FileGroupTree::AddWindowsShortcut}
    #$m add command -label "Add as Wrapped Script" -underline 0 \
    	#-command {::FileGroupTree::AddWrappedScript}
    #$m add command -label "Add as Wrapped Application" -underline 0 \
    	#-command {::FileGroupTree::AddWrappedApplication}
    $m add separator
    $m add command -label "Explore" -underline 1 \
        -compound left -image [GetImage filefind16] \
        -command ::FileGroupTree::Explore

    set m [POPUP $::FileGroupTree::MultiPopup]

    #$m add command -label "Select All" \
    	#-command {::FileTree::SelectAll $widg(FileGroupTree)}
    #$m add separator
    $m add command -label "Check" -underline 0 \
        -compound left -image [GetImage checkfiledocument16] \
    	-command {::FileGroupTree::Check}
    $m add command -label "Uncheck" -underline 0 \
        -compound left -image [GetImage filedocument16] \
    	-command {::FileGroupTree::Uncheck}
    $m add separator
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
    	-command {::FileGroupTree::delete}

    set m [POPUP $::FileGroupTree::FileGroupPopup]

    $m add command -label "Open" \
        -compound left -image [GetImage folderopen16] \
        -command {
            ::InstallJammer::Tree::OpenSelectedNode $widg(FileGroupTree)
        }
    $m add command -label "Open Recursive" \
        -compound left -image [GetImage folderopen16] \
        -command {
            ::InstallJammer::Tree::OpenSelectedNode $widg(FileGroupTree) 1
        }

    $m add command -label "Close" \
        -compound left -image [GetImage folder16] \
        -command {
            ::InstallJammer::Tree::CloseSelectedNode $widg(FileGroupTree)
        }

    $m add separator

    #$m add command -label "Select All" \
    	#-command {::FileTree::SelectAll $widg(FileGroupTree)}
    #$m add command -label "Select All in this File Group" \
    	#-command {::FileTree::SelectAllBeneath $widg(FileGroupTree)}
    #$m add separator
    $m add command -label "Add Files" -underline 0 \
        -compound left -image [GetImage filedocument16] \
        -command "AddFiles"
    $m add command -label "Add Directory" -underline 0 \
        -compound left -image [GetImage folder16] \
        -command "AddFiles -isdir 1"
    $m add separator
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
    	-command {::FileGroupTree::delete}

    set m [POPUP $::FileGroupTree::DirectoryPopup]

    $m add command -label "Open" \
        -compound left -image [GetImage folderopen16] \
        -command {
            ::InstallJammer::Tree::OpenSelectedNode $widg(FileGroupTree)
        }
    $m add command -label "Open Recursive" \
        -compound left -image [GetImage folderopen16] \
        -command {
            ::InstallJammer::Tree::OpenSelectedNode $widg(FileGroupTree) 1
        }

    $m add command -label "Close" \
        -compound left -image [GetImage folder16] \
        -command {
            ::InstallJammer::Tree::CloseSelectedNode $widg(FileGroupTree)
        }

    $m add separator
    #$m add command -label "Select All" \
    	#-command {::FileTree::SelectAll $widg(FileGroupTree)}
    #$m add separator
    $m add command -label "Check" -underline 0 \
        -compound left -image [GetImage checkfolder16] \
    	-command {::FileGroupTree::Check}
    $m add command -label "Uncheck" -underline 0 \
        -compound left -image [GetImage folder16] \
    	-command {::FileGroupTree::Uncheck}
    $m add separator
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
    	-command {::FileGroupTree::delete}
    $m add separator
    $m add command -label "Explore" -underline 1 \
        -compound left -image [GetImage filefind16] \
        -command ::FileGroupTree::Explore

    ## Create the frame to hold file group details.
    set widg(FileGroupDetails) [ScrolledWindow $f1.details -scrollbar vertical]

    set prop [PROPERTIES $f1.details.prop -width 250]
    set widg(FileGroupDetailsProp) $prop

    $widg(FileGroupDetails) setwidget $widg(FileGroupDetailsProp)

    $prop insert end root standard -text "Standard Properties" -open 1

    ::FileGroupObject addproperties $prop foo

    ## Add a node for file / directory properties.
    $prop insert end root filestandard -text "Standard Properties" -open 1
    ::FileObject addproperties $prop file -standardnode filestandard \
        -array ::FileGroupTree::details

    $prop insert end root dir  -text "Directory Details"
        $prop insert end dir #auto -text "Name" \
            -variable ::FileGroupTree::details(name) -state disabled
        $prop insert end dir #auto -text "Location" \
            -variable ::FileGroupTree::details(location) -state disabled
        $prop insert end dir #auto -text "File Group" \
            -variable ::FileGroupTree::details(fileGroup) -state disabled
        $prop insert end dir #auto -text "File Update Method" \
            -variable ::FileGroupTree::details(fileMethod) -state disabled
        $prop insert end dir #auto -text "Install Location" \
            -variable ::FileGroupTree::details(installLocation) -state disabled
        $prop insert end dir #auto -text "Compression Method" \
            -variable ::FileGroupTree::details(compressionMethod) \
            -state disabled
        $prop insert end dir #auto -text "Version" \
            -variable ::FileGroupTree::details(fileVersion) -state disabled
        $prop insert end dir #auto -text "Created" \
            -variable ::FileGroupTree::details(created) -state disabled
        $prop insert end dir #auto -text "Modified" \
            -variable ::FileGroupTree::details(modified) -state disabled
        $prop insert end dir #auto -text "Accessed" \
            -variable ::FileGroupTree::details(accessed) -state disabled

    $prop insert end root file -text "File Details"
        $prop insert end file #auto -text "Name" \
            -variable ::FileGroupTree::details(name) -state disabled
        $prop insert end file #auto -text "Location" \
            -variable ::FileGroupTree::details(location) -state disabled
        $prop insert end file #auto -text "File Group" \
            -variable ::FileGroupTree::details(fileGroup) -state disabled
        $prop insert end file #auto -text "File Size" \
            -variable ::FileGroupTree::details(fileSize) -state disabled
        $prop insert end file #auto -text "File Update Method" \
            -variable ::FileGroupTree::details(fileMethod) -state disabled
        $prop insert end file #auto -text "Install Location" \
            -variable ::FileGroupTree::details(installLocation) -state disabled
        $prop insert end file #auto -text "Compression Method" \
            -variable ::FileGroupTree::details(compressionMethod) \
            -state disabled
        $prop insert end file #auto -text "Version" \
            -variable ::FileGroupTree::details(fileVersion) -state disabled
        $prop insert end file #auto -text "Created" \
            -variable ::FileGroupTree::details(created) -state disabled
        $prop insert end file #auto -text "Modified" \
            -variable ::FileGroupTree::details(modified) -state disabled
        $prop insert end file #auto -text "Accessed" \
            -variable ::FileGroupTree::details(accessed) -state disabled

    ## Create a property node for multiple file options
    $prop insert end root multiplefiles -text "Standard Properties" -open 1

    AddProperty $prop end multiplefiles multiplefiles Active \
        ::FileGroupTree::details(Active) -type boolean -pretty "Active"
    AddProperty $prop end multiplefiles multiplefiles Destination \
        ::FileGroupTree::details(Destination) -type installedfile \
        -pretty "Destination Directory"
    AddProperty $prop end multiplefiles multiplefiles FileUpdateMethod \
        ::FileGroupTree::details(FileUpdateMethod) -type filemethod \
        -pretty "File Update Method"
    AddProperty $prop end multiplefiles multiplefiles CompressionMethod \
        ::FileGroupTree::details(CompressionMethod) -type choice \
        -pretty "Compression Method" -choices $conf(CompressionMethods)
    AddProperty $prop end multiplefiles multiplefiles Version \
        ::FileGroupTree::details(Version) -type version \
        -pretty "Version"

    ## Create the permissions property node.
    set permf [frame $f1.permissions]
    set widg(FileGroupPermissions) $permf

    labelframe $permf.unix -text "UNIX File Permissions"
    UNIXPermissionsFrame $permf.unix UNIXDetailsPermissions \
        ::FileGroupTree::permissions
    pack $permf.unix -side left -anchor nw -padx 5

    labelframe $permf.windows -text "Windows File Attributes"
    WindowsPermissionsFrame $permf.windows WindowsDetailsPermissions \
        ::FileGroupTree::permissions
    pack $permf.windows -side left -anchor nw -fill y

    ::InstallJammer::AddPlatformPropertyNode $prop ::FileGroupTree::details 1

    $prop insert end root permissions -text "Permissions" -window $permf
}

proc Frame.components {} {
    global conf
    global widg
    global preferences

    set f2 [$widg(Product) getframe components]

    ::InstallJammer::SetHelp Components

    if {[winfo exists $f2.top]} {
        set conf(TreeFocus) $widg(ComponentTree)

        variable ::InstallJammer::ActiveComponents
        if {[info exists ActiveComponents(component)]} {
            ::InstallJammer::SetActiveComponent $ActiveComponents(component)
        }

        return
    }
    
    frame $f2.top
    pack $f2.top -side top -anchor w

    WinButton $f2.top.b1 -image [GetImage foldernew16] \
    	-command ::ComponentTree::New
    pack $f2.top.b1 -side left

    set widg(ComponentDeleteButton) [WinButton $f2.top.b3 \
    	-image [GetImage buttoncancel16] -command "::ComponentTree::delete"]
    pack $f2.top.b3 -side left

    DynamicHelp::register $f2.top.b1 balloon "Add New Component"
    DynamicHelp::register $f2.top.b3 balloon "Delete Component"

    set opts [list]
    if {[info exists preferences(Geometry,ComponentPref)]} {
        set opts $preferences(Geometry,ComponentPref)
    }

    eval [list PREFERENCES $f2.p -treepadx 20 -deltay 19 -showlines 1 \
        -pagewidth 300 -treestretch never -pagestretch always \
        -dropovermode p -dragenabled 1 -dropenabled 1 \
        -dropcmd ::InstallJammer::Tree::DropNode \
        -draginitcmd ::InstallJammer::Tree::DragInit] $opts
    pack $f2.p -expand 1 -fill both

    set widg(ComponentPref) $f2.p
    set widg(ComponentTree) [$f2.p gettree]

    ::ComponentTree::setup $widg(ComponentTree)

    ## Create the Component popup menu.
    set m [POPUP $f2.popup -tearoff 0]
    set ::ComponentTree::popup $m
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
    	-command {::ComponentTree::delete}

    ## Create the frame to hold component details.
    set widg(ComponentDetails) $f2.details

    set f [frame $widg(ComponentDetails)]

    ScrolledWindow $f.sw
    pack $f.sw -expand 1 -fill both -padx [list 0 10] -pady [list 0 5]

    set widg(ComponentFileGroupTree) $f.sw.tree
    OPTIONTREE $widg(ComponentFileGroupTree)
    $f.sw setwidget $widg(ComponentFileGroupTree)

    ScrolledWindow $f.details -scrollbar vertical
    pack $f.details -fill x

    set prop [PROPERTIES $f.details.prop -width 250]
    set widg(ComponentDetailsProp) $prop

    $f.details setwidget $widg(ComponentDetailsProp)

    $prop insert end root standard -text "Standard Properties" -open 1
    ::ComponentObject addproperties $prop foo

    $prop insert end root text -text "Text Properties" -open 0
    ::ComponentObject addtextfields $prop text foo

    ::InstallJammer::AddPlatformPropertyNode $prop ::ComponentTree::details
}

proc Frame.setupTypes {} {
    global conf
    global widg
    global preferences

    set f3 [$widg(Product) getframe setupTypes]

    ::InstallJammer::SetHelp SetupTypes

    if {[winfo exists $f3.top]} {
        set conf(TreeFocus) $widg(SetupTypeTree)

        variable ::InstallJammer::ActiveComponents
        if {[info exists ActiveComponents(setuptype)]} {
            ::InstallJammer::SetActiveComponent $ActiveComponents(setuptype)
        }

        return
    }

    frame $f3.top
    pack $f3.top -side top -anchor w

    WinButton $f3.top.b1 -image [GetImage foldernew16] \
    	-command ::SetupTypeTree::New
    pack $f3.top.b1 -side left

    set widg(SetupTypeDeleteButton) [WinButton $f3.top.b3 \
    	-image [GetImage buttoncancel16] -command "::SetupTypeTree::delete"]
    pack $f3.top.b3 -side left

    DynamicHelp::add $f3.top.b1 -text "Add New Setup Type"
    DynamicHelp::add $f3.top.b3 -text "Delete Setup Type"

    set opts [list]
    if {[info exists preferences(Geometry,SetupTypePref)]} {
        set opts $preferences(Geometry,SetupTypePref)
    }

    eval [list PREFERENCES $f3.p -treepadx 20 -showlines 0 -deltax 0 \
        -deltay 18 -pagewidth 300 -treestretch never -pagestretch always \
        -dropovermode p -dragenabled 1 -dropenabled 1 \
        -dropcmd ::InstallJammer::Tree::DropNode \
        -draginitcmd ::InstallJammer::Tree::DragInit] $opts
    pack $f3.p -expand 1 -fill both

    set widg(SetupTypePref) $f3.p
    set widg(SetupTypeTree) [$f3.p gettree]

    ::SetupTypeTree::setup $widg(SetupTypeTree)

    ## Create the Setup Type popup menu.
    set m [POPUP $f3.popup -tearoff 0]
    set ::SetupTypeTree::popup $m
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
        -command {::SetupTypeTree::delete}

    set widg(SetupTypeDetails) $f3.details

    set f [frame $widg(SetupTypeDetails)]

    ScrolledWindow $f.sw
    pack $f.sw -expand 1 -fill both -padx [list 0 10] -pady [list 0 5]

    set widg(SetupTypeComponentTree) $f.sw.tree
    OPTIONTREE $widg(SetupTypeComponentTree)
    $f.sw setwidget $widg(SetupTypeComponentTree)

    ## Create the frame to hold setup type details.
    ScrolledWindow $f.details -scrollbar vertical
    pack $f.details -fill x

    set prop [PROPERTIES $f.details.prop -expand 1 -width 250]
    set widg(SetupTypeDetailsProp) $prop

    $f.details setwidget $widg(SetupTypeDetailsProp)

    $prop insert end root standard -text "Standard Properties" -open 1

    ::SetupTypeObject addproperties $prop foo

    $prop insert end root text -text "Text Properties" -open 0
    ::SetupTypeObject addtextfields $prop text foo

    ::InstallJammer::AddPlatformPropertyNode $prop ::SetupTypeTree::details
}

proc Frame.install {} {
    global conf
    global widg
    global preferences

    set widg(Install) [$widg(Product) getframe install].p

    ::InstallJammer::SetHelp PanesAndActions

    if {[winfo exists $widg(Install)]} {
        set conf(TreeFocus) $widg(InstallTree)

        variable ::InstallJammer::ActiveComponents
        if {[info exists ActiveComponents(Install)]} {
            ::InstallJammer::SetActiveComponent $ActiveComponents(Install)
        }

        return
    }

    set opts [list]
    if {[info exists preferences(Geometry,Install)]} {
        set opts $preferences(Geometry,Install)
    }

    set main $widg(Install)

    eval [list PREFERENCES $widg(Install) \
        -showlines 0 -treewidth 215 -treepadx 20 -deltay 18 \
        -dropovermode p -dragenabled 1 -dropenabled 1 \
        -dropcmd ::InstallJammer::Tree::DropNode \
        -draginitcmd ::InstallJammer::Tree::DragInit] $opts
    pack $main -expand 1 -fill both -side bottom

    set tree [$widg(Install) gettree]
    set widg(InstallTree) $tree

    set p [winfo parent $widg(Install)]
    set f [frame $p.f1]
    set widg(InstallButtons) $f
    pack $f -anchor nw

    WinMenuButton $f.addPane -image [GetImage displayscreen16] \
        -menu $f.addPane.panes
    pack $f.addPane -side left -padx 2
    DynamicHelp::add $f.addPane -text "Insert Install Pane"

    ## Create the menu for the install panes, but they won't
    ## get added until a project is loaded.
    set m [MENU $f.addPane.panes]
    set widg(InstallPanesMenu) $m

    WinMenuButton $f.addAction -image [GetImage insertaction16] \
        -menu $f.addAction.actions
    pack $f.addAction -side left -padx 2
    DynamicHelp::add $f.addAction -text "Insert Action"

    set m [MENU $f.addAction.actions]
    set widg(InstallActionsMenu) $m

    $m insert end cascade -label "All Actions" -menu $m.all \
        -compound left -image [GetImage appwindow_list16]
    MENU $m.all

    foreach group [lsort [array names ::InstallJammer::actiongroups]] {
        set submenu [MENU $m.[WidgetName $group]]
        $m insert end cascade -label "$group   " -menu $submenu \
            -compound left -image [GetImage appwindow_list16]

        foreach id $::InstallJammer::actiongroups($group) {
            set allactions([$id title]) $id
            lappend actions($submenu) [$id title]
        }
    }

    foreach submenu [array names actions] {
        foreach title [lsort $actions($submenu)] {
            set id $allactions($title)
            $submenu add command -label $title \
                -compound left -image [GetImage insertaction16] \
                -command [list ::InstallJammer::AddAction Install [$id action]]
        }
    }

    foreach title [lsort [array names allactions]] {
        set id $allactions($title)
        $m.all add command -label $title \
            -compound left -image [GetImage insertaction16] \
            -command [list ::InstallJammer::AddAction Install [$id action]]
    }

    WinButton $f.addActionGroup -image [GetImage appwindow_list16] \
        -command [list ::InstallJammer::AddActionGroup Install]
    pack $f.addActionGroup -side left -padx 2
    DynamicHelp::add $f.addActionGroup -text "New Action Group"

    WinButton $f.delete -image [GetImage buttoncancel16] \
        -command [list ::InstallJammer::Tree::Delete $widg(Install)]
    pack $f.delete -side left -padx 2
    DynamicHelp::add $f.delete -text "Delete"

    set args [list -deltax 5 -padx 10 -haspage 0]
    eval $main insert end root CommonInstall -data installtype \
        [list -text "Common Components" -font TkCaptionFont] $args
    eval $main insert end root StandardInstall -data installtype \
        [list -text "Standard Install" -font TkCaptionFont] $args
    eval $main insert end root DefaultInstall -data installtype \
        [list -text "Default Install" -font TkCaptionFont] $args
    eval $main insert end root ConsoleInstall -data installtype \
        [list -text "Console Install" -font TkCaptionFont] $args
    eval $main insert end root SilentInstall -data installtype \
        [list -text "Silent Install" -font TkCaptionFont] $args
    eval $main insert end root ActionGroupsInstall -data installtype \
        [list -text "Action Groups" -font TkCaptionFont] $args

    ::InstallJammer::Tree::Setup Install $tree
}

proc Frame.uninstall {} {
    global conf
    global widg
    global preferences

    set widg(Uninstall) [$widg(Product) getframe uninstall].p

    ::InstallJammer::SetHelp PanesAndActions

    if {[winfo exists $widg(Uninstall)]} {
        set conf(TreeFocus) $widg(UninstallTree)

        variable ::InstallJammer::ActiveComponents
        if {[info exists ActiveComponents(Uninstall)]} {
            ::InstallJammer::SetActiveComponent $ActiveComponents(Uninstall)
        }

        return
    }

    set opts [list]
    if {[info exists preferences(Geometry,Uninstall)]} {
        set opts $preferences(Geometry,Uninstall)
    }

    set main $widg(Uninstall)
    eval [list PREFERENCES $widg(Uninstall) \
        -showlines 0 -treewidth 215 -treepadx 20 -deltay 18 \
        -dropovermode p -dragenabled 1 -dropenabled 1 \
        -dropcmd ::InstallJammer::Tree::DropNode \
        -draginitcmd ::InstallJammer::Tree::DragInit] $opts
    pack $main -expand 1 -fill both -side bottom

    set tree [$widg(Uninstall) gettree]
    set widg(UninstallTree) $tree

    set p [winfo parent $widg(Uninstall)]
    set f [frame $p.f1]
    set widg(UninstallButtons) $f
    pack $f -anchor nw

    WinMenuButton $f.addPane -image [GetImage displayscreen16] \
        -menu $f.addPane.panes
    pack $f.addPane -side left -padx 2
    DynamicHelp::add $f.addPane -text "Insert Uninstall Pane"

    set m [MENU $f.addPane.panes]
    set widg(UninstallPanesMenu) $m

    WinMenuButton $f.addAction -image [GetImage insertaction16] \
        -menu $f.addAction.actions
    pack $f.addAction -side left -padx 2
    DynamicHelp::add $f.addAction -text "Insert Action"

    set m [MENU $f.addAction.actions]
    set widg(UninstallActionsMenu) $m

    $m insert end cascade -label "All Actions" -menu $m.all
    MENU $m.all

    foreach group [lsort [array names ::InstallJammer::actiongroups]] {
        set submenu [MENU $m.[WidgetName $group]]
        $m insert end cascade -label "$group   " -menu $submenu

        foreach id $::InstallJammer::actiongroups($group) {
            set action [$id action]
            set allactions($action) $id
            $submenu add command -label [$id title] \
                -command [list ::InstallJammer::AddAction Uninstall $action]
        }
    }

    foreach action [lsort [array names allactions]] {
        set id $allactions($action)
        $m.all add command -label [$id title] \
            -command [list ::InstallJammer::AddAction Uninstall $action]
    }

    WinButton $f.addActionGroup -image [GetImage appwindow_list16] \
        -command [list ::InstallJammer::AddActionGroup Uninstall]
    pack $f.addActionGroup -side left -padx 2
    DynamicHelp::add $f.addActionGroup -text "New Action Group"

    WinButton $f.delete -image [GetImage buttoncancel16] \
        -command [list ::InstallJammer::Tree::Delete $widg(Uninstall)]
    pack $f.delete -side left -padx 2
    DynamicHelp::add $f.delete -text "Delete"

    set args [list -deltax 5 -padx 10 -haspage 0]
    eval $main insert end root CommonUninstall -data installtype \
        [list -text "Common Components" -font TkCaptionFont] $args
    eval $main insert end root StandardUninstall -data installtype \
        [list -text "Standard Uninstall" -font TkCaptionFont] $args
    eval $main insert end root ConsoleUninstall -data installtype \
        [list -text "Console Uninstall" -font TkCaptionFont] $args
    eval $main insert end root SilentUninstall -data installtype \
        [list -text "Silent Uninstall" -font TkCaptionFont] $args
    eval $main insert end root ActionGroupsUninstall -data installtype \
        [list -text "Action Groups" -font TkCaptionFont] $args

    ::InstallJammer::Tree::Setup Uninstall $tree
}

proc Frame.commandLine { setup } {
    global conf
    global widg

    set top [$widg(Product) getframe ${setup}CommandLine]

    ::InstallJammer::SetHelp CommandLineOptions

    if {[winfo exists $top.buttons]} {
        focus $top.sw.table
        return
    }

    set f [frame $top.buttons]
    pack $f -anchor w

    ScrolledWindow $top.sw
    pack $top.sw -expand 1 -fill both -padx 5

    set l [TableList $top.sw.table -cols 7 -bd 1 -relief ridge \
        -background #FFFFFF -selectmode extended -keycolumn 0 \
        -editstartcommand  "::InstallJammer::EditStartCommandLine  %W %i %c" \
        -editfinishcommand "::InstallJammer::EditFinishCommandLine %W %i %c"]

    $top.sw setwidget $l
    set widg(${setup}CommandLineOptionsTable) $l

    $l column configure 0 -title "Option" -width 15
    $l column configure 1 -title "Virtual Text" -width 15
    $l column configure 2 -title "Type" -width 8 \
        -editable 0 -values [list "Boolean" "Choice" "Prefix" "String" "Switch"]
    $l column configure 3 -title "Debug" -width 6 \
        -editable 0 -values [list Yes No]
    $l column configure 4 -title "Hide" -width 6 \
        -editable 0 -values [list Yes No]
    $l column configure 5 -title "Value(s)" -width 25 \
        -browsebutton 1 -browseargs [list -style Toolbutton] \
        -browsecommand "::InstallJammer::EditCommandLineOptionChoices %W %i"
    $l column configure 6 -title "Description" \
        -browsebutton 1 -browseargs [list -style Toolbutton] \
        -browsecommand "::InstallJammer::EditCommandLineOptionDescription %W %i"

    WinButton $f.add -image [GetImage filenew16] \
    	-command [list ::InstallJammer::NewCommandLineOption $l]
    pack $f.add -side left
    DynamicHelp::add $f.add -text "Add New Command Line Option"

    WinButton $f.delete -image [GetImage editdelete16] \
    	-command [list ::InstallJammer::DeleteCommandLineOption $l]
    pack $f.delete -side left
    DynamicHelp::add $f.delete -text "Delete Command Line Option"
}

proc Frame.virtualText {} {
    global conf
    global widg

    set top [$widg(Product) getframe virtualText]

    ::InstallJammer::SetHelp VirtualText

    if {[winfo exists $top.buttons]} {
        focus $top.listframe.listbox
        return
    }

    set f [frame $top.buttons]
    pack $f -anchor w

    ScrolledWindow $top.listframe
    pack $top.listframe -expand 1 -fill both -padx 5

    set l [TableList $top.listframe.listbox -cols 2 -bd 1 -relief ridge \
        -background #FFFFFF -selectmode extended -keycolumn 0 \
        -editstartcommand  "::InstallJammer::EditStartVirtualText  %W %i %c" \
        -editfinishcommand "::InstallJammer::EditFinishVirtualText %W %i %c"]

    $top.listframe setwidget $l
    set widg(VirtualTextTable) $l

    $l tag configure sel -borderwidth 1 -relief ridge
    $l column configure 0 -title "Text" -width 25
    $l column configure 1 -title "Value" \
        -browsebutton 1 -browseargs [list -style Toolbutton] \
        -browsecommand "::InstallJammer::LongEditVirtualText %W %i"

    WinButton $f.add -image [GetImage filenew16] \
    	-command "::InstallJammer::NewVirtualText $l"
    pack $f.add -side left
    DynamicHelp::add $f.add -text "Add New Virtual Text"

    WinButton $f.delete -image [GetImage editdelete16] \
    	-command "::InstallJammer::DeleteVirtualText $l"
    pack $f.delete -side left
    DynamicHelp::add $f.delete -text "Delete Virtual Text"

    ttk::label $f.langL -text "Language"
    pack $f.langL -side left -padx [list 20 2]

    ttk::combobox $f.lang -state readonly \
        -textvariable ::conf(VirtualTextLanguage) \
        -values [::InstallJammer::GetLanguages 1]
    pack $f.lang -side left -padx [list 0 20]

    bind $f.lang <<ComboboxSelected>> \
        "::InstallJammer::LoadVirtualText;after idle [list focus $l]"
}

proc Frame.diskBuilder {} {
    global conf
    global widg

    set top [$widg(Product) getframe diskBuilder]

    ::InstallJammer::SetHelp DiskBuilder

    if {[winfo exists $top.label]} {
        ## If this is the first time the user is seeing the
        ## build log, scroll to the bottom incase there's
        ## already log data in it.
        if {![info exists conf($widg(BuildLog),realized)]} {
            $widg(BuildLog) see end
            set conf($widg(BuildLog),realized) 1
        }

        return
    }

    grid rowconfigure    $top 1 -weight 1
    grid columnconfigure $top 1 -weight 1

    label $top.label -text "Platforms to Build:"
    grid  $top.label -row 0 -column 0 -sticky ws

    set f [frame $top.progressF]
    grid $f -row 0 -column 1 -sticky ew -padx 10
    grid columnconfigure $f 1 -weight 1

    label $f.l1 -text "Build Progress:"
    grid  $f.l1 -row 0 -column 0 -sticky w

    PROGRESSBAR $f.progress -variable ::conf(buildProgress)
    set widg(ProgressBuild) $f.progress
    grid $f.progress -row 0 -column 1 -sticky ew

    label $f.l2 -text "Platform Progress:"
    grid  $f.l2 -row 1 -column 0 -sticky w

    PROGRESSBAR $f.fileProgress -variable ::conf(buildPlatformProgress)
    set widg(ProgressBuildPlatform) $f.fileProgress
    grid $f.fileProgress -row 1 -column 1 -sticky ew

    ScrolledWindow $top.sw1
    grid $top.sw1 -row 1 -column 0 -sticky ns -pady [list 5 10]

    set t [OPTIONTREE $top.buildTree -width 16 -highlightthickness 0]
    $top.sw1 setwidget $t

    set widg(BuildTree) $t

    ScrolledWindow $top.sw2 -auto none
    grid $top.sw2 -row 1 -column 1 -sticky news -padx 10 -pady [list 5 2]

    set widg(BuildLog) [Text $top.log -wrap none -state readonly -height 1]
    $top.sw2 setwidget $top.log

    CHECKBUTTON $top.buildRelease -text "Build for final release" \
        -variable ::conf(buildForRelease)
    grid $top.buildRelease -row 2 -column 1 -sticky w -padx 10
    DynamicHelp::add $top.buildRelease -text "Build installers without \
        debugging options and with options optimized for final release"

    $widg(BuildLog) tag configure error -foreground red

    $widg(BuildLog) tag configure link -foreground blue -underline 1
    $widg(BuildLog) tag bind link <Enter> [list %W configure -cursor hand2]
    $widg(BuildLog) tag bind link <Leave> [list %W configure -cursor ""]
    $widg(BuildLog) tag bind link <1> {
        ::InstallJammer::Explore [InstallDir output]
    }

    set f [frame $top.buttons]
    grid $top.buttons -row 3 -column 1 -sticky e -padx 10

    BUTTON $f.clear -text "Clear Build Log" -width 14 \
        -image [GetImage editshred16] -compound left \
        -command ::InstallJammer::ClearBuildLog
    pack $f.clear -side left -padx 5

    BUTTON $f.build -text "Build Install" -width 14 -command Build \
        -image [GetImage build16] -compound left
    pack   $f.build -side left
}

proc Frame.testInstaller {} {
    global conf
    global widg

    set top [$widg(Product) getframe testInstaller]

    ::InstallJammer::SetHelp TestRun

    if {[winfo exists $top.l1]} { return }

    label $top.l1 -text "Select the options to use on the command-line:"
    pack  $top.l1 -anchor w -pady 5

    label $top.l2 -text "Command-Line:"
    pack  $top.l2 -anchor w

    ENTRY $top.e1 -textvariable ::conf(TestCommandLineOptions)
    pack  $top.e1 -anchor w -fill x
    bind  $top.e1 <Return> TestInstall

    label $top.l3 -text "Test Options:"
    pack  $top.l3 -anchor w -pady 5

    OPTIONTREE $top.options -highlightthickness 0
    pack $top.options -expand 1 -fill both

    bind $top.options <<TreeModify>> AdjustTestInstallOptions

    $top.options insert end root #auto -type checkbutton \
        -text "Save temporary directory for debugging" \
        -variable ::conf(SaveTempDir)

    $top.options insert end root #auto -type checkbutton \
        -text "Test in default mode" \
        -variable ::conf(TestAllDefaults)

    if {!$conf(windows)} {
        $top.options insert end root #auto -type checkbutton \
            -text "Test in console mode" \
            -variable ::conf(TestConsole)
    }

    $top.options insert end root #auto -type checkbutton \
        -text "Test in silent mode" \
        -variable ::conf(TestSilent)

    $top.options insert end root #auto -type checkbutton \
        -text "Test install in test mode and without installing files" \
        -variable ::conf(TestWithoutFiles)

    $top.options insert end root #auto -type checkbutton \
        -text "Test install with an open console window" \
        -variable ::conf(TestWithConsole)

    BUTTON $top.test -text "Test Install" -width 14 -command "TestInstall" \
        -image [GetImage actrun16] -compound left
    pack   $top.test -side bottom -anchor se -padx 5 -pady [list 10 0]

    bind $top <Alt-s> "focus $top.c2"
    bind $top <Alt-t> "focus $top.c1"
    bind $top <Alt-c> "focus $top.c3"
}

proc Frame.testUninstaller {} {
    global conf
    global widg

    set top [$widg(Product) getframe testUninstaller]

    ::InstallJammer::SetHelp TestUninstaller

    if {[winfo exists $top.l1]} { return }

    label $top.l1 -text "Select the options to use on the command-line:"
    pack  $top.l1 -anchor w -pady 5

    label $top.l2 -text "Command-Line:"
    pack  $top.l2 -anchor w

    ENTRY $top.e1 -textvariable ::conf(TestUninstallCommandLineOptions)
    pack  $top.e1 -anchor w -fill x
    bind  $top.e1 <Return> TestUninstall

    label $top.l3 -text "Test Options:"
    pack  $top.l3 -anchor w -pady 5

    OPTIONTREE $top.options -highlightthickness 0
    pack $top.options -expand 1 -fill both

    bind $top.options <<TreeModify>> AdjustTestUninstallOptions

    $top.options insert end root #auto -type checkbutton \
        -text "Save temporary directory for debugging" \
        -variable ::conf(TestUninstallDebugging)

    if {!$conf(windows)} {
        $top.options insert end root #auto -type checkbutton \
            -text "Test in console mode" \
            -variable ::conf(TestUninstallConsoleMode)
    }

    $top.options insert end root #auto -type checkbutton \
        -text "Test in silent mode" \
        -variable ::conf(TestUninstallSilentMode)

    $top.options insert end root #auto -type checkbutton \
        -text "Test uninstall in test mode and without uninstalling files" \
        -variable ::conf(TestUninstallWithoutFiles)

    $top.options insert end root #auto -type checkbutton \
        -text "Test uninstall with an open console window" \
        -variable ::conf(TestUninstallWithConsole)

    BUTTON $top.test -text "Test Uninstall" -width 14 \
        -command "TestUninstall" -image [GetImage edittrash16] -compound left
    pack   $top.test -side bottom -anchor se -padx 5 -pady [list 10 0]
}

proc WindowsPermissionsFrame { f tag arrayName } {
    set row -1

    incr row

    CHECKBUTTON $f.c1 -text "Archive" -variable ${arrayName}(PermArchive) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c1 -row $row -column 0 -sticky w

    CHECKBUTTON $f.c2 -text "Hidden" -variable ${arrayName}(PermHidden) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c2 -row $row -column 1 -sticky w

    CHECKBUTTON $f.c3 -text "Readonly" -variable ${arrayName}(PermReadonly) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c3 -row [incr row] -column 0 -sticky w

    CHECKBUTTON $f.c4 -text "System" -variable ${arrayName}(PermSystem) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c4 -row $row -column 1 -sticky w

    tag addtag $tag class Checkbutton class TCheckbutton children $f

    CHECKBUTTON $f.c -text "Use default attributes" \
    	-variable ${arrayName}(UseWindowsDefaultPermissions) \
    	-command "
    	    if {\$${arrayName}(UseWindowsDefaultPermissions)} {
		tag configure $tag -state disabled
	    } else {
		tag configure $tag -state normal
	    }
            ::FileGroupTree::SetPermissions $arrayName
	"

    grid $f.c -row [incr row] -column 0 -columnspan 2 -sticky w
}

proc UNIXPermissionsFrame { f tag arrayName } {
    set row -1

    set f [frame $f.unix]
    grid $f -row [incr row] -column 0 -columnspan 2 -sticky w

    incr row
    grid [label $f.exec  -text Exec]  -row $row -column 1
    grid [label $f.write -text Write] -row $row -column 2
    grid [label $f.read  -text Read]  -row $row -column 3

    grid [label $f.user  -text User]  -row [incr row] -column 0 -sticky w

    CHECKBUTTON $f.c3 -variable ${arrayName}(PermUserExecute) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c3 -row $row -column 1
    CHECKBUTTON $f.c2 -variable ${arrayName}(PermUserWrite) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c2 -row $row -column 2
    CHECKBUTTON $f.c1 -variable ${arrayName}(PermUserRead) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c1 -row $row -column 3

    grid [label $f.group -text Group] -row [incr row] -column 0 -sticky w

    CHECKBUTTON $f.c6 -variable ${arrayName}(PermGroupExecute) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c6 -row $row -column 1
    CHECKBUTTON $f.c5 -variable ${arrayName}(PermGroupWrite) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c5 -row $row -column 2
    CHECKBUTTON $f.c4 -variable ${arrayName}(PermGroupRead) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c4 -row $row -column 3

    grid [label $f.other -text Other] -row [incr row] -column 0 -sticky w

    CHECKBUTTON $f.c9 -variable ${arrayName}(PermOtherExecute) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c9 -row $row -column 1
    CHECKBUTTON $f.c8 -variable ${arrayName}(PermOtherWrite) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c8 -row $row -column 2
    CHECKBUTTON $f.c7 -variable ${arrayName}(PermOtherRead) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c7 -row $row -column 3

    tag addtag $tag class Checkbutton class TCheckbutton children $f

    CHECKBUTTON $f.c -text "Use default permissions" \
    	-variable ${arrayName}(UseUNIXDefaultPermissions) \
    	-command "
    	    if {\$${arrayName}(UseUNIXDefaultPermissions)} {
		tag configure $tag -state disabled
	    } else {
		tag configure $tag -state normal
	    }

            ::FileGroupTree::SetPermissions $arrayName
	"

    grid $f.c -row [incr row] -column 0 -columnspan 4 -sticky w
}

proc Window.preferences {} {
    global widg

    set top $widg(InstallJammer).preferences

    ::InstallJammer::SetHelp InstallBuilderPreferences

    array set ::tmppreferences [array get ::preferences]

    if {[winfo exists $top]} {
	wm deiconify $top
	return
    }

    toplevel     $top
    wm withdraw  $top
    update idletasks
    wm title     $top "InstallJammer Preferences"
    wm geometry  $top 450x400
    wm protocol  $top WM_DELETE_WINDOW "CancelPreferences"
    wm transient $top $widg(InstallJammer)
    BWidget::place $top 450 400 center $widg(InstallJammer)

    bind $top <Return> "SetPreferences"
    bind $top <Escape> "CancelPreferences"

    grid rowconfigure    $top 2 -weight 1
    grid columnconfigure $top 0 -weight 1

    Buttons $top -okcmd "SetPreferences" -cancelcmd "CancelPreferences" \
    	-helpcmd "Help InstallBuilderPreferences" -pack 0

    grid $top.bbox -row 0 -column 0 -sticky e
    grid [Separator $top.bboxsp1] -row 1 -column 0 -sticky ew

    ttk::notebook $top.n
    grid $top.n -row 2 -column 0 -sticky news -pady 10

    ttk::frame $top.n.dirs
    $top.n add $top.n.dirs -text "Directories"

    ttk::frame $top.n.programs
    $top.n add $top.n.programs -text "External Programs"

    ttk::frame $top.n.update
    #$top.n add $top.n.update -text "InstallJammer Update"

    $top.n select $top.n.dirs

    ## Project Directory
    set f $top.n.dirs.f
    pack [frame $f] -anchor nw -fill x -padx 5 -pady {5 0}
    
    grid columnconfigure $f 0 -weight 1

    label $f.projectDirL -text "Project Directory Location"
    grid  $f.projectDirL -row 0 -column 0 -sticky w -padx 5

    ENTRY $f.projectDirE -width 50 -textvariable ::tmppreferences(ProjectDir)
    grid  $f.projectDirE -row 1 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.projectDirB -command \
        [list GetDir ::tmppreferences(ProjectDir) -parent $top]
    grid  $f.projectDirB -row 1 -column 1

    ## Custom Theme Dir
    set f $top.n.dirs.f2
    pack [frame $f] -anchor nw -fill x -padx 5
    
    grid columnconfigure $f 0 -weight 1

    label $f.projectDirL -text "Custom Theme Directory Location"
    grid  $f.projectDirL -row 0 -column 0 -sticky w -padx 5

    ENTRY $f.projectDirE -width 50 \
        -textvariable ::tmppreferences(CustomThemeDir)
    grid  $f.projectDirE -row 1 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.projectDirB -command \
        [list GetDir ::tmppreferences(CustomThemeDir) -parent $top]
    grid  $f.projectDirB -row 1 -column 1

    ## Custom Action Dir
    set f $top.n.dirs.f3
    pack [frame $f] -anchor nw -fill x -padx 5
    
    grid columnconfigure $f 0 -weight 1

    label $f.projectDirL -text "Custom Action Directory Location"
    grid  $f.projectDirL -row 0 -column 0 -sticky w -padx 5

    ENTRY $f.projectDirE -width 50 \
        -textvariable ::tmppreferences(CustomActionDir)
    grid  $f.projectDirE -row 1 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.projectDirB -command \
        [list GetDir ::tmppreferences(CustomActionDir) -parent $top]
    grid  $f.projectDirB -row 1 -column 1

    ## Custom Condition Dir
    set f $top.n.dirs.f4
    pack [frame $f] -anchor nw -fill x -padx 5 -pady {0 5}
    
    grid columnconfigure $f 0 -weight 1

    label $f.projectDirL -text "Custom Condition Directory Location"
    grid  $f.projectDirL -row 0 -column 0 -sticky w -padx 5

    ENTRY $f.projectDirE -width 50 \
        -textvariable ::tmppreferences(CustomConditionDir)
    grid  $f.projectDirE -row 1 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.projectDirB -command \
        [list GetDir ::tmppreferences(CustomConditionDir) -parent $top]
    grid  $f.projectDirB -row 1 -column 1


    ## Create the External Programs tab.

    set f $top.n.programs.f
    pack [frame $f] -anchor nw -expand 1 -fill x -padx 5 -pady 5
    
    grid columnconfigure $f 0 -weight 1

    label $f.l2 -text "File Explorer"
    grid  $f.l2 -row 2 -column 0 -sticky w -padx 5

    ENTRY $f.e2 -width 50 -textvariable ::tmppreferences(FileExplorer)
    grid  $f.e2 -row 3 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.b2 -command \
        [list GetFile ::tmppreferences(FileExplorer) -parent $top]
    grid  $f.b2 -row 3 -column 1

    label $f.l3 -text "Help Browser" -padx 5
    grid  $f.l3 -row 4 -column 0 -sticky w

    set browsers [::InstallJammer::HelpBrowsers]

    ttk::combobox $f.e3 -width 50 -textvariable ::tmppreferences(HelpBrowser) \
    	-values $browsers
    grid  $f.e3 -row 5 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.b3 -command \
        [list GetFile ::tmppreferences(HelpBrowser) -parent $top]
    grid  $f.b3 -row 5 -column 1

    label $f.l4 -text "Editor" -padx 5
    grid  $f.l4 -row 6 -column 0 -sticky w

    ttk::entry $f.e4 -width 50 -textvariable ::tmppreferences(Editor)
    grid  $f.e4 -row 7 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.b4 -command \
        [list GetFile ::tmppreferences(Editor) -parent $top]
    grid  $f.b4 -row 7 -column 1


    ## Create the InstallJammer Update tab.

    set f $top.n.update.f
    pack [frame $f] -anchor nw -expand 1 -fill x -padx 5 -pady 5
    
    grid columnconfigure $f 0 -weight 1

    ttk::checkbutton $f.check \
        -text "Check for updates to InstallJammer on startup" \
        -variable ::tmppreferences(CheckForUpdates)
    grid $f.check -row 0 -column 0 -sticky nw -pady 2

    ttk::checkbutton $f.useProxy \
        -text "Use a proxy server" \
        -variable ::tmppreferences(UseProxyServer) \
        -command {tag configure proxy -state \
        [expr {$::tmppreferences(UseProxyServer) ? "normal" : "disabled"}]}
    grid $f.useProxy -row 1 -column 0 -columnspan 2 -sticky nw -pady {10 2}

    ttk::label $f.proxyHostL -text "Proxy Host"
    grid $f.proxyHostL -row 2 -column 0 -padx 20 -pady {2 0} -sticky nw
    tag add proxy $f.proxyHostL

    ttk::entry $f.proxyHost -textvariable ::tmppreferences(ProxyHost)
    grid $f.proxyHost -row 3 -column 0 -padx 20 -sticky ew
    tag add proxy $f.proxyHost

    ttk::label $f.proxyPortL -text "Proxy Port"
    grid $f.proxyPortL -row 4 -column 0 -padx 20 -pady {2 0} -sticky nw
    tag add proxy $f.proxyPortL

    ttk::entry $f.proxyPort -textvariable ::tmppreferences(ProxyPort)
    grid $f.proxyPort -row 5 -column 0 -padx 20 -sticky ew
    tag add proxy $f.proxyPort

    $f.useProxy invoke
    $f.useProxy invoke

    ttk::button $top.n.update.checkNow -text "Check for Updates Now" \
        -padding {4 2} -command {::InstallJammer::DownloadVersionInfo 1}
    pack $top.n.update.checkNow -anchor se -padx 5 -pady 5


    wm deiconify $top
}

proc Window.filterFileGroups {} {
    global widg

    set top  .__filterFileGroups
    set tree $widg(FileGroupTree)

    set parent $widg(InstallJammer)

    ClearTmpVars

    set ::TMPARRAY(regexp)    0
    set ::TMPARRAY(include)   include
    set ::TMPARRAY(filterall) 1
    set ::TMPARRAY(recursive) 1
    set ::TMPARRAY(includePatterns) [list]
    set ::TMPARRAY(excludePatterns) [list]

    set selection [$tree selection get]
    if {![lempty $selection]} { set ::TMPARRAY(filterall) 0 }

    toplevel     $top
    wm withdraw  $top
    update idletasks
    wm transient $top $parent
    wm geometry  $top 300x260
    wm title     $top "Filter File Groups"
    wm protocol  $top WM_DELETE_WINDOW "set ::TMP 0"
    CenterWindow $top

    bind $top <Escape> "set ::TMP 0"
    bind $top <Return> "set ::TMP 1"

    Buttons $top -okcmd "set ::TMP 1" -cancelcmd "set ::TMP 0" \
    	-helpcmd "Help FilterFileGroups"

    label $top.l1 -text "Include File Patterns:"
    pack  $top.l1 -anchor w

    ENTRY $top.e1 -textvariable ::TMPARRAY(includePatterns)
    pack  $top.e1 -anchor w -fill x

    focus $top.e1

    label $top.l2 -text "Exclude File Patterns:"
    pack  $top.l2 -anchor w

    ENTRY $top.e2 -textvariable ::TMPARRAY(excludePatterns)
    pack  $top.e2 -anchor w -fill x

    CHECKBUTTON $top.c1 -text "Recursively Check File Groups" \
    	-variable ::TMPARRAY(recursive)
    pack $top.c1 -anchor w

    CHECKBUTTON $top.c2 -text "Use Regular Expression Matching" \
    	-variable ::TMPARRAY(regexp)
    pack $top.c2 -anchor w -pady [list 0 5]

    RADIOBUTTON $top.r4 -text "Filter selected file groups" \
    	-variable ::TMPARRAY(filterall) -value 0
    pack $top.r4 -anchor w

    RADIOBUTTON $top.r3 -text "Filter all file groups" \
    	-variable ::TMPARRAY(filterall) -value 1
    pack $top.r3 -anchor w -pady [list 0 5]

    RADIOBUTTON $top.r1 -text "Include files that match both" \
    	-variable ::TMPARRAY(include) -value include
    pack $top.r1 -anchor w

    RADIOBUTTON $top.r2 -text "Exclude files that match both" \
    	-variable ::TMPARRAY(include) -value exclude
    pack $top.r2 -anchor w

    wm deiconify $top
    tkwait variable ::TMP
    destroy $top
    if {!$::TMP} { return }

    lappend opts -regexp    $::TMPARRAY(regexp)
    lappend opts -include   $::TMPARRAY(includePatterns)
    lappend opts -exclude   $::TMPARRAY(excludePatterns)
    lappend opts -recursive $::TMPARRAY(recursive)
    lappend opts -defaultaction $::TMPARRAY(include)

    if {!$::TMPARRAY(filterall)} {
	lappend opts -nodes [$tree selection get]
    }

    eval ::InstallJammer::FilterFileGroups $opts
}

proc VersionFrame {path arrayName args} {
    set command ""
    array set _args $args
    if {[info exists _args(-command)]} {
        set command $_args(-command)
        unset _args(-command)
    }

    eval frame $path [array get _args]

    SPINBOX $path.e1 -textvariable ${arrayName}(MajorVersion) -width 3 -to 999 \
    	-validate key -validatecommand [list ValidateSpinBox %W %s %P] -bd 1
    bind  $path.e1 <Return> $command
    pack  $path.e1 -side left
    label $path.l1 -text "." -bd 1
    pack  $path.l1 -side left
    DynamicHelp::register $path.e1 balloon "Major Version"

    SPINBOX $path.e2 -textvariable ${arrayName}(MinorVersion) -width 3 -to 999 \
    	-validate key -validatecommand [list ValidateSpinBox %W %s %P] -bd 1
    bind  $path.e2 <Return> $command
    pack  $path.e2 -side left
    label $path.l2 -text "." -bd 1
    pack  $path.l2 -side left
    DynamicHelp::register $path.e2 balloon "Minor Version"

    SPINBOX $path.e3 -textvariable ${arrayName}(PatchVersion) -width 3 -to 999 \
    	-validate key -validatecommand [list ValidateSpinBox %W %s %P] -bd 1
    bind  $path.e3 <Return> $command
    pack  $path.e3 -side left
    label $path.l3 -text "." -bd 1
    pack  $path.l3 -side left
    DynamicHelp::register $path.e3 balloon "Patch Version"

    SPINBOX $path.e4 -textvariable ${arrayName}(BuildVersion) -width 3 -to 999 \
    	-validate key -validatecommand [list ValidateSpinBox %W %s %P] -bd 1
    bind  $path.e4 <Return> $command
    pack  $path.e4 -side left
    DynamicHelp::register $path.e4 balloon "Build Version"
}

proc ::InstallJammer::EditFinishProperty { path node } {
    upvar #0 [$path itemcget $node -variable] newvalue
    set oldvalue [$path edit value]

    if {![::InstallJammer::CheckVirtualText $newvalue]} { return 0 }

    if {![string equal $oldvalue $newvalue]} { Modified }

    return 1
}

proc ::InstallJammer::FinishEditVersion { args } {
    global info
    set old $info(InstallVersion)

    set info(InstallVersion)     $info(MajorVersion)
    append info(InstallVersion) .$info(MinorVersion)
    append info(InstallVersion) .$info(PatchVersion)
    append info(InstallVersion) .$info(BuildVersion)

    if {![string equal $old $info(InstallVersion)]} { Modified }

    return 1
}

proc SetInstallPanes {} {
    global conf
    ::msgcat::mcmset en [array get ::InstallJammer::preview::text]
    if {[info exists conf(window)]} { Cancel $conf(window) }
}

proc PopupEditMenu {w X Y} {
    global widg
    set menu $widg(RightClickEditMenu)

    set ::edit::widget $w

    focus $w

    tag configure editMenu -state normal

    if {[lempty [::edit::curselection $w]]} {
	$menu entryconfigure 0 -state disabled
	$menu entryconfigure 1 -state disabled
	$menu entryconfigure 3 -state disabled
    }

    if {[$w cget -state] == "disabled"} {
	$menu entryconfigure 0 -state disabled
	$menu entryconfigure 2 -state disabled
	$menu entryconfigure 3 -state disabled
    }

    if {[catch {clipboard get} clip]} { set clip [list] }
    if {[lempty $clip]} {
	$menu entryconfigure 2 -state disabled
    }

    $menu post $X $Y
    #if {$::tcl_platform(platform) == "unix"} { tkwait window $menu }
}

proc Buttons { w args } {
    set data(-ok) 1
    set data(-cancel) 1
    set data(-help) 1
    set data(-pack) 1

    set data(-oktxt)     OK
    set data(-helptxt)   Help
    set data(-canceltxt) Cancel

    set data(-okimg)     buttonok16
    set data(-helpimg)   acthelp16
    set data(-cancelimg) buttoncancel16

    set data(-okcmd)     "Cancel $w"
    set data(-helpcmd)   "Help"
    set data(-cancelcmd) "Cancel $w"

    array set data $args

    ## Check to see if the image names are references to another image.
    foreach opt {-okimg -cancelimg -helpimg} {
	if {[info exists data(-$data($opt))]} {
	    set data($opt) $data(-$data($opt))
	}
    }

    set f [frame $w.bbox -height 24 -width 235]

    if {$data(-help)} {
	set b [WinButton $f.help -padx 0 -pady 0 \
	    -image [GetImage $data(-helpimg)] \
	    -command $data(-helpcmd)]
	pack $b -side right
	DynamicHelp::register $f.help balloon $data(-helptxt)
    }

    if {$data(-cancel)} {
	set b [WinButton $f.cancel -padx 0 -pady 0\
	    -image [GetImage $data(-cancelimg)] \
	    -command $data(-cancelcmd)]
	pack $b -side right
	DynamicHelp::register $f.cancel balloon $data(-canceltxt)
    }

    if {$data(-ok)} {
	set b [WinButton $f.ok -padx 0 -pady 0 \
	    -image [GetImage $data(-okimg)] \
	    -command $data(-okcmd)]
	pack $b -side right
	DynamicHelp::register $f.ok balloon $data(-oktxt)
    }

    if {$data(-pack)} {
        pack $f -fill x -side top -anchor ne -pady 5
        pack [Separator $w.bboxsp1] -fill x
        pack [frame $w.bboxsp2 -height 5]
    }

    return $f
}

proc SetPreferences {} {
    array set ::preferences [array get ::tmppreferences]
    CancelPreferences
}

proc CancelPreferences {} {
    ::InstallJammer::SetHelp <last>
    wm withdraw [::InstallJammer::TopName .preferences]
}

proc ::InstallJammer::AddPlatformPropertyNode { prop arrayName
                                                {includeArchives 0} } {
    global conf

    $prop insert end root platforms -text "Build Platforms"

    set platforms [AllPlatforms]
    if {$includeArchives} { eval lappend platforms $conf(Archives) }

    foreach platform [lsort $platforms] {
        set pretty [PlatformText $platform]
        AddProperty $prop end platforms foo platform,$platform \
            ::FileGroupTree::details(platform,$platform) -data $platform \
            -pretty $pretty -node platform,$platform -type boolean
    }
}

proc InitializeBindings {} {
    global conf

    if {$conf(osx)} {
        event add <<RightClick>> <Button-2>
    } else {
        event add <<RightClick>> <Button-3>
    }

    BIND all <FocusIn>  { ::InstallJammer::WidgetFocusIn %W }
    BIND all <FocusOut> { ::InstallJammer::WidgetFocusOut %W }

    BIND all <Control-x> ::InstallJammer::EditCut
    BIND all <Control-c> ::InstallJammer::EditCopy
    BIND all <Control-v> ::InstallJammer::EditPaste

    BIND Entry  <<RightClick>> { PopupEditMenu %W %X %Y }
    BIND Entry  <Control-a>    { ::InstallJammer::EditSelectAll }
    BIND Entry  <Control-A>    { ::InstallJammer::EditSelectAll }
    BIND TEntry <Control-a>    { ::InstallJammer::EditSelectAll }
    BIND TEntry <Control-A>    { ::InstallJammer::EditSelectAll }

    BIND Text  <<RightClick>> { PopupEditMenu %W %X %Y }
    BIND Text  <Control-a>    { ::InstallJammer::EditSelectAll }
    BIND Text  <Control-A>    { ::InstallJammer::EditSelectAll }

    BIND Button <Return> { %W invoke }

    #BIND Properties <FocusOut> { ::InstallJammer::FinishEditingActiveNode }
}

proc ::InstallJammer::WidgetFocusIn { w } {
    ::InstallJammer::FinishEditingActiveNode $w

    switch -- [winfo class $w] {
        "Entry" - "TEntry" - "Text" {
            set ::edit::widget $w
        }
    }
}

proc ::InstallJammer::WidgetFocusOut { w } {
    set ::edit::widget ""
}
Added lib/gui-osx.tcl.














































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

option add *Installjammer*background                   #F0F0F0
option add *Installjammer*Entry.background             #FFFFFF

tk_setPalette #F0F0F0

proc Window.installjammer { {base .installjammer} } {
    global conf
    global widg
    global preferences

    set widg(InstallJammer)      $base
    set widg(Main)               $base.main
    set widg(MainMenu)           $base.m
    set widg(MainEditMenu)       $base.m.edit
    set widg(MainFileMenu)       $base.m.file
    set widg(MainBuildMenu)      $base.m.build
    set widg(MainHelpMenu)       $base.m.helpm
    set widg(MainAppleMenu)      $base.m.apple

    set geometry 800x600+50+20
    if {[info exists preferences(Geometry)]} {
        set geometry $preferences(Geometry)
    }

    if {[winfo exists $base]} {
        wm geometry  $base $geometry
        wm deiconify $base

        if {[info exists preferences(Zoomed)] && $preferences(Zoomed)} {
            wm state $base zoomed
        }

        return
    }

    toplevel    $base -class Installjammer
    wm withdraw $base
    update idletasks
    wm geometry $base $geometry
    wm protocol $base WM_DELETE_WINDOW Exit
    wm minsize  $base 640 480

    ::InstallJammer::SetMainWindowTitle

    if {[string length [package provide twapi]]} {
        set title "InstallJammer - Multiplatform Installer"
        set conf(hwin) [twapi::find_windows -text $title]
    }

    bind all <F1> {Help $conf(HelpTopic)}

    bind $base <F7> { Build }
    bind $base <Command-F5> { TestInstall }

    bind $base <Command-b> { Build }
    bind $base <Command-r> { TestInstall }

    bind $base <Command-n> "NewFromWizard"
    bind $base <Command-N> "NewFromWizard"

    bind $base <Command-o> "Open"
    bind $base <Command-O> "Open"

    bind $base <Command-s> "Save"
    bind $base <Command-S> "Save"

    bind $base <Command-w> "Close"
    bind $base <Command-W> "Close"

    bind $base <Shift-Command-s> "SaveAs"
    bind $base <Shift-Command-S> "SaveAs"

    InstallJammerIcons add blank -imageargs [list -width 16 -height 16]

    $base configure -menu $base.m

    ## Create the main menu
    set m [menu $widg(MainMenu)]
    MENU $widg(MainFileMenu)
    MENU $widg(MainEditMenu)
    MENU $widg(MainBuildMenu)
    MENU $widg(MainHelpMenu)
    MENU $widg(MainAppleMenu)

    $m add cascade -label Apple -menu $widg(MainAppleMenu)

    $widg(MainAppleMenu) add command -label "About InstallJammer" \
        -underline 0 -command "::InstallJammer::AboutInstallJammer"
    $widg(MainAppleMenu) add separator

    $m add cascade -label File -menu $m.file -underline 0

    $m.file add command -label "New" -underline 0 \
        -accel "Command-N"  -command New
    $m.file add command -label "New Project Wizard..." -underline 0 \
        -command NewFromWizard
    $m.file add command -label "Open..." -underline 0 \
        -accel "Command-O" -command Open
    $m.file add separator
    $m.file add command -label "Close" -underline 0 \
        -accel "Command-W" -command Close
    $m.file add command -label "Save" -underline 0 -accel "Command-S" \
        -command Save
    #$m.file add command -label "Save Project as..." -underline 5 \
        #-accel "Shift-Command-S" -command SaveAs
    
    tag add project [list $m.file "Save Project"]
    #tag add project [list $m.file "Save Project as..."]
    tag add project [list $m.file "Close Project"]

    $m add cascade -label Edit -menu $m.edit -underline 0

    $m.edit add command -label Cut -underline 2 -accel "Command-X" \
    	-command ::InstallJammer::EditCut
    $m.edit add command -label Copy -underline 0 -accel "Command-C" \
    	-command ::InstallJammer::EditCopy
    $m.edit add command -label Paste -underline 0 -accel "Command-V" \
    	-command ::InstallJammer::EditPaste
    $m.edit add command -label Delete -underline 0 -accel "Delete" \
    	-command ::InstallJammer::EditDelete
    $m.edit add separator
    $m.edit add command -label "Select All" -underline 7 -accel "Command-A" \
    	-command ::InstallJammer::EditSelectAll

    tag addtag editMenu menuentries $m recursive

    $m add cascade -label Build -menu $m.build -underline 0

    $m.build add command -label "Build Install" -underline 0 \
    	-accel "Command-B" -command "Build"
    $m.build add command -label "Quick Build Install" -underline 0 \
    	-accel "Command-B" -command ::InstallJammer::QuickBuild
    $m.build add command -label "Stop Build" -underline 0 \
    	-command ::InstallJammer::StopBuild
    	
    $m.build add command -label "Run Install" -underline 0 \
    	-accel "Command-R" -command "TestInstall"
    $m.build add command -label "Run Uninstall" -underline 4 \
        -command "TestUninstall"
    tag add project [list $m.build "Build Install"]
    tag add project [list $m.build "Quick Build Install"]
    tag add project [list $m.build "Stop Build"]
    tag add project [list $m.build "Run Install"]
    tag add project [list $m.build "Run Uninstall"]

    $m add cascade -label Help -menu $m.helpm -underline 0

    if {[::InstallJammer::LocalHelpExists]} {
        $m.helpm add command -label "InstallJammer Help" \
            -underline 0 -accel "F1" \
            -command {Help $conf(DefaultHelpTopic)}
        $m.helpm add command -label "Release Notes" -underline 0 \
            -command [list Help ReleaseNotes]
        $m.helpm add separator
    }
    $m.helpm add command -label "Online Help" -underline 0 \
    	-command [list ::InstallJammer::LaunchBrowser $conf(HelpURL)]
    $m.helpm add separator
    $m.helpm add command -label "Show Debug Console" \
	-underline 0 -command "console show"

    if {$conf(demo)} {
	$m.helpm add command -label "About Demo Mode" \
	    -underline 0 -command "Help Demo"
    }

    set toolbar $base.toolbar
    set widg(MainToolbar) $toolbar
    pack [ttk::frame $toolbar] -anchor w -fill x

    set b [WinButton $toolbar.new -image [GetImage filenew22] \
    	-command NewFromWizard]
    pack $b -side left
    DynamicHelp::register $b balloon "New Project Wizard"

    set b [WinButton $toolbar.open -image [GetImage fileopen22] -command Open]
    pack $b -side left
    DynamicHelp::register $b balloon "Open Install"

    set b [WinButton $toolbar.save -image [GetImage filesave22] -command Save]
    pack $b -side left
    DynamicHelp::register $b balloon "Save Install"
    tag add project $b

    set b [WinButton $toolbar.exploreProject \
        -image [GetImage filefind22] -command ::InstallJammer::ExploreProject]
    pack $b -side left
    DynamicHelp::register $b balloon "Explore Project"
    tag add project $b

    pack [Separator $toolbar.sp1 -orient vertical] \
    	-side left -fill y -padx 3 -pady 4

    set widg(BuildButton) [WinButton $toolbar.build \
        -image [GetImage build22] -command Build -state disabled]
    pack $widg(BuildButton) -side left
    DynamicHelp::register $widg(BuildButton) balloon "Build Install"
    tag add project $widg(BuildButton)

    set widg(BuildQuickButton) [WinButton $toolbar.qbuild -state disabled \
        -image [GetImage quickbuild22] -command ::InstallJammer::QuickBuild]
    pack $widg(BuildQuickButton) -side left
    DynamicHelp::register $widg(BuildQuickButton) balloon "Quick Build Install"
    tag add project $widg(BuildQuickButton)

    set widg(StopBuildButton) [WinButton $toolbar.stopbuild -state disabled \
        -image [GetImage actstop22] -command ::InstallJammer::StopBuild]
    pack $widg(StopBuildButton) -side left
    DynamicHelp::register $widg(StopBuildButton) balloon "Stop Build"
    tag add project $widg(StopBuildButton)

    set widg(TestButton) [WinButton $toolbar.test -image [GetImage actrun22] \
    	-command TestInstall -state disabled]
    pack $widg(TestButton) -side left
    DynamicHelp::register $widg(TestButton) balloon "Test Install"
    tag add project $widg(TestButton)

    WinButton $toolbar.exploreInstall -image [GetImage filefind22] \
        -command ::InstallJammer::ExploreTestInstall -state disabled
    pack $toolbar.exploreInstall -side left
    DynamicHelp::add $toolbar.exploreInstall -text "Explore Test Install"
    tag add project  $toolbar.exploreInstall

    WinButton $toolbar.uninstall -image [GetImage edittrash22] \
        -command TestUninstall -state disabled
    pack $toolbar.uninstall -side left
    DynamicHelp::add $toolbar.uninstall -text "Test Uninstall"
    tag add project  $toolbar.uninstall

    WinButton $toolbar.help \
    	-image [GetImage acthelp22] \
    	-command {Help $conf(HelpTopic)}
    pack $toolbar.help -side right
    DynamicHelp::register $toolbar.help balloon "Help"

    set status [StatusBar $base.status -showresize 0]
    set widg(Status) $status
    pack $status -fill x -side bottom
    set f [$status getframe]

    ttk::label $f.status -textvariable conf(status) -anchor w -width 1
    $status add $f.status -weight 1 -separator 0

    PROGRESSBAR $f.progress
    set widg(Progress) $f.progress
    $status add $f.progress -separator 0
    grid remove $widg(Progress)

    set n [ttk::notebook $widg(Main)]
    pack $widg(Main) -expand 1 -fill both

    set widg(StartPageTab) [ttk::frame $n.fProjects]
    $n add $widg(StartPageTab) -text "Start Page" \
        -compound left -image [GetImage startpage16]

    set widg(InstallDesignerTab) [ttk::frame $n.fProduct]
    $n add $widg(InstallDesignerTab) -text "Install Designer" -state disabled \
        -compound left -image [GetImage actwizard16]

    $n select $widg(InstallDesignerTab)

    ## Create the Projects tab.
    set widg(Projects) $widg(StartPageTab).c

    ScrolledWindow $widg(StartPageTab).sw
    pack $widg(StartPageTab).sw -expand 1 -fill both

    canvas $widg(Projects) -bg #FFFFFF -bd 2 -relief sunken
    $widg(StartPageTab).sw setwidget $widg(Projects)

    label  $widg(Projects).logo -image logo -background #FFFFFF
    pack   $widg(Projects).logo -side bottom -anchor se -padx 10 -pady 10

    set c $widg(Projects)
    $c bind project <1>     "::InstallJammer::LoadProject 1"
    $c bind project <2>     "::InstallJammer::ProjectPopup %X %Y"
    $c bind project <Enter> "::InstallJammer::EnterProjectItem %W"
    $c bind project <Leave> "::InstallJammer::LeaveProjectItem %W"

    ## Create the Project popup.

    set m [MENU $widg(Projects).rightClick]
    $m add command -label "Open Project" \
        -command "::InstallJammer::LoadProject"
    $m add command -label "Explore Project" \
        -command "::InstallJammer::ExploreProject"
    $m add separator
    $m add command -label "Rename Project" \
        -command "::InstallJammer::RenameProject"
    $m add command -label "Duplicate Project" \
        -command "::InstallJammer::DuplicateProject"
    $m add separator
    $m add command -label "Delete Project" \
        -command "::InstallJammer::DeleteProject"

    ## Create the Product tab.
    set widg(Product) $widg(InstallDesignerTab).p

    set opts {}
    if {[info exists preferences(Geometry,Product)]} {
        set opts $preferences(Geometry,Product)
    }

    eval [list PREFERENCES $widg(Product) -showlines 0 -treewidth 215 \
    	-padx [list 10 0] -deltax 5 -deltay 18 -treepadx 5] $opts

    set main $widg(Product)

    $main insert end root general -text "General Information" \
        -font TkCaptionFont -haspage 0
    	$main insert end general applicationInformation \
	    -text "Application Information" \
	    -raisecommand Frame.applicationInformation
    	$main insert end general platformInformation \
	    -text "Platform Information" \
	    -raisecommand Frame.platformInformation
        $main insert end general packageAndArchiveInformation \
            -text "Package and Archive Information" \
            -raisecommand Frame.packageAndArchiveInformation

    $main insert end root groups  -text "Components and Files" \
    	-font TkCaptionFont -haspage 0
    	$main insert end groups groupsAndFiles \
	    -text "Groups and Files" \
	    -raisecommand Frame.groupsAndFiles
	$main insert end groups components \
	    -text "Components" \
	    -raisecommand Frame.components
        $main insert end groups setupTypes \
            -text "Setup Types" \
            -raisecommand Frame.setupTypes

    $main insert end root installInterface -text "Install User Interface" \
        -font TkCaptionFont -haspage 0
        $main insert end installInterface install \
            -text "Install Panes and Actions" \
            -raisecommand Frame.install
        $main insert end installInterface InstallCommandLine \
            -text "Install Command Line Options" \
            -raisecommand [list Frame.commandLine Install]

    $main insert end root uninstallInterface -text "Uninstall User Interface" \
        -font TkCaptionFont -haspage 0
        $main insert end uninstallInterface uninstall \
            -text "Uninstall Panes and Actions" \
            -raisecommand Frame.uninstall
        $main insert end uninstallInterface UninstallCommandLine \
            -text "Uninstall Command Line Options" \
            -raisecommand [list Frame.commandLine Uninstall]

    $main insert end root virtualDefinitions -text "Virtual Definitions" \
    	-font TkCaptionFont -haspage 0
    	$main insert end virtualDefinitions virtualText \
	    -text "Virtual Text Strings" \
	    -raisecommand Frame.virtualText

    $main insert end root builder -text "Run Disk Builder" \
        -font TkCaptionFont -haspage 0
    	$main insert end builder diskBuilder -text "Disk Builder" \
            -raisecommand Frame.diskBuilder

    $main insert end root test -text "Test the Installation" \
        -font TkCaptionFont -haspage 0
    	$main insert end test testInstaller -text "Test Installer" \
            -raisecommand Frame.testInstaller
    	$main insert end test testUninstaller -text "Test Uninstaller" \
            -raisecommand Frame.testUninstaller

    #Frame.general
    #Frame.applicationInformation
    #Frame.platformInformation
    Frame.groupsAndFiles
    Frame.components
    Frame.setupTypes
    Frame.install
    Frame.commandLine Install
    Frame.uninstall
    Frame.commandLine Uninstall
    Frame.virtualText
    Frame.diskBuilder
    #Frame.testInstaller

    foreach node [$main nodes root] { $main open $node 1 }

    ## Create the standard right-click edit menu.
    set m [POPUP $base.editMenu -tearoff 0]
    set widg(RightClickEditMenu) $m
    $m add command -label Cut -underline 2 \
    	-command {::edit::cut $::edit::widget} \
    	-image [GetImage editcut16] -compound left
    $m add command -label Copy -underline 0 \
    	-command {::edit::copy $::edit::widget} \
    	-image [GetImage editcopy16] -compound left
    $m add command -label Paste -underline 0 \
    	-command {::edit::paste $::edit::widget} \
    	-image [GetImage editpaste16] -compound left
    $m add command -label Delete -underline 0 \
    	-command {::edit::delete $::edit::widget} \
    	-image [GetImage editdelete16] -compound left
    $m add command -label "Select All" -underline 7 \
    	-command {::edit::selectall $::edit::widget} \
    	-image [GetImage blank] -compound left
    tag addtag editMenu menuentries $m recursive

    ## Create the properties right-click menu.
    set m [POPUP $base.propertiesRightClick -tearoff 0]
    set widg(PropertiesRightClick) $m
    $m add command -label "Copy Value" \
        -command ::InstallJammer::CopyPropertiesValue \
    	-image [GetImage editcopy16] -compound left
    $m add command -label "Paste Value" \
        -command ::InstallJammer::PastePropertiesValue \
        -image [GetImage editpaste16] -compound left

    ::InstallJammer::SetHelp <default>
}

proc Frame.applicationInformation {} {
    global conf
    global widg

    set f1 [$widg(Product) getframe applicationInformation]
    set p  $f1.p

    set widg(ApplicationInformationPref) $p

    ::InstallJammer::SetHelp ApplicationInformation

    if {[winfo exists $p]} { return }

    ScrolledWindow $f1.sw -scrollbar vertical -auto vertical
    PROPERTIES $p -browseargs [list -style Toolbutton]
    $f1.sw setwidget $p
    pack $f1.sw -expand 1 -fill both

    $p insert end root standard -text "Application Information" \
        -helptext "This section describes general information about\
                your application and your project."

        $p insert end standard #auto -text "Application ID" \
            -variable info(ApplicationID) -helptext "The unique ID for this\
                application"
	$p insert end standard #auto -text "Application Name" \
	    -variable info(AppName) -helptext "The name of your application"

	$p insert end standard #auto -text "Application URL" \
	    -variable info(ApplicationURL) -helptext \
                "The main URL where people can find your application."

	$p insert end standard #auto -text "Company" \
	    -variable info(Company) -helptext "Your company name"

	$p insert end standard #auto -text "Copyright" \
	    -variable info(Copyright) -helptext "Copyright of your application"

	$p insert end standard #auto -text "Install Icon" \
	    -variable info(Icon) \
	    -browsebutton 1 -browsecommand [list GetImageFile ::info(Icon)] \
            -helptext "A standard icon to use for your install"

	$p insert end standard #auto -text "Install Image" \
	    -variable info(Image) \
	    -browsebutton 1 -browsecommand [list GetImageFile ::info(Image)] \
            -helptext "A standard image to use for your install"

	VersionFrame $f1.installVersion info
	$p insert end standard #auto -text "Install Version" \
	    -variable info(InstallVersion) -editwindow $f1.installVersion \
            -editfinishcommand ::InstallJammer::FinishEditVersion -helptext \
                "The build version for your install"

	$p insert end standard #auto -text "Short Application Name" \
	    -variable info(ShortAppName) -helptext \
                "The short name of your application."

        $p insert end standard #auto -text "Upgrade Application ID" \
            -variable info(UpgradeApplicationID) -helptext "If this project\
                is an upgrade to another application, this is the unique ID\
                for that application"

	$p insert end standard #auto -text "Version String" \
	    -variable info(Version) -helptext "The version of your application"


    $p insert end root features -text "Install Features" \
        -helptext "This section defines different features that can be\
                enabled or disabled for your install project."

        $p insert end features #auto -text "Allow Language Selection" \
            -variable info(AllowLanguageSelection) -editable 0 \
            -values [list Yes No] -helptext "Allow the user to select\
                which language to use for installation"

	set actions [list "Cancel and Stop" "Continue to Next Pane"]
	lappend actions "Rollback and Stop" "Rollback and Continue to Next Pane"
	$p insert end features #auto -text "Cancelled Install Action" \
	    -variable info(CancelledInstallAction) -editable 0 \
            -values $actions -helptext "The action your install will take when\
                the user cancels in the middle of installing files"

        $p insert end features #auto -text "Default Language" \
            -variable info(DefaultLanguage) -editable 0 \
            -valuescommand ::InstallJammer::GetLanguages \
            -helptext "The default language to use during installation.  This\
                could change depending on system settings if the user is\
                allowed to select a language"

        $p insert end features #auto -text "Extract Solid Archives on Startup" \
            -variable info(ExtractSolidArchivesOnStartup) -editable 0 \
            -values [list Yes No] -helptext "Whether or not InstallJammer\
                should extract solid archives during startup or wait until\
                just before file installation"

        $p insert end features #auto -text "Install Password" \
            -variable info(InstallPassword) \
            -helptext "A password to encrypt the installer with.  The user\
                must then be prompted for a password to install"

    $p insert end root languages -text "Install Languages" \
        -helptext "This section defines which languages are supported by\
                        your installer."

    variable ::InstallJammer::languages
    foreach lang [::InstallJammer::GetLanguages] {
        set code $languages($lang)
        $p insert end languages #auto -text "$lang" \
            -variable info(Language,$code) -editable 0 \
            -values {Yes No} -helptext "Allow user to choose $lang as the\
                install language if Allow Language Selection is true"
    }

    $p insert end root preferences -text "Project Preferences" \
        -helptext "This section defines preferences about how InstallJammer\
                will save and build your project."

	set actions [list "Fail (recommended)" \
                "Continue without including missing files"]
	$p insert end preferences #auto -text "Command Line Failure Action" \
	    -variable info(CommandLineFailureAction) \
	    -editable 0 -values $actions -helptext "The action InstallJammer\
                will take when a file is missing while building installs from\
                the command line"

        for {set i 1} {$i <= 9} {incr i} { lappend levels $i }
	$p insert end preferences #auto -text "Compression Level" \
	    -variable info(CompressionLevel) -editable 0 \
            -values $levels -helptext "The level of compression to use when\
                storing files in your install with zlib compression\
                (1 = faster, 9 = smaller)"

	$p insert end preferences #auto -text "Compression Method" \
	    -variable info(CompressionMethod) -editable 0 \
            -values $conf(CompressionMethods) -helptext "The method of\
                compression to use when storing files in your install"

	$p insert end preferences #auto \
            -text "Include Install Debugging Options" \
	    -variable info(IncludeDebugging) -editable 0 \
            -values [list Yes No] -helptext "Turn install debugging options\
                on or off"

	$p insert end preferences #auto \
            -text "Preserve UNIX File Permissions" \
	    -variable info(PreserveFilePermissions) -editable 0 \
            -values [list Yes No] -helptext "Whether or not InstallJammer\
                should preserve the current UNIX file permissions when adding\
                files to an installer"

	$p insert end preferences #auto \
            -text "Refresh File List Before Building" \
	    -variable info(AutoRefreshFiles) -editable 0 \
            -values [list Yes No] -helptext "Whether or not InstallJammer\
                should look for new and deleted files in directories added\
                to file groups automatically before building"

	$p insert end preferences #auto -text "Save Only Toplevel Directories" \
	    -variable info(SaveOnlyToplevelDirs) -editable 0 \
            -values [list Yes No] -helptext "Do not recursively save all of the\
                files and subdirectories beneath a directory in a file\
                group.\nOnly save the directories and files that are direct\
                children of the file group."

	$p insert end preferences #auto -text "Skip Unused File Groups" \
	    -variable info(SkipUnusedFileGroups) -editable 0 \
            -values [list Yes No] -helptext "Do not pack file groups that are\
                not included in at least one component."

    return

    ## Build the restore buttons.
    set f [frame $f1.themes]
    pack $f -side bottom -anchor se -pady [list 10 0]

    BUTTON $f.restorewin -text "Restore Windows" -width 18 \
        -command RestoreThemeWindows
    pack $f.restorewin -side left

    BUTTON $f.restore -text "Restore Theme" -width 18 \
        -command [list RestoreTheme -prompt]
    pack $f.restore -side left -padx 5

    BUTTON $f.save -text "Save New Theme" -width 18 \
        -command SaveTheme
    pack $f.save -side left
}

proc Frame.platformInformation {} {
    global conf
    global info
    global widg

    set f [$widg(Product) getframe platformInformation]
    set p $f.sw.p

    ::InstallJammer::SetHelp PlatformInformation

    if {[winfo exists $p]} {
        foreach platform [AllPlatforms] {
            foreach node [$p nodes [PlatformName $platform]] {
                set var [$p itemcget $node -data]
                $p itemconfigure $node -value [$platform get $var]
            }
        }

        return
    }

    ScrolledWindow $f.sw -scrollbar vertical -auto vertical
    PROPERTIES $p
    $f.sw setwidget $p
    pack $f.sw -expand 1 -fill both

    set platforms [ActivePlatforms]
    foreach platform [AllPlatforms] {
	set open 0
	if {[lsearch -exact $platforms $platform] > -1} { set open 1 }

        set cmd [list ::InstallJammer::FinishEditPlatformPropertyNode %W %p %n]

	set node [PlatformName $platform]
	$p insert end root $node -text [PlatformText $platform] \
            -open $open -data $platform

        $p insert end $node #auto -text "Active" \
            -values [list Yes No] -editable 0 -data Active \
            -editfinishcommand $cmd -value [$platform get Active] \
            -helptext "Whether this platform is active for your project"

	$p insert end $node #auto \
	    -text "Default Destination Directory" \
            -valuescommand [list InstallDirList $platform] \
            -data InstallDir -editfinishcommand $cmd \
            -value [$platform get InstallDir] -helptext "The default\
                installation location for this application"

        if {$platform ne "Windows"} {
            $p insert end $node #auto \
                -text "Default Directory Permission Mask" \
                -data DefaultDirectoryPermission -editfinishcommand $cmd \
                -value [$platform get DefaultDirectoryPermission] \
                -helptext "The default permission mask for\
                    directories on a UNIX platform (in octal format)"

            $p insert end $node #auto \
                -text "Default File Permission Mask" \
                -data DefaultFilePermission -editfinishcommand $cmd \
                -value [$platform get DefaultFilePermission] \
                -helptext "The default permission mask for\
                    files on a UNIX platform (in octal format)"
        }

	$p insert end $node #auto -text "Default Install Mode" \
            -values [list Default Silent Standard] \
            -editable 0 -data InstallMode -editfinishcommand $cmd \
            -value [$platform get InstallMode] -helptext "The default install\
                mode when installing this application"

	$p insert end $node #auto -text "Default Program Folder" \
            -data ProgramFolderName -editfinishcommand $cmd \
            -value [$platform get ProgramFolderName] -helptext "The default\
                program folder on Windows to store shortcuts for this\
                application"

	$p insert end $node #auto -text "Default Setup Type" \
            -valuescommand [list ::InstallJammer::GetSetupTypeNames $platform] \
            -editable 0 -data InstallType -editfinishcommand $cmd \
            -value [$platform get InstallType] -helptext "The default setup\
                type when installing this application"

        if {$platform ne "Windows"} {
            $p insert end $node #auto -text "Fall Back to Console Mode" \
                -values [list Yes No] -editable 0 \
                -data FallBackToConsole -editfinishcommand $cmd \
                -value [$platform get FallBackToConsole] \
                -helptext "If a GUI mode is unavailable the installer will\
                    automatically fall back to a console mode to install"
        }

        if {$platform eq "Windows"} {
            $p insert end $node #auto -text "Include Windows API Extension" \
                -values [list Yes No] -editable 0 \
                -data IncludeTWAPI -editfinishcommand $cmd \
                -value [$platform get IncludeTWAPI] \
                -helptext "Whether or not to include the Tcl Windows API\
                    extension in your install (Windows NT 4.0 SP4 or later)"
        }

	$p insert end $node #auto -text "Install Executable Name" \
            -data Executable -editfinishcommand $cmd \
            -value [$platform get Executable] -helptext "The name of your\
                installer when it is built"

        if {$platform eq "Windows"} {
            $p insert end $node #auto \
                -text "Install Program Folder for All Users" \
                -values [list Yes No] -editable 0 \
                -data ProgramFolderAllUsers -editfinishcommand $cmd \
                -value [$platform get ProgramFolderAllUsers] -helptext \
                    "Whether or not to create the Program Folder for all or \
                     the current user by default"
        }

	$p insert end $node #auto \
	    -text "Program Executable" \
            -valuescommand [list InstallDirList $platform] \
            -data ProgramExecutable -editfinishcommand $cmd \
            -value [$platform get ProgramExecutable] -helptext "The path to\
                the main executable for your application on the target system"

	$p insert end $node #auto \
	    -text "Program License" \
            -valuescommand [list InstallDirList $platform] \
            -data ProgramLicense -editfinishcommand $cmd \
            -value [$platform get ProgramLicense] -helptext "The path to your\
                LICENSE file on the target system"

	$p insert end $node #auto \
	    -text "Program Readme" \
            -valuescommand [list InstallDirList $platform] \
            -data ProgramReadme -editfinishcommand $cmd \
            -value [$platform get ProgramReadme] -helptext "The path to your\
                README file on the target system"

        if {$platform ne "Windows"} {
            $p insert end $node #auto -text "Prompt for Root Password" \
                -values [list Yes No] -editable 0 -data PromptForRoot \
                -editfinishcommand $cmd -value [$platform get PromptForRoot] \
                -helptext "If root access is required, InstallJammer will\
                    prompt the user to login as root on startup if they are\
                    not already root"

            $p insert end $node #auto -text "Require Root User" \
                -values [list Yes No] -editable 0 -data RequireRoot \
                -editfinishcommand $cmd -value [$platform get RequireRoot] \
                -helptext "Whether this install requires the root user to\
                    install"

            $p insert end $node #auto \
                -text "Root Destination Directory" \
                -valuescommand [list InstallDirList $platform] \
                -data RootInstallDir -editfinishcommand $cmd \
                -value [$platform get RootInstallDir] -helptext "The\
                    default installation location for this application\
                    when being installed as root.  If this value is empty,\
                    the Default Destination Directory will be used"
        }

        if {$platform eq "Windows"} {
            $p insert end $node #auto -text "Windows File Icon" \
                -browsebutton 1 -browsecommand [list GetIconFile %v] \
                -browseargs {-style Toolbutton} \
                -valuescommand GetIconList \
                -data WindowsIcon -editfinishcommand $cmd \
                -value [$platform get WindowsIcon] -helptext "The Windows\
                    icon to use for building the Windows installer"
        }
    }
}

proc Frame.packageAndArchiveInformation {} {
    global conf
    global info
    global widg

    set f [$widg(Product) getframe packageAndArchiveInformation]
    set p $f.sw.p

    ::InstallJammer::SetHelp PackageAndArchiveInformation

    if {[winfo exists $p]} {
        foreach archive $conf(Archives) {
            foreach node [$p nodes $archive] {
                set var [$p itemcget $node -data]
                $p itemconfigure $node -value [$archive get $var]
            }
        }

        return
    }

    ScrolledWindow $f.sw -scrollbar vertical -auto vertical
    PROPERTIES $p
    $f.sw setwidget $p
    pack $f.sw -expand 1 -fill both

    set cmd [list ::InstallJammer::FinishEditPlatformPropertyNode %W %p %n]

    $p insert end root package -text "Package Information" \
        -helptext "This section defines the information used by the\
                Register Package action if you want to register your\
                application with the local package database.\nIt is\
                highly recommended that you fill in all of the available\
                properties if you plan on registering your package."

        $p insert end package #auto -text "Package Description" \
            -variable info(PackageDescription) -browsebutton 1 \
            -browseargs [list -style Toolbutton] \
            -browsecommand [list ::editor::new \
                -title "Edit Package Description" \
                -variable ::info(PackageDescription)]

        $p insert end package #auto -text "Package License" \
            -variable info(PackageLicense)

        $p insert end package #auto -text "Package Maintainer" \
            -variable info(PackageMaintainer)

        $p insert end package #auto -text "Package Name" \
            -variable info(PackageName)

        $p insert end package #auto -text "Package Packager" \
            -variable info(PackagePackager)

        $p insert end package #auto -text "Package Release" \
            -variable info(PackageRelease)

        $p insert end package #auto -text "Package Summary" \
            -variable info(PackageSummary)

        $p insert end package #auto -text "Package Version" \
            -variable info(PackageVersion)

    set archive TarArchive
    if {[::InstallJammer::ArchiveExists $archive]} {
        $p insert end root $archive -text "Tar Archive Information" \
            -data $archive -editfinishcommand $cmd -open [$archive get Active] \
            -helptext "This section defines the attributes for creating a\
                TAR archive file of your install project."

            $p insert end $archive #auto -text "Active" \
                -values [list Yes No] -editable 0 \
                -data Active -value [$archive get Active] \
                -helptext "Whether this archive is active for your project"

            set levels [list]
            for {set i 0} {$i <= 9} {incr i} { lappend levels $i }
            $p insert end $archive #auto -text "Compression Level" \
                -data CompressionLevel -editable 0 -values $levels \
                -value [$archive get CompressionLevel] \
                -helptext "The level of gzip compression for the tar file.\
                    (0 = no compression, 9 highest compression)"

            $p insert end $archive #auto \
                -text "Default Directory Permission Mask" \
                -data DefaultDirectoryPermission \
                -value [$archive get DefaultDirectoryPermission] \
                -helptext "The default permission mask for directories on\
                    a UNIX platform (in octal format)"

            $p insert end $archive #auto -text "Default File Permission Mask" \
                -data DefaultFilePermission \
                -value [$archive get DefaultFilePermission] \
                -helptext "The default permission mask for files on a\
                    UNIX platform (in octal format)"

            $p insert end $archive #auto -text "Output File Name" \
                -data OutputFileName -value [$archive get OutputFileName] \
                -helptext "The name of the tar file to output to"

            $p insert end $archive #auto -text "Virtual Text Map" \
                -data VirtualTextMap -value [$archive get VirtualTextMap] \
                -helptext "A map of virtual text for filenames being stored in\
                    the tar file"
    }

    set archive ZipArchive
    if {[::InstallJammer::ArchiveExists $archive]} {
        $p insert end root ZipArchive -text "Zip Archive Information" \
            -data ZipArchive -editfinishcommand $cmd -open [$archive get Active]

            $p insert end $archive #auto -text "Active" \
                -values [list Yes No] -editable 0 \
                -data Active -value [$archive get Active] \
                -helptext "Whether this archive is active for your project"

            set levels [list]
            for {set i 1} {$i <= 9} {incr i} { lappend levels $i }
            $p insert end $archive #auto -text "Compression Level" \
                -data CompressionLevel -editable 0 -values $levels \
                -value [$archive get CompressionLevel] \
                -helptext "The level of compression for the zip file.\
                    (1 = lowest compression, 9 highest compression)"

            $p insert end $archive #auto -text "Output File Name" \
                -data OutputFileName -value [$archive get OutputFileName] \
                -helptext "The name of the zip file to output to"

            $p insert end $archive #auto -text "Virtual Text Map" \
                -data VirtualTextMap -value [$archive get VirtualTextMap] \
                -helptext "A map of virtual text for filenames being stored in\
                    the zip file"
    }
}

proc Frame.groupsAndFiles {} {
    global conf
    global widg
    global preferences

    set f1 [$widg(Product) getframe groupsAndFiles]
    set widg(FileGroupsMain) $f1

    ::InstallJammer::SetHelp GroupsAndFiles

    if {[winfo exists $f1.buttons]} {
        set conf(TreeFocus) $widg(FileGroupTree)

        variable ::InstallJammer::ActiveComponents
        if {[info exists ActiveComponents(filegroup)]} {
            ::InstallJammer::SetActiveComponent $ActiveComponents(filegroup)
        }

        return
    }

    set f [frame $f1.buttons]
    pack $f -anchor w

    WinButton $f.b1 -image [GetImage foldernew16] \
    	-command "::FileGroupTree::New"
    set widg(DeleteButton) [WinButton $f.b4 \
	-image [GetImage buttoncancel16] -command "::FileGroupTree::delete"]
    set widg(AddFilesButton) [WinButton $f.b2 \
    	-image [GetImage filedocument16] -command "AddFiles" -state disabled]
    set widg(AddDirButton) [WinButton $f.b3 \
    	-image [GetImage folder16] -command "AddFiles -isdir 1" -state disabled]
    WinButton $f.b5 -image [GetImage filefind16] \
        -command ::FileGroupTree::Explore
    WinButton $f.refresh -image [GetImage actreload16] \
    	-command "::InstallJammer::RefreshFileGroups"
    WinButton $f.filter -image [GetImage viewsidetree16] \
    	-command "Window show .filterFileGroups"

    pack $f.b1 $f.b4 $f.b2 $f.b3 $f.b5 $f.refresh $f.filter -side left

    DynamicHelp::register $f.b1 balloon "Add New File Group"
    DynamicHelp::register $widg(AddFilesButton) balloon \
        "Add Files to File Group"
    DynamicHelp::register $widg(AddDirButton) balloon \
        "Add Directory to File Group"
    DynamicHelp::register $f.b4 balloon "Delete"
    DynamicHelp::register $f.b5 balloon "File Explorer"
    DynamicHelp::add $f.refresh -text "Refresh File Groups"
    DynamicHelp::register $f.filter balloon \
    	"Filter file groups based on patterns"

    set widg(FileGroupPref) $f1.p

    set opts [list]
    if {[info exists preferences(Geometry,FileGroupPref)]} {
        set opts $preferences(Geometry,FileGroupPref)
    }

    eval [list PREFERENCES $widg(FileGroupPref) -treepadx 20 -showlines 1 \
        -deltay 17 -pagewidth 300 -treestretch always -pagestretch never] $opts
    pack $f1.p -expand 1 -fill both

    set widg(FileGroupTree) [$f1.p gettree]

    set tree $widg(FileGroupTree)
    ::FileGroupTree::setup $widg(FileGroupTree)

    set prop [PROPERTIES $f1.properties]
    set widg(FileGroupProperties) $prop
    $prop insert end root filegroup   -text "File Group Properties"
    $prop insert end root dir         -text "Directory Properties"
    $prop insert end root file        -text "File Properties"
    $prop insert end root fileunix    -text "File Permissions"
    $prop insert end root filewindows -text "File Permissions"

    dnd bindtarget $tree.c Files <Drop> "::Tree::DropFiles $tree %D"
    dnd bindtarget $tree.c Files <Drag> "::Tree::DragFiles $tree %x %y"

    ## Create the popup menus.
    set ::FileGroupTree::FilePopup      $f1.filePopup
    set ::FileGroupTree::MultiPopup     $f1.multiPopup
    set ::FileGroupTree::FileGroupPopup $f1.fileGroupPopup
    set ::FileGroupTree::DirectoryPopup $f1.directoryPopup

    set m [POPUP $::FileGroupTree::FilePopup]

    #$m add command -label "Select All" \
    	#-command {::FileTree::SelectAll $widg(FileGroupTree)}
    #$m add separator
    $m add command -label "Check" -underline 0 \
        -compound left -image [GetImage checkfiledocument16] \
    	-command {::FileGroupTree::Check}
    $m add command -label "Uncheck" -underline 0 \
        -compound left -image [GetImage filedocument16] \
    	-command {::FileGroupTree::Uncheck}
    $m add separator
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
    	-command {::FileGroupTree::delete}
    $m add separator
    $m add command -label "Add to Desktop" -underline 0 \
    	-command {::FileGroupTree::AddToDesktop}
    $m add command -label "Add to Program Folder" -underline 0 \
    	-command {::FileGroupTree::AddToProgramFolder}
    #$m add command -label "Add Windows Shortcut" -underline 0 \
    	#-command {::FileGroupTree::AddWindowsShortcut}
    #$m add command -label "Add as Wrapped Script" -underline 0 \
    	#-command {::FileGroupTree::AddWrappedScript}
    #$m add command -label "Add as Wrapped Application" -underline 0 \
    	#-command {::FileGroupTree::AddWrappedApplication}
    $m add separator
    $m add command -label "Explore" -underline 1 \
        -compound left -image [GetImage filefind16] \
        -command ::FileGroupTree::Explore

    set m [POPUP $::FileGroupTree::MultiPopup]

    #$m add command -label "Select All" \
    	#-command {::FileTree::SelectAll $widg(FileGroupTree)}
    #$m add separator
    $m add command -label "Check" -underline 0 \
        -compound left -image [GetImage checkfiledocument16] \
    	-command {::FileGroupTree::Check}
    $m add command -label "Uncheck" -underline 0 \
        -compound left -image [GetImage filedocument16] \
    	-command {::FileGroupTree::Uncheck}
    $m add separator
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
    	-command {::FileGroupTree::delete}

    set m [POPUP $::FileGroupTree::FileGroupPopup]

    $m add command -label "Open" \
        -compound left -image [GetImage folderopen16] \
        -command {
            ::InstallJammer::Tree::OpenSelectedNode $widg(FileGroupTree)
        }
    $m add command -label "Open Recursive" \
        -compound left -image [GetImage folderopen16] \
        -command {
            ::InstallJammer::Tree::OpenSelectedNode $widg(FileGroupTree) 1
        }

    $m add command -label "Close" \
        -compound left -image [GetImage folder16] \
        -command {
            ::InstallJammer::Tree::CloseSelectedNode $widg(FileGroupTree)
        }

    $m add separator

    #$m add command -label "Select All" \
    	#-command {::FileTree::SelectAll $widg(FileGroupTree)}
    #$m add command -label "Select All in this File Group" \
    	#-command {::FileTree::SelectAllBeneath $widg(FileGroupTree)}
    #$m add separator
    $m add command -label "Add Files" -underline 0 \
        -compound left -image [GetImage filedocument16] \
        -command "AddFiles"
    $m add command -label "Add Directory" -underline 0 \
        -compound left -image [GetImage folder16] \
        -command "AddFiles -isdir 1"
    $m add separator
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
    	-command {::FileGroupTree::delete}

    set m [POPUP $::FileGroupTree::DirectoryPopup]

    $m add command -label "Open" \
        -compound left -image [GetImage folderopen16] \
        -command {
            ::InstallJammer::Tree::OpenSelectedNode $widg(FileGroupTree)
        }
    $m add command -label "Open Recursive" \
        -compound left -image [GetImage folderopen16] \
        -command {
            ::InstallJammer::Tree::OpenSelectedNode $widg(FileGroupTree) 1
        }

    $m add command -label "Close" \
        -compound left -image [GetImage folder16] \
        -command {
            ::InstallJammer::Tree::CloseSelectedNode $widg(FileGroupTree)
        }

    $m add separator
    #$m add command -label "Select All" \
    	#-command {::FileTree::SelectAll $widg(FileGroupTree)}
    #$m add separator
    $m add command -label "Check" -underline 0 \
        -compound left -image [GetImage checkfolder16] \
    	-command {::FileGroupTree::Check}
    $m add command -label "Uncheck" -underline 0 \
        -compound left -image [GetImage folder16] \
    	-command {::FileGroupTree::Uncheck}
    $m add separator
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
    	-command {::FileGroupTree::delete}
    $m add separator
    $m add command -label "Explore" -underline 1 \
        -compound left -image [GetImage filefind16] \
        -command ::FileGroupTree::Explore

    ## Create the frame to hold file group details.
    set widg(FileGroupDetails) [ScrolledWindow $f1.details -scrollbar vertical]

    set prop [PROPERTIES $f1.details.prop -width 250]
    set widg(FileGroupDetailsProp) $prop

    $widg(FileGroupDetails) setwidget $widg(FileGroupDetailsProp)

    $prop insert end root standard -text "Standard Properties" -open 1

    ::FileGroupObject addproperties $prop foo

    ## Add a node for file / directory properties.
    $prop insert end root filestandard -text "Standard Properties" -open 1
    ::FileObject addproperties $prop file -standardnode filestandard \
        -array ::FileGroupTree::details

    $prop insert end root dir  -text "Directory Details"
        $prop insert end dir #auto -text "Name" \
            -variable ::FileGroupTree::details(name) -state disabled
        $prop insert end dir #auto -text "Location" \
            -variable ::FileGroupTree::details(location) -state disabled
        $prop insert end dir #auto -text "File Group" \
            -variable ::FileGroupTree::details(fileGroup) -state disabled
        $prop insert end dir #auto -text "File Update Method" \
            -variable ::FileGroupTree::details(fileMethod) -state disabled
        $prop insert end dir #auto -text "Install Location" \
            -variable ::FileGroupTree::details(installLocation) -state disabled
        $prop insert end dir #auto -text "Compression Method" \
            -variable ::FileGroupTree::details(compressionMethod) \
            -state disabled
        $prop insert end dir #auto -text "Version" \
            -variable ::FileGroupTree::details(fileVersion) -state disabled
        $prop insert end dir #auto -text "Created" \
            -variable ::FileGroupTree::details(created) -state disabled
        $prop insert end dir #auto -text "Modified" \
            -variable ::FileGroupTree::details(modified) -state disabled
        $prop insert end dir #auto -text "Accessed" \
            -variable ::FileGroupTree::details(accessed) -state disabled

    $prop insert end root file -text "File Details"
        $prop insert end file #auto -text "Name" \
            -variable ::FileGroupTree::details(name) -state disabled
        $prop insert end file #auto -text "Location" \
            -variable ::FileGroupTree::details(location) -state disabled
        $prop insert end file #auto -text "File Group" \
            -variable ::FileGroupTree::details(fileGroup) -state disabled
        $prop insert end file #auto -text "File Size" \
            -variable ::FileGroupTree::details(fileSize) -state disabled
        $prop insert end file #auto -text "File Update Method" \
            -variable ::FileGroupTree::details(fileMethod) -state disabled
        $prop insert end file #auto -text "Install Location" \
            -variable ::FileGroupTree::details(installLocation) -state disabled
        $prop insert end file #auto -text "Compression Method" \
            -variable ::FileGroupTree::details(compressionMethod) \
            -state disabled
        $prop insert end file #auto -text "Version" \
            -variable ::FileGroupTree::details(fileVersion) -state disabled
        $prop insert end file #auto -text "Created" \
            -variable ::FileGroupTree::details(created) -state disabled
        $prop insert end file #auto -text "Modified" \
            -variable ::FileGroupTree::details(modified) -state disabled
        $prop insert end file #auto -text "Accessed" \
            -variable ::FileGroupTree::details(accessed) -state disabled

    ## Create a property node for multiple file options
    $prop insert end root multiplefiles -text "Standard Properties" -open 1

    AddProperty $prop end multiplefiles multiplefiles Active \
        ::FileGroupTree::details(Active) -type boolean -pretty "Active"
    AddProperty $prop end multiplefiles multiplefiles Destination \
        ::FileGroupTree::details(Destination) -type installedfile \
        -pretty "Destination Directory"
    AddProperty $prop end multiplefiles multiplefiles FileUpdateMethod \
        ::FileGroupTree::details(FileUpdateMethod) -type filemethod \
        -pretty "File Update Method"
    AddProperty $prop end multiplefiles multiplefiles CompressionMethod \
        ::FileGroupTree::details(CompressionMethod) -type choice \
        -pretty "Compression Method" -choices $conf(CompressionMethods)
    AddProperty $prop end multiplefiles multiplefiles Version \
        ::FileGroupTree::details(Version) -type version \
        -pretty "Version"

    ## Create the permissions property node.
    set permf [frame $f1.permissions]
    set widg(FileGroupPermissions) $permf

    labelframe $permf.unix -text "UNIX File Permissions"
    UNIXPermissionsFrame $permf.unix UNIXDetailsPermissions \
        ::FileGroupTree::permissions
    pack $permf.unix -side left -anchor nw -padx 5

    labelframe $permf.windows -text "Windows File Attributes"
    WindowsPermissionsFrame $permf.windows WindowsDetailsPermissions \
        ::FileGroupTree::permissions
    pack $permf.windows -side left -anchor nw -fill y

    ::InstallJammer::AddPlatformPropertyNode $prop ::FileGroupTree::details 1

    $prop insert end root permissions -text "Permissions" -window $permf
}

proc Frame.components {} {
    global conf
    global widg
    global preferences

    set f2 [$widg(Product) getframe components]

    ::InstallJammer::SetHelp Components

    if {[winfo exists $f2.top]} {
        set conf(TreeFocus) $widg(ComponentTree)

        variable ::InstallJammer::ActiveComponents
        if {[info exists ActiveComponents(component)]} {
            ::InstallJammer::SetActiveComponent $ActiveComponents(component)
        }

        return
    }
    
    frame $f2.top
    pack $f2.top -side top -anchor w

    WinButton $f2.top.b1 -image [GetImage foldernew16] \
    	-command ::ComponentTree::New
    pack $f2.top.b1 -side left

    set widg(ComponentDeleteButton) [WinButton $f2.top.b3 \
    	-image [GetImage buttoncancel16] -command "::ComponentTree::delete"]
    pack $f2.top.b3 -side left

    DynamicHelp::register $f2.top.b1 balloon "Add New Component"
    DynamicHelp::register $f2.top.b3 balloon "Delete Component"

    set opts [list]
    if {[info exists preferences(Geometry,ComponentPref)]} {
        set opts $preferences(Geometry,ComponentPref)
    }

    eval [list PREFERENCES $f2.p -treepadx 20 -deltay 19 -showlines 1 \
        -pagewidth 300 -treestretch never -pagestretch always \
        -dropovermode p -dragenabled 1 -dropenabled 1 \
        -dropcmd ::InstallJammer::Tree::DropNode \
        -draginitcmd ::InstallJammer::Tree::DragInit] $opts
    pack $f2.p -expand 1 -fill both

    set widg(ComponentPref) $f2.p
    set widg(ComponentTree) [$f2.p gettree]

    ::ComponentTree::setup $widg(ComponentTree)

    ## Create the Component popup menu.
    set m [POPUP $f2.popup -tearoff 0]
    set ::ComponentTree::popup $m
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
    	-command {::ComponentTree::delete}

    ## Create the frame to hold component details.
    set widg(ComponentDetails) $f2.details

    set f [frame $widg(ComponentDetails)]

    ScrolledWindow $f.sw
    pack $f.sw -expand 1 -fill both -padx [list 0 10] -pady [list 0 5]

    set widg(ComponentFileGroupTree) $f.sw.tree
    OPTIONTREE $widg(ComponentFileGroupTree)
    $f.sw setwidget $widg(ComponentFileGroupTree)

    ScrolledWindow $f.details -scrollbar vertical
    pack $f.details -fill x

    set prop [PROPERTIES $f.details.prop -width 250]
    set widg(ComponentDetailsProp) $prop

    $f.details setwidget $widg(ComponentDetailsProp)

    $prop insert end root standard -text "Standard Properties" -open 1
    ::ComponentObject addproperties $prop foo

    $prop insert end root text -text "Text Properties" -open 0
    ::SetupTypeObject addtextfields $prop text foo

    ::InstallJammer::AddPlatformPropertyNode $prop ::ComponentTree::details
}

proc Frame.setupTypes {} {
    global conf
    global widg
    global preferences

    set f3 [$widg(Product) getframe setupTypes]

    ::InstallJammer::SetHelp SetupTypes

    if {[winfo exists $f3.top]} {
        set conf(TreeFocus) $widg(SetupTypeTree)

        variable ::InstallJammer::ActiveComponents
        if {[info exists ActiveComponents(setuptype)]} {
            ::InstallJammer::SetActiveComponent $ActiveComponents(setuptype)
        }

        return
    }

    frame $f3.top
    pack $f3.top -side top -anchor w

    WinButton $f3.top.b1 -image [GetImage foldernew16] \
    	-command ::SetupTypeTree::New
    pack $f3.top.b1 -side left

    set widg(SetupTypeDeleteButton) [WinButton $f3.top.b3 \
    	-image [GetImage buttoncancel16] -command "::SetupTypeTree::delete"]
    pack $f3.top.b3 -side left

    DynamicHelp::add $f3.top.b1 -text "Add New Setup Type"
    DynamicHelp::add $f3.top.b3 -text "Delete Setup Type"

    set opts [list]
    if {[info exists preferences(Geometry,SetupTypePref)]} {
        set opts $preferences(Geometry,SetupTypePref)
    }

    eval [list PREFERENCES $f3.p -treepadx 20 -showlines 0 -deltax 0 \
        -deltay 18 -pagewidth 300 -treestretch never -pagestretch always \
        -dropovermode p -dragenabled 1 -dropenabled 1 \
        -dropcmd ::InstallJammer::Tree::DropNode \
        -draginitcmd ::InstallJammer::Tree::DragInit] $opts
    pack $f3.p -expand 1 -fill both

    set widg(SetupTypePref) $f3.p
    set widg(SetupTypeTree) [$f3.p gettree]

    ::SetupTypeTree::setup $widg(SetupTypeTree)

    ## Create the Setup Type popup menu.
    set m [POPUP $f3.popup -tearoff 0]
    set ::SetupTypeTree::popup $m
    $m add command -label "Delete" -underline 0 \
    	-compound left -image [GetImage buttoncancel16] \
        -command {::SetupTypeTree::delete}

    set widg(SetupTypeDetails) $f3.details

    set f [frame $widg(SetupTypeDetails)]

    ScrolledWindow $f.sw
    pack $f.sw -expand 1 -fill both -padx [list 0 10] -pady [list 0 5]

    set widg(SetupTypeComponentTree) $f.sw.tree
    OPTIONTREE $widg(SetupTypeComponentTree)
    $f.sw setwidget $widg(SetupTypeComponentTree)

    ## Create the frame to hold setup type details.
    ScrolledWindow $f.details -scrollbar vertical
    pack $f.details -fill x

    set prop [PROPERTIES $f.details.prop -expand 1 -width 250]
    set widg(SetupTypeDetailsProp) $prop

    $f.details setwidget $widg(SetupTypeDetailsProp)

    $prop insert end root standard -text "Standard Properties" -open 1

    ::SetupTypeObject addproperties $prop foo

    $prop insert end root text -text "Text Properties" -open 0
    ::SetupTypeObject addtextfields $prop text foo

    ::InstallJammer::AddPlatformPropertyNode $prop ::SetupTypeTree::details
}

proc Frame.install {} {
    global conf
    global widg
    global preferences

    set widg(Install) [$widg(Product) getframe install].p

    ::InstallJammer::SetHelp PanesAndActions

    if {[winfo exists $widg(Install)]} {
        set conf(TreeFocus) $widg(InstallTree)

        variable ::InstallJammer::ActiveComponents
        if {[info exists ActiveComponents(Install)]} {
            ::InstallJammer::SetActiveComponent $ActiveComponents(Install)
        }

        return
    }

    set opts [list]
    if {[info exists preferences(Geometry,Install)]} {
        set opts $preferences(Geometry,Install)
    }

    set main $widg(Install)

    eval [list PREFERENCES $widg(Install) \
        -showlines 0 -treewidth 215 -treepadx 20 -deltay 18 \
        -dropovermode p -dragenabled 1 -dropenabled 1 \
        -dropcmd ::InstallJammer::Tree::DropNode \
        -draginitcmd ::InstallJammer::Tree::DragInit] $opts
    pack $main -expand 1 -fill both -side bottom

    set tree [$widg(Install) gettree]
    set widg(InstallTree) $tree

    set p [winfo parent $widg(Install)]
    set f [frame $p.f1]
    set widg(InstallButtons) $f
    pack $f -anchor nw

    WinMenuButton $f.addPane -image [GetImage displayscreen16] \
        -menu $f.addPane.panes
    pack $f.addPane -side left -padx 2
    DynamicHelp::add $f.addPane -text "Insert Install Pane"

    ## Create the menu for the install panes, but they won't
    ## get added until a project is loaded.
    set m [MENU $f.addPane.panes]
    set widg(InstallPanesMenu) $m

    WinMenuButton $f.addAction -image [GetImage insertaction16] \
        -menu $f.addAction.actions
    pack $f.addAction -side left -padx 2
    DynamicHelp::add $f.addAction -text "Insert Action"

    set m [MENU $f.addAction.actions]
    set widg(InstallActionsMenu) $m

    $m insert end cascade -label "All Actions" -menu $m.all
    MENU $m.all

    foreach group [lsort [array names ::InstallJammer::actiongroups]] {
        set submenu [MENU $m.[WidgetName $group]]
        $m insert end cascade -label "$group   " -menu $submenu

        foreach id $::InstallJammer::actiongroups($group) {
            set allactions([$id title]) $id
            lappend actions($submenu) [$id title]
        }
    }

    foreach submenu [array names actions] {
        foreach title [lsort $actions($submenu)] {
            set id $allactions($title)
            $submenu add command -label $title \
                -command [list ::InstallJammer::AddAction Install [$id action]]
        }
    }

    foreach title [lsort [array names allactions]] {
        set id $allactions($title)
        $m.all add command -label $title \
            -command [list ::InstallJammer::AddAction Install [$id action]]
    }

    WinButton $f.addActionGroup -image [GetImage appwindow_list16] \
        -command [list ::InstallJammer::AddActionGroup Install]
    pack $f.addActionGroup -side left -padx 2
    DynamicHelp::add $f.addActionGroup -text "New Action Group"

    WinButton $f.delete -image [GetImage buttoncancel16] \
        -command [list ::InstallJammer::Tree::Delete $widg(Install)]
    pack $f.delete -side left -padx 2
    DynamicHelp::add $f.delete -text "Delete"

    set args [list -deltax 5 -padx 10 -haspage 0]
    eval $main insert end root CommonInstall -data installtype \
        [list -text "Common Components" -font TkCaptionFont] $args
    eval $main insert end root StandardInstall -data installtype \
        [list -text "Standard Install" -font TkCaptionFont] $args
    eval $main insert end root DefaultInstall -data installtype \
        [list -text "Default Install" -font TkCaptionFont] $args
    eval $main insert end root ConsoleInstall -data installtype \
        [list -text "Console Install" -font TkCaptionFont] $args
    eval $main insert end root SilentInstall -data installtype \
        [list -text "Silent Install" -font TkCaptionFont] $args
    eval $main insert end root ActionGroupsInstall -data installtype \
        [list -text "Action Groups" -font TkCaptionFont] $args

    ::InstallJammer::Tree::Setup Install $tree
}

proc Frame.uninstall {} {
    global conf
    global widg
    global preferences

    set widg(Uninstall) [$widg(Product) getframe uninstall].p

    ::InstallJammer::SetHelp PanesAndActions

    if {[winfo exists $widg(Uninstall)]} {
        set conf(TreeFocus) $widg(UninstallTree)

        variable ::InstallJammer::ActiveComponents
        if {[info exists ActiveComponents(Uninstall)]} {
            ::InstallJammer::SetActiveComponent $ActiveComponents(Uninstall)
        }

        return
    }

    set opts [list]
    if {[info exists preferences(Geometry,Uninstall)]} {
        set opts $preferences(Geometry,Uninstall)
    }

    set main $widg(Uninstall)
    eval [list PREFERENCES $widg(Uninstall) \
        -showlines 0 -treewidth 215 -treepadx 20 -deltay 18 \
        -dropovermode p -dragenabled 1 -dropenabled 1 \
        -dropcmd ::InstallJammer::Tree::DropNode \
        -draginitcmd ::InstallJammer::Tree::DragInit] $opts
    pack $main -expand 1 -fill both -side bottom

    set tree [$widg(Uninstall) gettree]
    set widg(UninstallTree) $tree

    set p [winfo parent $widg(Uninstall)]
    set f [frame $p.f1]
    set widg(UninstallButtons) $f
    pack $f -anchor nw

    WinMenuButton $f.addPane -image [GetImage displayscreen16] \
        -menu $f.addPane.panes
    pack $f.addPane -side left -padx 2
    DynamicHelp::add $f.addPane -text "Insert Uninstall Pane"

    set m [MENU $f.addPane.panes]
    set widg(UninstallPanesMenu) $m

    WinMenuButton $f.addAction -image [GetImage insertaction16] \
        -menu $f.addAction.actions
    pack $f.addAction -side left -padx 2
    DynamicHelp::add $f.addAction -text "Insert Action"

    set m [MENU $f.addAction.actions]
    set widg(UninstallActionsMenu) $m

    $m insert end cascade -label "All Actions" -menu $m.all
    MENU $m.all

    foreach group [lsort [array names ::InstallJammer::actiongroups]] {
        set submenu [MENU $m.[WidgetName $group]]
        $m insert end cascade -label "$group   " -menu $submenu

        foreach id $::InstallJammer::actiongroups($group) {
            set action [$id action]
            set allactions($action) $id
            $submenu add command -label [$id title] \
                -command [list ::InstallJammer::AddAction Uninstall $action]
        }
    }

    foreach action [lsort [array names allactions]] {
        set id $allactions($action)
        $m.all add command -label [$id title] \
            -command [list ::InstallJammer::AddAction Uninstall $action]
    }

    WinButton $f.addActionGroup -image [GetImage appwindow_list16] \
        -command [list ::InstallJammer::AddActionGroup Uninstall]
    pack $f.addActionGroup -side left -padx 2
    DynamicHelp::add $f.addActionGroup -text "New Action Group"

    WinButton $f.delete -image [GetImage buttoncancel16] \
        -command [list ::InstallJammer::Tree::Delete $widg(Uninstall)]
    pack $f.delete -side left -padx 2
    DynamicHelp::add $f.delete -text "Delete"

    set args [list -deltax 5 -padx 10 -haspage 0]
    eval $main insert end root CommonUninstall -data installtype \
        [list -text "Common Components" -font TkCaptionFont] $args
    eval $main insert end root StandardUninstall -data installtype \
        [list -text "Standard Uninstall" -font TkCaptionFont] $args
    eval $main insert end root ConsoleUninstall -data installtype \
        [list -text "Console Uninstall" -font TkCaptionFont] $args
    eval $main insert end root SilentUninstall -data installtype \
        [list -text "Silent Uninstall" -font TkCaptionFont] $args
    eval $main insert end root ActionGroupsUninstall -data installtype \
        [list -text "Action Groups" -font TkCaptionFont] $args

    ::InstallJammer::Tree::Setup Uninstall $tree
}

proc Frame.commandLine { setup } {
    global conf
    global widg

    set top [$widg(Product) getframe ${setup}CommandLine]

    ::InstallJammer::SetHelp CommandLineOptions

    if {[winfo exists $top.buttons]} {
        focus $top.sw.table
        return
    }

    set f [frame $top.buttons]
    pack $f -anchor w

    ScrolledWindow $top.sw
    pack $top.sw -expand 1 -fill both -padx 5

    set l [TableList $top.sw.table -cols 7 -bd 1 -relief ridge \
        -background #FFFFFF -selectmode extended -keycolumn 0 \
        -editstartcommand  "::InstallJammer::EditStartCommandLine  %W %i %c" \
        -editfinishcommand "::InstallJammer::EditFinishCommandLine %W %i %c"]

    $top.sw setwidget $l
    set widg(${setup}CommandLineOptionsTable) $l

    $l column configure 0 -title "Option" -width 15
    $l column configure 1 -title "Virtual Text" -width 15
    $l column configure 2 -title "Type" -width 8 \
        -editable 0 -values [list "Boolean" "Choice" "Prefix" "String" "Switch"]
    $l column configure 3 -title "Debug" -width 6 \
        -editable 0 -values [list Yes No]
    $l column configure 4 -title "Hide" -width 6 \
        -editable 0 -values [list Yes No]
    $l column configure 5 -title "Value(s)" -width 25 \
        -browsebutton 1 -browseargs [list -style Toolbutton] \
        -browsecommand "::InstallJammer::EditCommandLineOptionChoices %W %i"
    $l column configure 6 -title "Description" \
        -browsebutton 1 -browseargs [list -style Toolbutton] \
        -browsecommand "::InstallJammer::EditCommandLineOptionDescription %W %i"

    WinButton $f.add -image [GetImage filenew16] \
    	-command [list ::InstallJammer::NewCommandLineOption $l]
    pack $f.add -side left
    DynamicHelp::add $f.add -text "Add New Command Line Option"

    WinButton $f.delete -image [GetImage editdelete16] \
    	-command [list ::InstallJammer::DeleteCommandLineOption $l]
    pack $f.delete -side left
    DynamicHelp::add $f.delete -text "Delete Command Line Option"
}

proc Frame.virtualText {} {
    global conf
    global widg

    set top [$widg(Product) getframe virtualText]

    ::InstallJammer::SetHelp VirtualText

    if {[winfo exists $top.buttons]} {
        focus $top.listframe.listbox
        return
    }

    set f [frame $top.buttons]
    pack $f -anchor w

    ScrolledWindow $top.listframe
    pack $top.listframe -expand 1 -fill both -padx 5

    set l [TableList $top.listframe.listbox -cols 2 -bd 1 -relief ridge \
        -background #FFFFFF -selectmode extended -keycolumn 0 \
        -editstartcommand  "::InstallJammer::EditStartVirtualText  %W %i %c" \
        -editfinishcommand "::InstallJammer::EditFinishVirtualText %W %i %c"]

    $top.listframe setwidget $l
    set widg(VirtualTextTable) $l

    $l column configure 0 -title "Text" -width 25
    $l column configure 1 -title "Value" \
        -browsebutton 1 -browseargs [list -style Toolbutton] \
        -browsecommand "::InstallJammer::LongEditVirtualText %W %i"

    WinButton $f.add -image [GetImage filenew16] \
    	-command "::InstallJammer::NewVirtualText $l"
    pack $f.add -side left
    DynamicHelp::add $f.add -text "Add New Virtual Text"

    WinButton $f.delete -image [GetImage editdelete16] \
    	-command "::InstallJammer::DeleteVirtualText $l"
    pack $f.delete -side left
    DynamicHelp::add $f.delete -text "Delete Virtual Text"

    ttk::label $f.langL -text "Language"
    pack $f.langL -side left -padx [list 20 2]

    ttk::combobox $f.lang -state readonly \
        -textvariable ::conf(VirtualTextLanguage) \
        -values [::InstallJammer::GetLanguages 1]
    pack $f.lang -side left -padx [list 0 20]

    bind $f.lang <<ComboboxSelected>> \
        "::InstallJammer::LoadVirtualText;after idle [list focus $l]"
}

proc Frame.diskBuilder {} {
    global conf
    global widg

    set top [$widg(Product) getframe diskBuilder]

    ::InstallJammer::SetHelp DiskBuilder

    if {[winfo exists $top.label]} {
        ## If this is the first time the user is seeing the
        ## build log, scroll to the bottom incase there's
        ## already log data in it.
        if {![info exists conf($widg(BuildLog),realized)]} {
            $widg(BuildLog) see end
            set conf($widg(BuildLog),realized) 1
        }

        return
    }

    grid rowconfigure    $top 1 -weight 1
    grid columnconfigure $top 1 -weight 1

    label $top.label -text "Platforms to Build:"
    grid  $top.label -row 0 -column 0 -sticky ws

    set f [frame $top.progressF]
    grid $f -row 0 -column 1 -sticky ew -padx 10
    grid columnconfigure $f 1 -weight 1

    label $f.l1 -text "Build Progress:"
    grid  $f.l1 -row 0 -column 0 -sticky w

    PROGRESSBAR $f.progress -variable ::conf(buildProgress)
    set widg(ProgressBuild) $f.progress
    grid $f.progress -row 0 -column 1 -sticky ew

    label $f.l2 -text "Platform Progress:"
    grid  $f.l2 -row 1 -column 0 -sticky w

    PROGRESSBAR $f.fileProgress -variable ::conf(buildPlatformProgress)
    set widg(ProgressBuildPlatform) $f.fileProgress
    grid $f.fileProgress -row 1 -column 1 -sticky ew

    ScrolledWindow $top.sw1
    grid $top.sw1 -row 1 -column 0 -sticky ns -pady [list 5 10]

    set t [OPTIONTREE $top.buildTree -width 16 -highlightthickness 0]
    $top.sw1 setwidget $t

    set widg(BuildTree) $t

    ScrolledWindow $top.sw2 -auto none
    grid $top.sw2 -row 1 -column 1 -sticky news -padx 10 -pady [list 5 2]

    set widg(BuildLog) [Text $top.log -wrap none -state readonly -height 1]
    $top.sw2 setwidget $top.log

    CHECKBUTTON $top.buildRelease -text "Build for final release" \
        -variable ::conf(buildForRelease)
    grid $top.buildRelease -row 2 -column 1 -sticky w -padx 10
    DynamicHelp::add $top.buildRelease -text "Build installers without \
        debugging options and with options optimized for final release"

    $widg(BuildLog) tag configure error -foreground red

    $widg(BuildLog) tag configure link -foreground blue -underline 1
    $widg(BuildLog) tag bind link <Enter> [list %W configure -cursor hand2]
    $widg(BuildLog) tag bind link <Leave> [list %W configure -cursor ""]
    $widg(BuildLog) tag bind link <1> {
        ::InstallJammer::Explore [InstallDir output]
    }

    set f [frame $top.buttons]
    grid $top.buttons -row 3 -column 1 -sticky e -padx 10

    BUTTON $f.clear -text "Clear Build Log" -width 14 \
        -image [GetImage editshred16] -compound left \
        -command ::InstallJammer::ClearBuildLog
    pack $f.clear -side left -padx 5

    BUTTON $f.build -text "Build Install" -width 14 -command Build \
        -image [GetImage build16] -compound left
    pack   $f.build -side left
}

proc Frame.testInstaller {} {
    global conf
    global widg

    set top [$widg(Product) getframe testInstaller]

    ::InstallJammer::SetHelp TestRun

    if {[winfo exists $top.l1]} { return }

    label $top.l1 -text "Select the options to use on the command-line:"
    pack  $top.l1 -anchor w -pady 5

    label $top.l2 -text "Command-Line:"
    pack  $top.l2 -anchor w

    ENTRY $top.e1 -textvariable ::conf(TestCommandLineOptions)
    pack  $top.e1 -anchor w -fill x
    bind  $top.e1 <Return> TestInstall

    label $top.l3 -text "Test Options:"
    pack  $top.l3 -anchor w -pady 5

    OPTIONTREE $top.options -highlightthickness 0
    pack $top.options -expand 1 -fill both

    bind $top.options <<TreeModify>> AdjustTestInstallOptions

    $top.options insert end root #auto -type checkbutton \
        -text "Save temporary directory for debugging" \
        -variable ::conf(SaveTempDir)

    $top.options insert end root #auto -type checkbutton \
        -text "Test in default mode" \
        -variable ::conf(TestAllDefaults)

    if {!$conf(windows)} {
        $top.options insert end root #auto -type checkbutton \
            -text "Test in console mode" \
            -variable ::conf(TestConsole)
    }

    $top.options insert end root #auto -type checkbutton \
        -text "Test in silent mode" \
        -variable ::conf(TestSilent)

    $top.options insert end root #auto -type checkbutton \
        -text "Test install without installing files" \
        -variable ::conf(TestWithoutFiles)

    $top.options insert end root #auto -type checkbutton \
        -text "Test install with an open console window" \
        -variable ::conf(TestWithConsole)

    BUTTON $top.test -text "Test Install" -width 14 -command "TestInstall" \
        -image [GetImage actrun16] -compound left
    pack   $top.test -side bottom -anchor se -padx 5 -pady [list 10 0]

    bind $top <Alt-s> "focus $top.c2"
    bind $top <Alt-t> "focus $top.c1"
    bind $top <Alt-c> "focus $top.c3"
}

proc Frame.testUninstaller {} {
    global conf
    global widg

    set top [$widg(Product) getframe testUninstaller]

    ::InstallJammer::SetHelp TestUninstaller

    if {[winfo exists $top.l1]} { return }

    label $top.l1 -text "Select the options to use on the command-line:"
    pack  $top.l1 -anchor w -pady 5

    label $top.l2 -text "Command-Line:"
    pack  $top.l2 -anchor w

    ENTRY $top.e1 -textvariable ::conf(TestUninstallCommandLineOptions)
    pack  $top.e1 -anchor w -fill x
    bind  $top.e1 <Return> TestUninstall

    label $top.l3 -text "Test Options:"
    pack  $top.l3 -anchor w -pady 5

    OPTIONTREE $top.options -highlightthickness 0
    pack $top.options -expand 1 -fill both

    bind $top.options <<TreeModify>> AdjustTestUninstallOptions

    if {!$conf(windows)} {
        $top.options insert end root #auto -type checkbutton \
            -text "Test in console mode" \
            -variable ::conf(TestUninstallConsoleMode)
    }

    $top.options insert end root #auto -type checkbutton \
        -text "Test in silent mode" \
        -variable ::conf(TestUninstallSilentMode)

    $top.options insert end root #auto -type checkbutton \
        -text "Test uninstall without uninstalling files" \
        -variable ::conf(TestUninstallWithoutFiles)

    $top.options insert end root #auto -type checkbutton \
        -text "Test uninstall with an open console window" \
        -variable ::conf(TestUninstallWithConsole)

    BUTTON $top.test -text "Test Uninstall" -width 14 \
        -command "TestUninstall" -image [GetImage edittrash16] -compound left
    pack   $top.test -side bottom -anchor se -padx 5 -pady [list 10 0]
}

proc WindowsPermissionsFrame { f tag arrayName } {
    set row -1

    incr row

    CHECKBUTTON $f.c1 -text "Archive" -variable ${arrayName}(PermArchive) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c1 -row $row -column 0 -sticky w

    CHECKBUTTON $f.c2 -text "Hidden" -variable ${arrayName}(PermHidden) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c2 -row $row -column 1 -sticky w

    CHECKBUTTON $f.c3 -text "Readonly" -variable ${arrayName}(PermReadonly) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c3 -row [incr row] -column 0 -sticky w

    CHECKBUTTON $f.c4 -text "System" -variable ${arrayName}(PermSystem) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c4 -row $row -column 1 -sticky w

    tag addtag $tag class Checkbutton class TCheckbutton children $f

    CHECKBUTTON $f.c -text "Use default attributes" \
    	-variable ${arrayName}(UseWindowsDefaultPermissions) \
    	-command "
    	    if {\$${arrayName}(UseWindowsDefaultPermissions)} {
		tag configure $tag -state disabled
	    } else {
		tag configure $tag -state normal
	    }
            ::FileGroupTree::SetPermissions $arrayName
	"

    grid $f.c -row [incr row] -column 0 -columnspan 2 -sticky w
}

proc UNIXPermissionsFrame { f tag arrayName } {
    set row -1

    set f [frame $f.unix]
    grid $f -row [incr row] -column 0 -columnspan 2 -sticky w

    incr row
    grid [label $f.exec  -text Exec]  -row $row -column 1
    grid [label $f.write -text Write] -row $row -column 2
    grid [label $f.read  -text Read]  -row $row -column 3

    grid [label $f.user  -text User]  -row [incr row] -column 0 -sticky w

    CHECKBUTTON $f.c3 -variable ${arrayName}(PermUserExecute) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c3 -row $row -column 1
    CHECKBUTTON $f.c2 -variable ${arrayName}(PermUserWrite) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c2 -row $row -column 2
    CHECKBUTTON $f.c1 -variable ${arrayName}(PermUserRead) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c1 -row $row -column 3

    grid [label $f.group -text Group] -row [incr row] -column 0 -sticky w

    CHECKBUTTON $f.c6 -variable ${arrayName}(PermGroupExecute) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c6 -row $row -column 1
    CHECKBUTTON $f.c5 -variable ${arrayName}(PermGroupWrite) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c5 -row $row -column 2
    CHECKBUTTON $f.c4 -variable ${arrayName}(PermGroupRead) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c4 -row $row -column 3

    grid [label $f.other -text Other] -row [incr row] -column 0 -sticky w

    CHECKBUTTON $f.c9 -variable ${arrayName}(PermOtherExecute) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c9 -row $row -column 1
    CHECKBUTTON $f.c8 -variable ${arrayName}(PermOtherWrite) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c8 -row $row -column 2
    CHECKBUTTON $f.c7 -variable ${arrayName}(PermOtherRead) \
        -command [list ::FileGroupTree::SetPermissions $arrayName]
    grid $f.c7 -row $row -column 3

    tag addtag $tag class Checkbutton class TCheckbutton children $f

    CHECKBUTTON $f.c -text "Use default permissions" \
    	-variable ${arrayName}(UseUNIXDefaultPermissions) \
    	-command "
    	    if {\$${arrayName}(UseUNIXDefaultPermissions)} {
		tag configure $tag -state disabled
	    } else {
		tag configure $tag -state normal
	    }

            ::FileGroupTree::SetPermissions $arrayName
	"

    grid $f.c -row [incr row] -column 0 -columnspan 4 -sticky w
}

proc Window.preferences {} {
    global widg

    set top $widg(InstallJammer).preferences

    ::InstallJammer::SetHelp InstallBuilderPreferences

    array set ::tmppreferences [array get ::preferences]

    if {[winfo exists $top]} {
	wm deiconify $top
	return
    }

    toplevel     $top
    wm withdraw  $top
    update idletasks
    wm title     $top "InstallJammer Preferences"
    wm geometry  $top 450x400
    wm protocol  $top WM_DELETE_WINDOW "CancelPreferences"
    wm transient $top $widg(InstallJammer)
    BWidget::place $top 450 400 center $widg(InstallJammer)

    bind $top <Return> "SetPreferences"
    bind $top <Escape> "CancelPreferences"

    grid rowconfigure    $top 2 -weight 1
    grid columnconfigure $top 0 -weight 1

    Buttons $top -okcmd "SetPreferences" -cancelcmd "CancelPreferences" \
    	-helpcmd "Help InstallBuilderPreferences" -pack 0

    grid $top.bbox -row 0 -column 0 -sticky e
    grid [Separator $top.bboxsp1] -row 1 -column 0 -sticky ew

    ttk::notebook $top.n
    grid $top.n -row 2 -column 0 -sticky news -pady 10

    ttk::frame $top.n.dirs
    $top.n add $top.n.dirs -text "Directories"

    ttk::frame $top.n.programs
    $top.n add $top.n.programs -text "External Programs"

    ttk::frame $top.n.update
    #$top.n add $top.n.update -text "InstallJammer Update"

    $top.n select $top.n.dirs

    ## Project Directory
    set f $top.n.dirs.f
    pack [frame $f] -anchor nw -fill x -padx 5 -pady {5 0}
    
    grid columnconfigure $f 0 -weight 1

    label $f.projectDirL -text "Project Directory Location"
    grid  $f.projectDirL -row 0 -column 0 -sticky w -padx 5

    ENTRY $f.projectDirE -width 50 -textvariable ::tmppreferences(ProjectDir)
    grid  $f.projectDirE -row 1 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.projectDirB -command \
        [list GetDir ::tmppreferences(ProjectDir) -parent $top]
    grid  $f.projectDirB -row 1 -column 1

    ## Custom Theme Dir
    set f $top.n.dirs.f2
    pack [frame $f] -anchor nw -fill x -padx 5
    
    grid columnconfigure $f 0 -weight 1

    label $f.projectDirL -text "Custom Theme Directory Location"
    grid  $f.projectDirL -row 0 -column 0 -sticky w -padx 5

    ENTRY $f.projectDirE -width 50 \
        -textvariable ::tmppreferences(CustomThemeDir)
    grid  $f.projectDirE -row 1 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.projectDirB -command \
        [list GetDir ::tmppreferences(CustomThemeDir) -parent $top]
    grid  $f.projectDirB -row 1 -column 1

    ## Custom Action Dir
    set f $top.n.dirs.f3
    pack [frame $f] -anchor nw -fill x -padx 5
    
    grid columnconfigure $f 0 -weight 1

    label $f.projectDirL -text "Custom Action Directory Location"
    grid  $f.projectDirL -row 0 -column 0 -sticky w -padx 5

    ENTRY $f.projectDirE -width 50 \
        -textvariable ::tmppreferences(CustomActionDir)
    grid  $f.projectDirE -row 1 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.projectDirB -command \
        [list GetDir ::tmppreferences(CustomActionDir) -parent $top]
    grid  $f.projectDirB -row 1 -column 1

    ## Custom Condition Dir
    set f $top.n.dirs.f4
    pack [frame $f] -anchor nw -fill x -padx 5 -pady {0 5}
    
    grid columnconfigure $f 0 -weight 1

    label $f.projectDirL -text "Custom Condition Directory Location"
    grid  $f.projectDirL -row 0 -column 0 -sticky w -padx 5

    ENTRY $f.projectDirE -width 50 \
        -textvariable ::tmppreferences(CustomConditionDir)
    grid  $f.projectDirE -row 1 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.projectDirB -command \
        [list GetDir ::tmppreferences(CustomConditionDir) -parent $top]
    grid  $f.projectDirB -row 1 -column 1


    ## Create the External Programs tab.

    set f $top.n.programs.f
    pack [frame $f] -anchor nw -expand 1 -fill x -padx 5 -pady 5
    
    grid columnconfigure $f 0 -weight 1

    label $f.l2 -text "File Explorer"
    grid  $f.l2 -row 2 -column 0 -sticky w -padx 5

    ENTRY $f.e2 -width 50 -textvariable ::tmppreferences(FileExplorer)
    grid  $f.e2 -row 3 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.b2 -command \
        [list GetFile ::tmppreferences(FileExplorer) -parent $top]
    grid  $f.b2 -row 3 -column 1

    label $f.l3 -text "Help Browser" -padx 5
    grid  $f.l3 -row 4 -column 0 -sticky w

    set browsers [::InstallJammer::HelpBrowsers]

    ttk::combobox $f.e3 -width 50 -textvariable ::tmppreferences(HelpBrowser) \
    	-values $browsers
    grid  $f.e3 -row 5 -column 0 -sticky ew -padx [list 5 0]

    BrowseButton $f.b3 -command \
        [list GetFile ::tmppreferences(HelpBrowser) -parent $top]
    grid  $f.b3 -row 5 -column 1


    ## Create the InstallJammer Update tab.

    set f $top.n.update.f
    pack [frame $f] -anchor nw -expand 1 -fill x -padx 5 -pady 5
    
    grid columnconfigure $f 0 -weight 1

    ttk::checkbutton $f.check \
        -text "Check for updates to InstallJammer on startup" \
        -variable ::tmppreferences(CheckForUpdates)
    grid $f.check -row 0 -column 0 -sticky nw -pady 2

    ttk::checkbutton $f.useProxy \
        -text "Use a proxy server" \
        -variable ::tmppreferences(UseProxyServer) \
        -command {tag configure proxy -state \
        [expr {$::tmppreferences(UseProxyServer) ? "normal" : "disabled"}]}
    grid $f.useProxy -row 1 -column 0 -columnspan 2 -sticky nw -pady {10 2}

    ttk::label $f.proxyHostL -text "Proxy Host"
    grid $f.proxyHostL -row 2 -column 0 -padx 20 -pady {2 0} -sticky nw
    tag add proxy $f.proxyHostL

    ttk::entry $f.proxyHost -textvariable ::tmppreferences(ProxyHost)
    grid $f.proxyHost -row 3 -column 0 -padx 20 -sticky ew
    tag add proxy $f.proxyHost

    ttk::label $f.proxyPortL -text "Proxy Port"
    grid $f.proxyPortL -row 4 -column 0 -padx 20 -pady {2 0} -sticky nw
    tag add proxy $f.proxyPortL

    ttk::entry $f.proxyPort -textvariable ::tmppreferences(ProxyPort)
    grid $f.proxyPort -row 5 -column 0 -padx 20 -sticky ew
    tag add proxy $f.proxyPort

    $f.useProxy invoke
    $f.useProxy invoke

    ttk::button $top.n.update.checkNow -text "Check for Updates Now" \
        -padding {4 2} -command {::InstallJammer::DownloadVersionInfo 1}
    pack $top.n.update.checkNow -anchor se -padx 5 -pady 5


    wm deiconify $top
}

proc Window.filterFileGroups {} {
    global widg

    set top  .__filterFileGroups
    set tree $widg(FileGroupTree)

    set parent $widg(InstallJammer)

    ClearTmpVars

    set ::TMPARRAY(regexp)    0
    set ::TMPARRAY(include)   include
    set ::TMPARRAY(filterall) 1
    set ::TMPARRAY(recursive) 1
    set ::TMPARRAY(includePatterns) [list]
    set ::TMPARRAY(excludePatterns) [list]

    set selection [$tree selection get]
    if {![lempty $selection]} { set ::TMPARRAY(filterall) 0 }

    toplevel     $top
    wm withdraw  $top
    update idletasks
    wm transient $top $parent
    wm geometry  $top 300x260
    wm title     $top "Filter File Groups"
    wm protocol  $top WM_DELETE_WINDOW "set ::TMP 0"
    CenterWindow $top

    bind $top <Escape> "set ::TMP 0"
    bind $top <Return> "set ::TMP 1"

    Buttons $top -okcmd "set ::TMP 1" -cancelcmd "set ::TMP 0" \
    	-helpcmd "Help FilterFileGroups"

    label $top.l1 -text "Include File Patterns:"
    pack  $top.l1 -anchor w

    ENTRY $top.e1 -textvariable ::TMPARRAY(includePatterns)
    pack  $top.e1 -anchor w -fill x

    focus $top.e1

    label $top.l2 -text "Exclude File Patterns:"
    pack  $top.l2 -anchor w

    ENTRY $top.e2 -textvariable ::TMPARRAY(excludePatterns)
    pack  $top.e2 -anchor w -fill x

    CHECKBUTTON $top.c1 -text "Recursively Check File Groups" \
    	-variable ::TMPARRAY(recursive)
    pack $top.c1 -anchor w

    CHECKBUTTON $top.c2 -text "Use Regular Expression Matching" \
    	-variable ::TMPARRAY(regexp)
    pack $top.c2 -anchor w -pady [list 0 5]

    RADIOBUTTON $top.r4 -text "Filter selected file groups" \
    	-variable ::TMPARRAY(filterall) -value 0
    pack $top.r4 -anchor w

    RADIOBUTTON $top.r3 -text "Filter all file groups" \
    	-variable ::TMPARRAY(filterall) -value 1
    pack $top.r3 -anchor w -pady [list 0 5]

    RADIOBUTTON $top.r1 -text "Include files that match both" \
    	-variable ::TMPARRAY(include) -value include
    pack $top.r1 -anchor w

    RADIOBUTTON $top.r2 -text "Exclude files that match both" \
    	-variable ::TMPARRAY(include) -value exclude
    pack $top.r2 -anchor w

    wm deiconify $top
    tkwait variable ::TMP
    destroy $top
    if {!$::TMP} { return }

    lappend opts -regexp    $::TMPARRAY(regexp)
    lappend opts -include   $::TMPARRAY(includePatterns)
    lappend opts -exclude   $::TMPARRAY(excludePatterns)
    lappend opts -recursive $::TMPARRAY(recursive)
    lappend opts -defaultaction $::TMPARRAY(include)

    if {!$::TMPARRAY(filterall)} {
	lappend opts -nodes [$tree selection get]
    }

    eval ::InstallJammer::FilterFileGroups $opts
}

proc VersionFrame {path arrayName args} {
    eval frame $path $args

    SPINBOX $path.e1 -textvariable ${arrayName}(MajorVersion) -width 3 -to 999 \
    	-validate key -validatecommand [list ValidateSpinBox %W %s %P] -bd 1
    pack  $path.e1 -side left
    label $path.l1 -text "." -bd 1
    pack  $path.l1 -side left
    DynamicHelp::register $path.e1 balloon "Major Version"

    SPINBOX $path.e2 -textvariable ${arrayName}(MinorVersion) -width 3 -to 999 \
    	-validate key -validatecommand [list ValidateSpinBox %W %s %P] -bd 1
    pack  $path.e2 -side left
    label $path.l2 -text "." -bd 1
    pack  $path.l2 -side left
    DynamicHelp::register $path.e2 balloon "Minor Version"

    SPINBOX $path.e3 -textvariable ${arrayName}(PatchVersion) -width 3 -to 999 \
    	-validate key -validatecommand [list ValidateSpinBox %W %s %P] -bd 1
    pack  $path.e3 -side left
    label $path.l3 -text "." -bd 1
    pack  $path.l3 -side left
    DynamicHelp::register $path.e3 balloon "Patch Version"

    SPINBOX $path.e4 -textvariable ${arrayName}(BuildVersion) -width 3 -to 999 \
    	-validate key -validatecommand [list ValidateSpinBox %W %s %P] -bd 1
    pack  $path.e4 -side left
    DynamicHelp::register $path.e4 balloon "Build Version"
}

proc ::InstallJammer::EditFinishProperty { path node } {
    upvar #0 [$path itemcget $node -variable] newvalue
    set oldvalue [$path edit value]

    if {![::InstallJammer::CheckVirtualText $newvalue]} { return 0 }

    if {![string equal $oldvalue $newvalue]} { Modified }

    return 1
}

proc ::InstallJammer::FinishEditVersion { args } {
    global info
    set old $info(InstallVersion)

    set info(InstallVersion)     $info(MajorVersion)
    append info(InstallVersion) .$info(MinorVersion)
    append info(InstallVersion) .$info(PatchVersion)
    append info(InstallVersion) .$info(BuildVersion)

    if {![string equal $old $info(InstallVersion)]} { Modified }

    return 1
}

proc SetInstallPanes {} {
    global conf
    ::msgcat::mcmset en [array get ::InstallJammer::preview::text]
    if {[info exists conf(window)]} { Cancel $conf(window) }
}

proc PopupEditMenu {w X Y} {
    global widg
    set menu $widg(RightClickEditMenu)

    set ::edit::widget $w

    focus $w

    tag configure editMenu -state normal

    if {[lempty [::edit::curselection $w]]} {
	$menu entryconfigure 0 -state disabled
	$menu entryconfigure 1 -state disabled
	$menu entryconfigure 3 -state disabled
    }

    if {[$w cget -state] == "disabled"} {
	$menu entryconfigure 0 -state disabled
	$menu entryconfigure 2 -state disabled
	$menu entryconfigure 3 -state disabled
    }

    if {[catch {clipboard get} clip]} { set clip [list] }
    if {[lempty $clip]} {
	$menu entryconfigure 2 -state disabled
    }

    $menu post $X $Y
    #if {$::tcl_platform(platform) == "unix"} { tkwait window $menu }
}

proc Buttons { w args } {
    set data(-ok) 1
    set data(-cancel) 1
    set data(-help) 1
    set data(-pack) 1

    set data(-oktxt)     OK
    set data(-helptxt)   Help
    set data(-canceltxt) Cancel

    set data(-okimg)     buttonok16
    set data(-helpimg)   acthelp16
    set data(-cancelimg) buttoncancel16

    set data(-okcmd)     "Cancel $w"
    set data(-helpcmd)   "Help"
    set data(-cancelcmd) "Cancel $w"

    array set data $args

    ## Check to see if the image names are references to another image.
    foreach opt {-okimg -cancelimg -helpimg} {
	if {[info exists data(-$data($opt))]} {
	    set data($opt) $data(-$data($opt))
	}
    }

    set f [frame $w.bbox -height 24 -width 235]

    if {$data(-help)} {
	set b [WinButton $f.help -padx 0 -pady 0 \
	    -image [GetImage $data(-helpimg)] \
	    -command $data(-helpcmd)]
	pack $b -side right
	DynamicHelp::register $f.help balloon $data(-helptxt)
    }

    if {$data(-cancel)} {
	set b [WinButton $f.cancel -padx 0 -pady 0\
	    -image [GetImage $data(-cancelimg)] \
	    -command $data(-cancelcmd)]
	pack $b -side right
	DynamicHelp::register $f.cancel balloon $data(-canceltxt)
    }

    if {$data(-ok)} {
	set b [WinButton $f.ok -padx 0 -pady 0 \
	    -image [GetImage $data(-okimg)] \
	    -command $data(-okcmd)]
	pack $b -side right
	DynamicHelp::register $f.ok balloon $data(-oktxt)
    }

    if {$data(-pack)} {
        pack $f -fill x -side top -anchor ne -pady 5
        pack [Separator $w.bboxsp1] -fill x
        pack [frame $w.bboxsp2 -height 5]
    }

    return $f
}

proc SetPreferences {} {
    array set ::preferences [array get ::tmppreferences]
    CancelPreferences
}

proc CancelPreferences {} {
    ::InstallJammer::SetHelp <last>
    wm withdraw [::InstallJammer::TopName .preferences]
}

proc ::InstallJammer::AddPlatformPropertyNode { prop arrayName
                                                {includeArchives 0} } {
    global conf

    $prop insert end root platforms -text "Build Platforms"

    set platforms [AllPlatforms]
    if {$includeArchives} { eval lappend platforms $conf(Archives) }

    foreach platform [lsort $platforms] {
        set pretty [PlatformText $platform]
        AddProperty $prop end platforms foo platform,$platform \
            ::FileGroupTree::details(platform,$platform) -data $platform \
            -pretty $pretty -node platform,$platform -type boolean
    }
}

proc ::tk::mac::ShowPreferences {} {
    Window show .preferences
}

proc ::tk::mac::Quit {} {
    Exit
}
Added lib/gui-unix.tcl.






































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc PROPERTIES { path args } {
    eval [list ::Properties $path -expand 1 -padx [list 0 10]] $args

    $path bindValue <3> {::InstallJammer::PostPropertiesRightClick %W %n %X %Y}

    return $path
}

proc COMBOBOX { path args } {
    eval ComboBox $path -entrybg #FFFFFF -autocomplete 1 -hottrack 1 $args
}

tile::setTheme jammer

if {[::InstallJammer::GetDesktopEnvironment] eq "KDE"
    && ![catch { tile::setTheme tileqt }]} { return }

option add *Installjammer*borderWidth        0
option add *Installjammer*highlightThickness 0

option add *Installjammer*foreground         #000000
option add *Installjammer*background         #FFFFFF
option add *Installjammer*selectForeground   [style default . -selectforeground]
option add *Installjammer*selectBackground   [style default . -selectbackground]

option add *Installjammer*Listbox.foreground           #000000
option add *Installjammer*Listbox.background           #FFFFFF

option add *Installjammer*Entry.foreground             #000000
option add *Installjammer*Entry.background             #FFFFFF
option add *Installjammer*Entry.borderWidth            1

option add *Installjammer*Text.foreground              #000000
option add *Installjammer*Text.background              #FFFFFF

option add *Installjammer*Menu.relief                  flat
option add *Installjammer*Menu.activeBackground \
    [style default . -selectbackground]
option add *Installjammer*Menu.activeForeground \
    [style default . -selectforeground]

option add *Installjammer*Table.borderWidth            1

#!tk_setPalette [style default . -background]
Added lib/gui-windows.tcl.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

if {[lsearch -exact [tile::availableThemes] "xpnative"] > -1} {
    tile::setTheme xpnative
} else {
    tile::setTheme winnative
}

style default Toolbutton -padding {4 4}

## Setup the default options.
option add *Button.padY 0

font create TkToolTip -family Tahoma -size 8
Added lib/header.tcl.










































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

if {[info exists ::InstallJammer]} { return }

namespace eval ::InstallAPI {}
namespace eval ::InstallJammer {}

set ::debug   0
set ::verbose 0

set ::conf(osx)       [string equal $::tcl_platform(os) "Darwin"]
set ::conf(unix)      [string equal $::tcl_platform(platform) "unix"]
set ::conf(windows)   [string equal $::tcl_platform(platform) "windows"]
set ::conf(windows98) [expr {$conf(windows) && $tcl_platform(osVersion) < 5.0}]
set ::conf(vista)     [expr {$conf(windows) && $tcl_platform(osVersion) >= 6.0}]
set ::conf(wine)      [expr {$conf(windows) && [info exists env(_)]
                         && [file tail $env(_)] eq "wine"}]

set ::info(Testing)   0
set ::info(Debugging) 0

## Trace the virtual text array for changes and execute any
## attached commands or auto-update actions.
trace add variable ::info write ::InstallJammer::VirtualTextTrace

proc ::InstallJammer::VirtualTextTrace { name1 name2 op } {
    upvar #0 ::info($name2) var

    if {[info exists ::InstallJammer::UpdateVarCmds($name2)]} {
        foreach cmd $::InstallJammer::UpdateVarCmds($name2) {
            uplevel #0 $cmd
        }
    }

    if {[info exists ::InstallJammer::AutoUpdateVars($name2)]
        && $var ne $::InstallJammer::AutoUpdateVars($name2)} {
        set ::InstallJammer::AutoUpdateVars($name2) $var
        ::InstallJammer::UpdateWidgets -updateidletasks 1
    }
}

proc ::InstallJammer::SourceCachedFile { file {namespace "::"} } {
    if {[info exists ::InstallJammer::files($file)]} {
        namespace eval $namespace $::InstallJammer::files($file)
        return 1
    }
    return 0
}
Added lib/help.tcl.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc Help {args} {
    global conf
    global preferences

    ## If we weren't passed a subject, try to get the subject for the current
    ## window.
    if {[lempty $args]} {
	set tab ""
	if {[info exists conf(tab)]} { set tab $conf(tab) }
    	set subject [HelpForWindow $conf(window) $tab]
    } elseif {[llength $args] == 1} {
	set subject $args
    } elseif {[llength $args] == 2} {
	lassign $args window tab
	set subject [HelpForWindow $window $tab]
    }

    if {![ShowHelp $subject]} { return }

    if {[info exists conf(helpIndex)]} {
	set end [expr [llength $conf(links)] - 1]
	## They've backed up somewhere.
	if {$conf(helpIndex) != $end} {
	    set conf(links) \
	    	[lreplace $conf(links) [expr $conf(helpIndex)+1] $end $subject]
	} else {
	    lappend conf(links) $subject
	}
    } else {
	lappend conf(links) $subject
    }
    set conf(helpIndex) [expr [llength $conf(links)] - 1]

    ## Configure the states of the back and next buttons.
    SetBackButton
    SetNextButton
}

proc SetHelp {window args} {
    global help

    if {[llength $args] == 2} {
	lassign $args tab subject
	set help($window,$tab) $subject
    } else {
	set subject [lindex $args 0]
	set help($window) $subject
    }
}

proc HelpForWindow {window {tab ""}} {
    global help
    set var $window
    if {![lempty $tab]} { append var ,$tab }
    if {![info exists help($var)]} { return $var }
    return $help($var)
}

proc ShowHelp {subject} {
    global conf
    global preferences

    set browser $preferences(HelpBrowser)

    if {$conf(windows) && $browser eq "Windows Help"} {
        ::InstallJammer::LaunchWindowsHelp $subject
        return 1
    }

    set file [file join $conf(help) html index.html]

    if {[::InstallJammer::LocalHelpExists]} {
        if {![file exists $file] || [file size $file] == 0} {
            ::InstallJammer::Error -title "No Help Available" \
                -message "There is no help for $subject"
            return 0
        }
    }

    if {$browser eq "Internal Browser"} {
	Window show [::InstallJammer::TopName .help] $file
    } else {
	Status "Launching External Help Browser..." 3000
        #set tail "?href=${subject}.html"
        #set url "file://$file$tail"

        set file [file join $conf(help) html $subject.html]
        set url  "file://$file"
        set tail ""
        if {![::InstallJammer::LocalHelpExists]} {
            set url [file join $conf(HelpURL) [file tail $file]$tail]
        }

	::InstallJammer::LaunchBrowser $url
    }

    return 1
}

proc Window.installjammer.help { file } {
    global conf
    global widg

    set top [::InstallJammer::TopName .help]

    if {[winfo exists $top]} {
	ParseHelpFile $file
	wm deiconify $top
	return
    }

    toplevel     $top
    wm withdraw  $top
    wm protocol  $top WM_DELETE_WINDOW "destroy $top"
    wm transient $top $widg(InstallJammer)
    wm title     $top "InstallJammer Help"
    ::InstallJammer::CenterWindow $top 500 400

    frame $top.top

    WinButton $top.top.back -image [GetImage navback22] \
    	-command "BackLink" -state disabled
    WinButton $top.top.next -image [GetImage navforward22] \
    	-command "NextLink" -state disabled
    WinButton $top.top.refresh -image [GetImage actreload22] \
    	-command "Reload $file"
    WinButton $top.top.home -image [GetImage navhome22] \
    	-command "Help index"
    WinButton $top.top.close -image [GetImage actexit22] \
    	-command "destroy $top"

    DynamicHelp::register $top.top.back balloon "Go back one page"
    DynamicHelp::register $top.top.next balloon "Go forward one page"
    DynamicHelp::register $top.top.refresh balloon "Refresh page"
    DynamicHelp::register $top.top.home balloon "Go to help index"
    DynamicHelp::register $top.top.close balloon "Close"

    ScrolledWindow $top.sw
    set html $top.sw.html
    html $html -width 500 -height 400 -bg #FFFFFF -base $conf(help)/trash \
    	-imagecommand AddHelpImage
    $top.sw setwidget $top.sw.html

    pack $top.top -fill x
    pack [frame $top.top.sp1 -width 5] -side left
    pack $top.top.back -side left
    pack [frame $top.top.sp2 -width 3] -side left
    pack $top.top.next -side left
    pack [frame $top.top.sp3 -width 5] -side left
    pack $top.top.refresh -side left
    pack $top.top.home -side left
    pack $top.top.close -side right

    pack $top.sw -fill both -expand 1

    bind $top <Up>    "$html yview scroll -1 units"
    bind $top <Down>  "$html yview scroll  1 units"
    bind $top <Left>  "$html xview scroll -1 units"
    bind $top <Right> "$html xview scroll  1 units"
    bind $top <Prior> "$html yview scroll -1 pages"
    bind $top <Next>  "$html yview scroll  1 pages"
    bind $top <Home>  "$html yview moveto 0"
    bind $top <End>   "$html yview moveto 1"

    bind $html <Button-1> "VisitLink %x %y"
    bind $html <Motion> {
	if {[lempty [%W href %x %y]]} {
	    %W configure -cursor {}
	    break
	}
    	%W configure -cursor hand1
    }

    BindMouseWheel $top.sw.html

    ParseHelpFile $file

    wm deiconify $top
}

proc ParseHelpFile {file} {
    set top [::InstallJammer::TopName .help]
    set html $top.sw.html
    #$html clear
    #$html parse [ReadHelpData [file join $::conf(help) header.html]]
    $html parse [ReadHelpData $file]
    SetHelpTitle
    $top.top.refresh configure -command "Reload [list $file]"
    update
}

proc ReadHelpData {file} {
    return [subst [read_file $file]]
}

proc VisitLink {x y} {
    global conf

    set top [::InstallJammer::TopName .help]

    set file [lindex [$top.sw.html href $x $y] 0]

    if {[lempty $file]} { return }
    set subject [file root [file tail $file]]
    Help $subject
}

proc SetBackButton {} {
    global conf
    if {![info exists conf(helpIndex)]} { return }

    set top [::InstallJammer::TopName .help]
    set b   $top.top.back

    if {![winfo exists $b]} { return }
    if {$conf(helpIndex) > 0} {
	$b configure -state normal
    } else {
	$b configure -state disabled
    }
}

proc BackLink {} {
    global conf

    incr conf(helpIndex) -1
    ShowHelp [lindex $conf(links) $conf(helpIndex)]

    ## Configure the states of the back and next buttons.
    SetBackButton
    SetNextButton
}

proc SetNextButton {} {
    global conf
    if {![info exists conf(helpIndex)]} { return }

    set top [::InstallJammer::TopName .help]
    set b   $top.top.next

    if {![winfo exists $b]} { return }
    set end [expr [llength $conf(links)] -1 ]

    if {$conf(helpIndex) < $end} {
	$b configure -state normal
    } else {
	$b configure -state disabled
    }
}

proc NextLink {} {
    global conf

    incr conf(helpIndex)
    ShowHelp [lindex $conf(links) $conf(helpIndex)]

    ## Configure the states of the back and next buttons.
    SetBackButton
    SetNextButton
}

proc Reload { file } {
    set top [::InstallJammer::TopName .help]
    set html $top.sw.html
    set y [lindex [$html yview] 0]
    Window show $top $file
    update idletasks
    $html yview moveto $y
}

proc HelpLink {subject text} {
    return "<A HREF=\"$subject.html\">$text</A>"
}

proc Include {subject} {
    set top [::InstallJammer::TopName .help]
    return [ReadHelpData [file join $::conf(help) html $subject.html]]
}

proc SetHelpTitle {} {
    global conf

    return

    set top  [::InstallJammer::TopName .help]
    set html $top.sw.html
    set a [lindex [$html token find title] 0]
    if {[lempty $a]} { return }
    set b [$html token getend $a]

    if {$a && $b} {
	set title [string trim [$html text ascii $a $b]]
    	wm title $top $title
    }
}

proc AddHelpImage {src width height args} {
    global conf

    set file $src
    if {[file pathtype $src] == "relative"} {
	set file [file join $conf(help) html $src]
    }
    return [image create photo [NewNode] -file $file]
}

proc ::InstallJammer::HelpBrowsers {} {
    global conf

    set browsers [list]
    if {[string equal $::tcl_platform(platform) "windows"]} {
        if {[file exists [file join $conf(help) installjammer.chm]]} {
            lappend browsers "Windows Help"
        }
        lappend list {C:\Program Files\Mozilla Firefox\firefox.exe}
        lappend list {C:\Program Files\Opera\opera.exe}
	lappend list {C:\Program Files\mozilla.org\Mozilla\mozilla.exe}
	lappend list {C:\Program Files\Internet Explorer\iexplore.exe}
	foreach browser $list {
	    if {[file exists $browser]
    		&& [lsearch -exact $browsers $browser] < 0} {
		lappend browsers $browser
	    }
	}
    } else {
	if {[info exists ::env(HELP_BROWSER)]} {
	    lappend browsers $::env(HELP_BROWSER)
	}

	if {[info exists ::env(BROWSER)]
	    && [lsearch -exact $browsers $::env(BROWSER)] < 0} {
	    lappend browsers $::env(BROWSER)
	}

	set list [list]
    	switch -- [::InstallJammer::GetDesktopEnvironment] {
	    "KDE" {
		lappend list konqueror
	    }

	    "Gnome" {
		lappend list galeon
	    }
	}
	lappend list firefox konqueror mozilla opera galeon

	foreach browser $list {
	    set path [auto_execok $browser]
	    if {[string length $path]
    		&& [lsearch -exact $browsers $path] < 0} {
		lappend browsers $path
	    }
	}
    }

    return $browsers
}

proc ::InstallJammer::AboutInstallJammer {} {
    global conf
    global widg

    set top [::InstallJammer::TopName .about]

    ::Dialog $top -title "About InstallJammer" -spacing 0 \
        -parent $widg(InstallJammer) -default 0

    $top add -text "OK" -width 12 -default active

    text $top.text -width 45 -height 8 -relief flat \
        -background [$top cget -background]
    pack $top.text -expand 1 -fill both

    $top.text tag configure center -justify center
    $top.text tag configure bold -font TkCaptionFont

    $top.text tag configure link -foreground blue -underline 1
    $top.text tag bind link <Enter> [list %W configure -cursor hand2]
    $top.text tag bind link <Leave> [list %W configure -cursor ""]
    $top.text tag bind link <1> {
        ::InstallJammer::LaunchBrowser http://www.installjammer.com/
    }

    $top.text tag configure email -foreground blue -underline 1
    $top.text tag bind email <Enter> [list %W configure -cursor hand2]
    $top.text tag bind email <Leave> [list %W configure -cursor ""]
    $top.text tag bind email <1> {
        exec $::env(COMSPEC) /c start mailto:damon@installjammer.com
    }

    $top.text insert end "InstallJammer Multiplatform Installer\n" bold
    $top.text insert end "http://www.installjammer.com/" link "\n\n"
    $top.text insert end "by Damon Courtney\n<"
    $top.text insert end "damon@installjammer.com" email ">\n\n"
    $top.text insert end "Version $conf(Version) "
    $top.text insert end "(Build $conf(BuildVersion))"

    $top.text tag add center 1.0 end
    $top.text configure -state disabled

    $top draw

    destroy $top
}

proc ::InstallJammer::LaunchWindowsHelp { subject } {
    global conf
    Status "Launching Windows Help..." 3000
    set help [file join $conf(help) InstallJammer.chm]
    exec $::env(COMSPEC) /c start /B hh ${help}::/$subject.html &
}

proc ::InstallJammer::LaunchBrowser { url } {
    global conf
    global preferences

    Status "Launching External Web Browser..." 3000

    set browser $preferences(HelpBrowser)

    if {$browser eq "" || $browser eq "Windows Help"} {
	if {$conf(windows)} {
            if {[string match "file://*" $url]} {
                set url [string range $url 7 end]
                set url file://[file attributes $url -short]
            }
            exec [file normalize $::env(COMSPEC)] /c start $url &
            return
        } elseif {$conf(osx)} {
            set browser open
        } else {
	    set browser xdg-open
        }
    }

    exec $browser $url &
}

proc ::InstallJammer::LocalHelpExists {} {
    global conf
    if {[file exists [file join $conf(help) html]]} { return 1 }
    if {[file exists [file join $conf(help) installjammer.chm]]} { return 1 }
    return 0
}

proc ::InstallJammer::SetHelp { topic } {
    global conf

    switch -- $topic {
        "<default>" {
            set conf(LastHelpTopic) $conf(HelpTopic)
            set conf(HelpTopic) $conf(DefaultHelpTopic)
        }

        "<last>" {
            set conf(HelpTopic) $conf(LastHelpTopic)
        }

        default {
            set conf(LastHelpTopic) $conf(HelpTopic)
            set conf(HelpTopic) $topic
        }
    }
}

proc ::InstallJammer::DownloadVersionInfo { {popup 0} } {
    global conf

    package require http

    set url "$conf(HomePage)/installjammer.info"

    http::config -proxyhost "" -proxyport ""
    if {[GetPref UseProxyServer]} {
        set host [GetPref ProxyHost]
        set port [GetPref ProxyPort]
        http::config -proxyhost $host -proxyport $port
    }

    set command [list ::InstallJammer::ParseVersionInfo $popup]

    if {[catch { ::http::geturl $url -command $command }] && $popup} {
        ::InstallJammer::MessageBox -title "No New Version" -message \
            "No new version of InstallJammer is available at this time."
    }
}

proc ::InstallJammer::ParseVersionInfo { popup token } {
    global conf

    variable versionInfo

    if {[::http::status $token] eq "ok"} {
        set data [::http::data $token]
        ::InstallJammer::ReadProperties $data versionInfo
    }

    ::http::cleanup $token

    set ver $conf(InstallJammerVersion)
    if {[info exists versionInfo(Version)]
        && [package vcompare $ver $versionInfo(Version)] < 0} {
        set ans [::InstallJammer::MessageBox -type yesno \
            -title "New Version Available" -message "There is a new version\
                of InstallJammer available.\nWould you like to download and\
                install it?"]

        if {$ans eq "yes"} {
            ::InstallJammer::DownloadNewVersion
        }
    } elseif {$popup} {
        ::InstallJammer::MessageBox -title "No New Version" -message \
            "No new version of InstallJammer is available at this time."
    }
}

proc ::InstallJammer::DownloadNewVersion {} {

}
Added lib/install.tcl.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

if {[info exists ::InstallJammer]} { return }

proc ::InstallJammer::UpdateInstallInfo {} {
    global conf
    global info

    set setups    [SetupTypes children]
    set setuptype [::InstallJammer::FindObjByName $info(InstallType) $setups]

    set total      0
    set filegroups ""
    set components ""
    foreach component [$setuptype get Components] {
        if {![$component active]} { continue }

        set name [$component name]
        if {[lsearch -exact $components $name] < 0} { lappend components $name }

        set doSize 1
        set size [$component get Size]
        if {$size ne ""} {
            set doSize 0
            set total [expr {wide($total) + $size}]
        }

        foreach filegroup [$component get FileGroups] {
            if {![$filegroup active]} { continue }

            if {$doSize} {
                set fsize [$filegroup get Size]
                if {$fsize eq ""} { set fsize [$filegroup get FileSize] }

                if {[string is integer -strict $fsize]} {
                    set total [expr {wide($total) + $fsize}]
                }
            }

            set name [$filegroup name]
            if {[lsearch -exact $filegroups $name] < 0} {
                lappend filegroups $name
            }
        }
    }

    set conf(ModifySelectedComponents) 0

    set info(SpaceRequired)      $total
    set info(SelectedFileGroups) $filegroups
    set info(SelectedComponents) $components

    set conf(ModifySelectedComponents) 1

    ::InstallJammer::UpdateWidgets
}

proc ::InstallJammer::SelectComponent { paneId } {
    global info

    ::InstallJammer::UpdateInstallInfo

    set id   $paneId
    set tree [$id widget get ComponentTree]
    set text [$id widget get DescriptionText]
    set node [$tree selection get]
    set desc [::InstallJammer::GetText $node Description]

    ::InstallJammer::SetText $text $desc

    ::InstallJammer::SetVirtualText $info(Language) $id \
        [list DescriptionText $desc]
}

proc ::InstallJammer::ToggleComponent { tree id node } {
    global info

    if {![$node get Selectable]} { return }
    if {[$node get RequiredComponent]} { return }

    set type $info(InstallTypeID)

    if {[$node active]} {
        $node active 0

        foreach component [$node children recursive] {
            if {[$component get RequiredComponent]} { continue }

            $component active 0
            if {[$tree exists $component]} {
                $tree itemconfigure $component -on 0
                
                ## If this child is a radiobutton, we need to grab its
                ## group and set the whole group to an empty string so
                ## that all of the radiobuttons turn off.
                if {[$tree itemcget $component -type] eq "radiobutton"} {
                    set group [$component get ComponentGroup]
                    set ::InstallJammer::Components($tree,$group) ""
                }
            }
        }
    } else {
        $node active 1

        foreach component [$node children recursive] {
            $component active 1
            if {[$tree exists $component]} {
                $tree itemconfigure $component -on 1

                ## If this child is a radiobutton, we need to grab its
                ## group and check the Checked status of it to see if
                ## it's supposed to default on or off.
                if {[$tree itemcget $component -type] eq "radiobutton"} {
                    set group [$component get ComponentGroup]
                    if {[$component get Checked]} {
                        set ::InstallJammer::Components($tree,$group) $component
                    } else {
                        $component active 0
                    }
                }
            }
        }
    }

    if {[$tree itemcget $node -type] eq "radiobutton"} {
        ## If this is a radiobutton, we need to deactivate
        ## all of the others in this group.
        set group [$node get ComponentGroup]
        foreach comp $::InstallJammer::Components($tree,$group,others) {
            if {$comp ne $node} { $comp active 0 }
        }
    }

    ::InstallJammer::UpdateInstallInfo
}

proc ::InstallJammer::SelectSetupType { {node ""} } {
    global info

    set name $info(InstallType)
    if {$node eq "" || [set name [$node name]] ne $info(InstallType)} {
        set info(InstallType) $name
        set obj [::InstallAPI::FindObjects -type setuptype -name $name]
        if {$obj eq ""} { set obj [lindex [SetupTypes children] 0] }
        ::InstallAPI::SetActiveSetupType -setuptype $obj
    }

    if {$node ne "" && [::InstallJammer::WizardExists]} {
        set id [$info(Wizard) raise]
        if {$id eq ""} { return }

        set text [$id widget get DescriptionText]
        set list [$id widget get SetupTypeListBox]
        if {$text eq "" || $list eq ""} { return }

        ::InstallJammer::UpdateInstallInfo

        set desc [::InstallJammer::GetText $node Description]
        ::InstallJammer::SetText $text $desc
        ::InstallJammer::SetVirtualText $info(Language) $id \
            [list DescriptionText $desc]

        $list selection set $node
    }
}

proc ::InstallJammer::PopulateProgramFolders { step } {
    global conf

    set listbox [$step widget get ProgramFolderListBox]

    if {$conf(windows)} {
        set folder [list]
        foreach dir {PROGRAMS COMMON_PROGRAMS} {
            set dir [::InstallJammer::WindowsDir $dir]
            eval lappend folders [glob -nocomplain -type d -dir $dir -tails *]
        }
	eval [list $listbox insert end] [lsort -dict -unique $folders]
    }
}

proc ::InstallJammer::SetProgramFolder { {folder ""} } {
    global conf
    global info

    if {![string length $folder]} {
        set step $info(CurrentPane)
        set listbox [$step widget get ProgramFolderListBox]
        set folder  [$listbox get [$listbox curselection]]

        set list [file split $info(OriginalProgramFolderName)]
        if {[llength $list] > 1} {
            set folder [file join $folder [lindex $list end]]
        } else {
            set folder [file join $folder $info(OriginalProgramFolderName)]
        }
    }

    set info(ProgramFolderName) $folder
}

proc ::InstallJammer::ModifyProgramFolder {} {
    global conf
    global info

    set all $info(ProgramFolderAllUsers)
    if {$conf(vista)} { set all 1 }

    if {!$all} {
        set info(ProgramFolder) "<%PROGRAMS%>/<%ProgramFolderName%>"
    } else {
        set info(ProgramFolder) "<%COMMON_PROGRAMS%>/<%ProgramFolderName%>"
    }
}

proc ::InstallJammer::ModifySelectedComponents {} {
    global conf
    global info

    if {!$conf(ModifySelectedComponents)} { return }
    set conf(ModifySelectedComponents) 0

    set selected $info(SelectedComponents)
    ::InstallAPI::ComponentAPI -components all -active 0
    ::InstallAPI::ComponentAPI -components $selected -active 1

    set conf(ModifySelectedComponents) 1
}

proc ::InstallJammer::ScrollLicenseTextBox { force args } {
    global info

    eval $args

    if {!$force} { return }

    set w   [lindex $args 0]
    lassign [$w yview] y0 y1

    if {$y1 == 1} {
        $info(Wizard) itemconfigure next -state normal
    } else {
        $info(Wizard) itemconfigure next -state disabled
    }
}

proc ::InstallJammer::exit { {prompt 0} } {
    global conf
    global info

    if {$prompt} {
        ::InstallJammer::PauseInstall

        set title   [sub "<%ExitTitle%>"]
        set message [sub "<%ExitText%>"]
        set ans [MessageBox -type yesno -default no \
            -parent [::InstallJammer::TransientParent] \
            -title $title -message $message]

        if {$ans eq "no"} {
            ::InstallJammer::ContinueInstall
            return
        }

        set id [$info(Wizard) raise]
        
        if {$id ne ""} {
            set when "After Pane is Cancelled"

            ::InstallJammer::ExecuteActions $id -when $when

            if {![$id checkConditions $when]} { return }
        }

        set info(WizardCancelled) 1
    }

    if {$info(Installing)} {
        ## If we're still installing, we need to stop the install.
	::InstallJammer::StopInstall

	## Give unpack a chance to die before exiting ourselves.
	vwait ::info(Installing)

        if {[string match "*Continue*" $info(CancelledInstallAction)]} {
            ## FIXME:  Need to finish Continue option for a cancelled install.
        }
    }

    if {$info(InstallStarted)
        && $info(InstallStopped)
        && $info(CleanupCancelledInstall)} {
	## We only want to try to cleanup if we actually started the
	## unpack process at some point in the install.  If not, we
	## haven't really done any work to cleanup.
        ::InstallJammer::CleanupCancelledInstall
    }

    if {!$info(WizardCancelled) && ($info(WizardStarted) || !$info(GuiMode))} {
        ::InstallJammer::ExecuteActions "Finish Actions"

        if {!$info(InstallStopped)} {
            ## Create the install logs and version information.
            ::InstallJammer::StoreVersionInfo
            ::InstallJammer::CreateInstallLog
            ::InstallJammer::CreateApplicationInstallLog

            if {!$info(InstallRegistryInfo)} {
                ::InstallJammer::StoreLogsInUninstall
            }
        }

        if {$info(EnableResponseFiles) && [::InstallAPI::CommandLineAPI \
            -do check -option save-response-file]} {
            ::InstallAPI::ResponseFileAPI -do write \
                -file $info(SaveResponseFile)
        }
    } else {
        ::InstallJammer::ExecuteActions "Cancel Actions"
    }

    ::InstallJammer::CheckAndUpdateInstallRegistry

    ::InstallJammer::CommonExit

    if {[string is integer -strict $conf(ExitCode)]} { ::exit $conf(ExitCode) }
    ::exit $info(WizardCancelled)
}

proc ::InstallJammer::UnpackOutput { line } {
    global conf
    global info

    if {$::verbose >= 2} {
        debug "Unpack Output: $line"
    }

    if {[catch {lindex $line 0} command]} { set command :ERROR }

    switch -- $command {
        ":DONE" {
	    ::InstallJammer::UnpackOutput [list :PERCENT 100]

            set info(FileBeingInstalled)  ""
            set info(GroupBeingInstalled) ""

            set info(Status) "File installation complete..."

            if {![threaded]} { catch { close $conf(UnpackFp) } }
            set info(Installing) 0
        }

        ":LOG" {
            ::InstallJammer::InstallLog [lindex $line 1]
        }

	":GROUP" {
	    set info(GroupBeingInstalled) [lindex $line 1]
            ::InstallJammer::UpdateWidgets -buttons 0 -updateidletasks 1

            if {!$info(GuiMode) && !$info(SilentMode)} {
                set cols [expr {$conf(ConsoleWidth) - 2}]
                ::InstallJammer::ConsoleClearLastLine $cols
                echo <%Status%> 1
            }
	}

	":DIR" {
	    set dir   [lindex $line 1]
	    set perms [lindex $line 2]
	    lappend conf(directoryPermissions) $dir $perms
	}

        ":DISC" {
            set info(RequiredDiscName) [lindex $line 1]
            ::InstallJammer::MessageBox -message [sub <%InsertDiscText%>]
            update
            ::InstallJammer::ContinueInstall
        }

	":FILE" {
            set file [lindex $line 1]
            set ::conf(TMPFILE) $file
	    set info(FileBeingInstalled) $file
            ::InstallJammer::SetVersionInfo $file [lindex $line 2]
            if {$conf(UpdateFileText)} {
                ::InstallJammer::UpdateWidgets -buttons 0 -updateidletasks 1
            }

            if {$::verbose == 1} {
                debug "Installing $file..."
            }
	}

	":PERCENT" {
	    set percent [lindex $line 1]
            set info(InstallPercentComplete) $percent
            if {$info(InstallPercentComplete) != $conf(LastPercent)} {
		if {$info(GuiMode)} {
		    ::InstallJammer::UpdateWidgets -buttons 0 -updateidletasks 1
		} elseif {$info(ConsoleMode) && $conf(ShowConsoleProgress)} {
		    ::InstallJammer::ConsoleProgressBar $percent
		}
		set conf(LastPercent) $percent
            }
	}

        ":ROLLBACK" {
            lappend conf(rollbackFiles) [lindex $line 1]
        }

	":FILEPERCENT" {
            set info(FilePercentComplete) [lindex $line 1]
            if {$conf(UpdateFilePercent)} {
                ::InstallJammer::UpdateWidgets -buttons 0 -updateidletasks 1
            }
	}

	default {
            debug "Unpack Error: $line"
            append info(InstallErrors) $line\n
	}
    }
}

proc ::InstallJammer::ReadUnpack { id } {
    global conf

    if {[gets $conf(UnpackFp) line] < 0} { set line :DONE }
    ::InstallJammer::UnpackOutput $line
}

proc ::InstallJammer::BuildUnpackInfo { groupList groupArray } {
    global conf
    global info
    global versions

    upvar 1 $groupArray groups

    ::InstallJammer::ReadVersionInfo

    set unpack [TmpDir unpack.ini]

    set fp [open_text $unpack w -translation lf -encoding utf-8]

    ## Some pieces of the internal configuration need to be
    ## sent to the unpack process.
    set confArray [array get conf eol,*]
    eval lappend confArray [array get conf Wow64Disabled]

    puts $fp "namespace eval ::InstallJammer {}"
    puts $fp "set info(installer) [list [info nameofexecutable]]"
    puts $fp "array set conf [list $confArray]"
    puts $fp "array set info [list [array get info]]"
    puts $fp "set groups [list $groupList]"
    puts $fp "array set files [list [array get groups]]"
    puts $fp ""
    puts $fp "array set versions [list [array get versions]]"

    puts -nonewline $fp "array set ::InstallJammer::Properties "
    puts $fp "[list [array get ::InstallJammer::Properties]]"

    puts $fp "proc ::InstallJammer::UpdateFiles {} {"
    if {[info exists conf(newFiles)]} {
        foreach obj $conf(newFiles) {
            puts $fp "File $obj [$obj serialize]"
        }
        unset conf(newFiles)
    }
    if {[info exists conf(modifiedFiles)]} {
        foreach obj $conf(modifiedFiles) {
            puts $fp "$obj configure [$obj serialize]"
        }
        unset conf(modifiedFiles)
    }
    puts $fp "}"

    puts $fp $::InstallJammer::files(files.tcl)
    puts $fp $::InstallJammer::files(setup.tcl)
    puts $fp $::InstallJammer::files(components.tcl)

    close $fp

    return $unpack
}

proc ::InstallJammer::BuildUnpack {} {
    global info
    global conf

    if {[info exists conf(UnpackBin)]} { return $conf(UnpackBin) }

    set unpack [TmpDir unpack.tcl]
    set conf(UnpackScript) $unpack

    set fp [open_text $unpack w -translation lf -encoding utf-8]
    puts $fp $::InstallJammer::files(common.tcl)
    puts $fp $::InstallJammer::files(unpack.tcl)
    close $fp

    return $unpack
}

## CleanupCancelledInstall
##
## Read the log and cleanup anything that has already been installed.
## This proc is called if the user cancels an installation half-way
## through, and the builder has opted to clean up cancelled installs.
proc ::InstallJammer::CleanupCancelledInstall {} {
    global conf
    global info

    if {$conf(TMPFILE) eq "" && ![llength $conf(LOG)]} { return }

    set info(Status) "Cleaning up install..."

    set dirs    {}
    set files   {}
    set regkeys {}
    foreach line [lreverse $conf(LOG)] {
	set type [lindex $line 0]
	set args [lrange $line 1 end]
	switch -- $type {
	    ":FILE"	{
                lappend files [lindex $args 0]
            }

	    ":DIR"	{
                lappend dirs $args
            }

	    ":REGISTRY"	{
                lappend regkeys $args
            }
	}
    }

    foreach file $files {
        set roll [::InstallJammer::RollbackName $file]
        if {[file exists $roll]} {
            if {$::verbose == 1} {
                debug "Rolling back file $file"
            }
            file rename -force $roll $file
        } else {
            if {$::verbose == 1} {
                debug "Cleaning up file $file"
            }
            ::InstallJammer::UninstallFile $file
        }
    }

    if {[lsearch -exact $files $::conf(TMPFILE)] < 0} {
        ::InstallJammer::UninstallFile $::conf(TMPFILE)
    }

    foreach dir $dirs {
        if {$::verbose == 1} {
            debug "Cleaning up directory $dir"
        }
        eval ::InstallJammer::UninstallDirectory $dir
    }

    foreach regkey $regkeys {
        if {$::verbose == 1} {
            debug "Cleaning up registry key $regkey"
        }
        eval ::InstallJammer::UninstallRegistryKey $regkey
    }
}

proc ::InstallJammer::CreateApplicationInstallLog {} {
    global conf
    global info

    if {$info(InstallRegistryInfo)} {
        set file [::InstallJammer::InstallInfoDir $info(InstallID).info]
    } else {
        set file [::InstallJammer::TmpDir $info(InstallID).info]
    }

    set fp [open_text $file w -translation lf -encoding utf-8]

    set    string ""
    append string "ApplicationID: <%ApplicationID%>\n"
    append string "Dir:           <%InstallDir%>\n"
    append string "Date:          [clock seconds]\n"
    append string "User:          <%Username%>\n"
    append string "RealUser:      <%RealUsername%>\n"
    append string "Version:       <%InstallVersion%>\n"
    append string "VersionString: <%Version%>\n"
    append string "Source:        <%InstallSource%>\n"
    append string "Executable:    <%Installer%>\n"
    append string "Uninstaller:   <%Uninstaller%>\n"
    append string "UpgradeID:     <%UpgradeApplicationID%>\n"

    puts $fp [::InstallJammer::SubstText $string]

    if {[info exists conf(APPLOG)]} {
        foreach {var val} $conf(APPLOG) {
            puts $fp "$var: $val"
        }
    }

    close $fp
}

proc ::InstallJammer::CreateInstallLog { {file ""} } {
    global conf
    global info

    if {$file eq ""} {
        if {$info(InstallRegistryInfo)} {
            set file [::InstallJammer::InstallInfoDir $info(InstallID).log]
        } else {
            set file [::InstallJammer::TmpDir $info(InstallID).log]
        }
    }

    if {[catch { open_text $file w -translation lf -encoding utf-8 } fp]} {
        return
    }

    ::InstallJammer::LogFile $file

    set checkRemove 0
    if {[info exists conf(RemoveFromUninstall)]} {
        set checkRemove 1
        set pattern [join $conf(RemoveFromUninstall) |]
    }

    foreach line $conf(LOG) {
        if {![info exists done($line)]} {
            set done($line) 1

            if {$checkRemove} {
                set type [lindex $line 0]
                set dir  [lindex $line 1]
                if {($type eq ":DIR" || $type eq ":FILE")
                    && [regexp $pattern $dir]} { continue }
            }

            puts $fp $line
        }
    }
    close $fp
}

proc ::InstallJammer::InstallLog {string} {
    lappend ::conf(LOG) $string
}

proc ::InstallJammer::LogRegistry { args } {
    ::InstallJammer::InstallLog [concat :REGISTRY $args]
}

proc ::InstallJammer::CheckAndUpdateInstallRegistry {} {
    global conf
    global info

    if {[info exists conf(checkAndUpdateRegistry)]} { return }
    set conf(checkAndUpdateRegistry) 1

    ## Setup the directories we need.
    set dir [::InstallJammer::GetInstallInfoDir]

    ## We need to check for older versions of InstallJammer
    ## that stored registry information by the ApplicationID
    ## instead of the InstallID.  If we find one, we're going
    ## to update it to the new method before proceeding.
    if {[file exists [file join $dir install.log]]} {
        ## This is an old registry.  We need to update it.

        ## Create a new InstallID for this old install.
        set newid [::InstallJammer::uuid]

        set file [file join $dir .installinfo]
        if {[file exists $file]} {
            file delete $file
        }

        set file [file join $dir install.log]
        if {[file exists $file]} {
            file rename -force $file [file join $dir $newid.log]

            set file [file join $dir $newid.log]
            foreach x [split [string trim [read_textfile $file]] \n] {
                if {[lindex $x 0] eq ":DIR"} {
                    set installdir [lindex $x 1]

                    set info [file join $dir $newid.info]
                    set fp [open_text $info w -translation lf -encoding utf-8]
                    puts  $fp "ApplicationID: $info(ApplicationID)"
                    puts  $fp "Dir:           $installdir"
                    puts  $fp "Date:          [file mtime $file]"
                    close $fp
                    break
                }
            }
        }
    }
}

proc ::InstallJammer::ReadPreviousInstall {} {
    global conf
    global info

    variable ::InstallJammer::PreviousInstallInfo

    ::InstallJammer::CheckAndUpdateInstallRegistry

    ::InstallAPI::ReadInstallInfo -prefix PreviousInstall \
        -array PreviousInstallInfo

    foreach {var val} [array get PreviousInstallInfo PreviousInstall*] {
        set info($var) $val
        unset PreviousInstallInfo($var)
    }
}

proc ::InstallJammer::StoreVersionInfo { {dir ""} {file ""} } {
    global conf
    global info
    global versions

    if {!$info(InstallVersionInfo)} { return }

    if {$info(InstallRegistryInfo)} {
        if {$dir eq ""} { set dir [::InstallJammer::InstallInfoDir] }
        if {$file eq ""} { set file $info(InstallID).ver }
    } else {
        if {$dir eq ""} { set dir $info(InstallDir) }
        if {$file eq ""} { set file .installinfo }
    }

    set file [file join $dir $file]

    if {[file exists $file]} {
        catch { file delete -force $file }
    }

    debug "Storing version file $file"
    if {[catch {open_text $file w -translation lf -encoding utf-8} fp]} {
        return
    }

    ::InstallJammer::LogFile $file

    foreach filename [array names versions] {
	puts $fp "Ver [list $filename] $versions($filename)"
    }

    catch {close $fp}

    if {![file exists $file] || [file size $file] == 0} {
        debug "Version file failed to create."
    } else {
        debug "Version file created successfully."
    }

    if {$conf(windows)} {
        file attributes $file -hidden 1
    }
}

proc ::InstallJammer::ReadVersionInfo {} {
    global info
    global versions

    ## Look for a file in our install info dir first.
    set dir  [::InstallJammer::GetInstallInfoDir]
    set file [file join $dir $info(InstallID).ver]
    if {![file exists $file]} {
        ## We didn't find one.  See if we can find one in
        ## the installation directory.
        set file [file join $info(InstallDir) .installinfo]
    }

    if {[file exists $file]} {
        set fp [open_text $file]

        while {[gets $fp line] != -1} {
            switch -- [lindex $line 0] {
                "Ver" {
                    lassign $line cmd file ver
                    set versions($file) $ver
                }
            }
        }

        close $fp
    }
}

proc ::InstallJammer::UnpackSolidProgress { in out showGui bytes {error ""} } {
    global conf
    global info

    set top .__solidExtract

    if {$error ne "" || [eof $in]} {
        set conf(solidUnpackDone) 1
    } else {
        set conf(solidDone) [expr {$conf(solidDone) + double($bytes)}]
        if {$conf(solidTotal) > 0} {
            set conf(solidLeft) [expr {wide($conf(solidTotal))
                                       - $conf(solidDone)}]
            set x [expr {round(($conf(solidDone) * wide(100))
                         / $conf(solidTotal))}]
            if {$showGui} {
                $top.p configure -value $x
                wm title $top "$x% Extracting"
                update
            } else {
                set info(InstallPercentComplete) $x
                ::InstallJammer::UpdateWidgets -update 1
            }
        }

        if {$conf(solidLeft) == 0} {
            set conf(solidUnpackDone) 1
            return
        }

        set size [expr {64 * 1024}]
        if {$size > $conf(solidLeft)} {
            set size [expr {round($conf(solidLeft))}]
        }

        ::fcopy $in $out -size $size -command [lrange [info level 0] 0 3]
    }
}

proc ::InstallJammer::UnpackSolidArchives { {showGui 0} } {
    global conf
    global info

    if {!$info(InstallHasSolidArchives) || $info(SolidArchivesExtracted)} {
        return
    }

    set files [list]
    set conf(solidDone)  0
    set conf(solidTotal) 0
    foreach file [glob -nocomplain -dir $conf(vfs) solid.*] {
        lappend files $file
        set conf(solidTotal) [expr {wide($conf(solidTotal))
                                    + [file size $file]}]
    }

    if {![llength $files]} { return }

    if {!$info(GuiMode)} { set showGui 0 }

    if {$showGui} {
        set top .__solidExtract
        toplevel    $top
        wm withdraw $top
        wm title    $top "0% Extracting"
        wm geometry $top 270x60
        wm protocol $top WM_DELETE_WINDOW {#}

        ttk::progressbar $top.p
        pack $top.p -expand 1 -fill both -padx 10 -pady 20

        BWidget::place $top 270 60 center

        wm deiconify $top
        update

        grab $top
    } else {
        set info(Status) "Extracting setup files..."
    }

    if {!$info(GuiMode) && !$info(SilentMode)} {
        puts  stdout [::InstallJammer::SubstText $info(Status)]
        flush stdout
    }

    foreach file $files {
        set temp [TmpDir [file tail $file]]

        set ifp [open $file]
        fconfigure $ifp -translation binary

        set ofp [open $temp w]
        fconfigure $ofp -translation binary

        ::InstallJammer::UnpackSolidProgress $ifp $ofp $showGui 0

        vwait ::conf(solidUnpackDone)

        close $ifp
        close $ofp

        installkit::Mount $temp $conf(vfs)
    }

    if {$showGui} {
        grab release $top
        destroy $top
    }

    set info(SolidArchivesExtracted) 1
}

proc ::InstallJammer::AskUserLanguage {} {
    global conf
    global info

    set list [::InstallJammer::GetLanguages]

    if {[llength $list] < 1} { return }

    set top .__askLanguage

    Dialog $top -title "Language Selection" -default ok -cancel 1
    wm resizable $top 0 0
    wm protocol  $top WM_DELETE_WINDOW {::InstallJammer::exit 1}

    set f [$top getframe]

    ttk::label $f.l -text [::InstallJammer::SubstText <%SelectLanguageText%>]
    pack $f.l -pady 10

    ttk::combobox $f.cb -state readonly \
        -textvariable ::conf(Language) -values $list
    pack $f.cb

    $top add -name ok     -text "OK"
    $top add -name cancel -text "Cancel" -command {::InstallJammer::exit 1}

    foreach code [::msgcat::mcpreferences] {
        set lang [::InstallJammer::GetLanguage $code]
        if {$lang ne ""} {
            set conf(Language) $lang
            break
        }
    }

    $top setfocus 0
    if {[$top draw] == 1} {
        set info(WizardCancelled) 1
        ::InstallJammer::exit
    }

    ::msgcat::mclocale [::InstallJammer::GetLanguageCode $conf(Language)]
    set info(Language) [::msgcat::mclocale]
}

proc ::InstallJammer::InstallMain {} {
    global conf
    global info

    if {$info(SilentMode)} {
        ::InstallJammer::ExecuteActions "Startup Actions"
        ::InstallJammer::ExecuteActions Silent
    } elseif {$info(ConsoleMode)} {
        ::InstallJammer::ConfigureBidiFonts
        ::InstallJammer::ExecuteActions "Startup Actions"
        ::InstallJammer::ExecuteActions Console
    } else {
        if {$info(AllowLanguageSelection)} {
            ::InstallJammer::AskUserLanguage
        }

        ::InstallJammer::ConfigureBidiFonts

        ::InstallJammer::ExecuteActions "Startup Actions"

        set info(WizardStarted) 1
        ::InstallJammer::CenterWindow $info(Wizard)
        raise $info(Wizard)
        ::InstallJammer::Wizard next
    }
}

proc ::InstallJammer::InitInstall {} {
    global conf
    global info

    catch { wm withdraw . }

    ## Check and load the TWAPI extension.
    ::InstallJammer::LoadTwapi

    SourceCachedFile gui.tcl
    SourceCachedFile setup.tcl
    SourceCachedFile files.tcl
    SourceCachedFile components.tcl

    set info(InstallID) [::InstallJammer::uuid]

    set info(RunningInstaller)   1
    set info(RunningUninstaller) 0

    ::InstallJammer::CommonInit

    array set info {
        Installing             0
        InstallStarted         0
        InstallStopped         0
        InstallFinished        0

        LicenseAccepted         No
        FileBeingInstalled      ""
        GroupBeingInstalled     ""
        InstallPercentComplete  0

        PreviousInstallDir      ""
        PreviousInstallCount    0
        PreviousInstallExists   0

        RunningInstaller        1

        SolidArchivesExtracted  0
        InstallHasSolidArchives 0
    }

    set conf(LOG)      {}
    set conf(TMPFILE)  ""
    set conf(mode)     "InstallMode"
    set conf(rollback) [string match "*Rollback*" $info(CancelledInstallAction)]
    set conf(rollbackFiles) {}

    set conf(modes) "Standard Default Silent"
    if {!$conf(windows)} { lappend conf(modes) "Console" }

    set info(Installer)     $conf(exe)
    set info(InstallSource) [file dirname $conf(exe)]

    if {[llength [glob -nocomplain -dir $conf(vfs) solid.*]]} {
        set info(InstallHasSolidArchives) 1
    }

    SafeSet info(UpgradeInstall) \
        [expr {[string trim $info(UpgradeApplicationID)] ne ""}]

    ::InstallJammer::ReadMessageCatalog messages

    ::InstallJammer::ParseCommandLineArguments $::argv

    if {$info(GuiMode)} { ::InstallJammer::InitializeGui }

    ::InstallJammer::CommonPostInit

    ::InstallJammer::MountSetupArchives

    if {$info(ExtractSolidArchivesOnStartup)} {
        ::InstallJammer::UnpackSolidArchives 1
    }

    if {$conf(windows)} {
        ## Commented out for now.
        #if {$info(RequireAdministrator) && !$conf(vista)} {
            #set admin [::twapi::map_account_to_name S-1-5-32-544]
            #set members [::twapi::get_local_group_members $admin]
            #if {[lsearch -glob $members "*\\$info(Username)"] < 0} {
                #::InstallJammer::Message -title "Install Error" -message \
                    #[sub "<%RequireAdministratorText%>"]
                #::exit 1
            #}
        #}
    } elseif {$conf(unix)} {
        if {$info(RequireRoot) && !$info(UserIsRoot)} {
            if {$info(GuiMode) && $info(PromptForRoot)} {
                set msg [sub "<%PromptForAdministratorText%>"]
                set cmd [concat [list [info nameofexecutable]] $::argv]
                ::InstallJammer::ExecAsRoot $cmd -message $msg
                ::exit 0
            }

            set title   [sub "<%RequireRootTitleText%>"]
            set message [sub "<%RequireRootText%>"]
            ::InstallJammer::Message -title $title -message $message
            ::exit 1
        }

        ## If we have a root install dir, and the user is root,
        ## set the install dir to the root install dir.
        variable ::InstallJammer::VirtualTextSetByCommandLine
        if {$info(RootInstallDir) ne "" && $info(UserIsRoot)
            && ![info exists VirtualTextSetByCommandLine(InstallDir)]} {
            set info(InstallDir) $info(RootInstallDir)
        }
    }

    ::InstallJammer::InitSetup
    ::InstallJammer::InitFiles

    ## Setup the default user information under Windows
    if {$conf(windows)} {
	set key {HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion}
	catch {
            set info(UserInfoName)    [registry get $key RegisteredOwner]
            set info(UserInfoCompany) [registry get $key RegisteredOrganization]
        }
    }

    if {$conf(windows)} {
        set dir [::InstallJammer::WindowsDir PROGRAM_FILES]
        set info(InstallDrive) [string range $dir 0 1]
    }

    ## Normalize some of the install variables.
    foreach var [list InstallDir ProgramFolderName] {
        set info($var) [::InstallJammer::SubstText <%$var%>]
        set info(Original$var) $info($var)
    }

    ## Call a proc if the all users value changes.
    ::InstallAPI::SetVirtualText -virtualtext ProgramFolderAllUsers \
    	-command ::InstallJammer::ModifyProgramFolder

    ::InstallAPI::SetVirtualText -virtualtext SelectedComponents \
        -command ::InstallJammer::ModifySelectedComponents

    if {$info(UpgradeInstall)} {
        ::InstallJammer::ReadPreviousInstall
        if {[info exists info(PreviousInstallUninstaller)]} {
            set info(Uninstaller) $info(PreviousInstallUninstaller)
        }
    }

    ::InstallJammer::SelectSetupType
}

::InstallJammer::InitInstall
Added lib/installapi.tcl.
























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

namespace eval ::InstallAPI {}

proc ::InstallAPI::AddInstallInfo { args } {
    ::InstallAPI::ParseArgs _args $args {
        -key   { string 1 }
        -value { string 1 }
    }

    global conf
    lappend conf(APPLOG) $_args(-key) $_args(-value)
}

proc ::InstallAPI::AddLanguage { args } {
    ::InstallAPI::ParseArgs _args $args {
        -language     { string 1 }
        -languagecode { string 1 }
    }

    variable ::InstallJammer::languages
    variable ::InstallJammer::languagecodes
    set languages($_args(-language)) $_args(-languagecode)
    set languagecodes($_args(-languagecode)) $_args(-language)
}

proc ::InstallAPI::CommandLineAPI { args } {
    ::InstallAPI::ParseArgs _args $args {
        -do         { choice  1 "" {check exists}}
        -option     { string  1 }
    }

    variable ::InstallJammer::CommandLineOptions
    variable ::InstallJammer::PassedCommandLineOptions

    set opt [string tolower [string trimleft $_args(-option) -/]]
    if {$_args(-do) eq "exists"} {
        return [info exists CommandLineOptions($opt)]
    }

    if {$_args(-do) eq "check"} {
        return [info exists PassedCommandLineOptions($opt)]
    }
}

proc ::InstallAPI::ComponentAPI { args } {
    ::InstallAPI::ParseArgs _args $args {
        -components { string  1 }
        -active     { boolean 0 }
        -updateinfo { boolean 0 1 }
    }

    global conf

    set components $_args(-components)
    if {$components eq "all"} { set components [Components children recursive] }

    foreach component $components {
        set component [string trim $component]
        set id [::InstallAPI::FindObjects -alias $component]
        if {$id eq ""} {
            set id [::InstallAPI::FindObjects -type component -name $component]
        }
        if {$id eq ""} {
            return -code error "invalid component \"$component\""
        }

        set id [$id id]
        lappend componentIds $id
        if {[info exists _args(-active)]} {
            if {$_args(-active)} {
                debug "Activating component $component"
            } else {
                debug "Deactivating component $component"
            }
            $id active $_args(-active)
        }
    }

    variable ::InstallJammer::Components

    foreach tree $conf(ComponentTrees) {
        if {![winfo exists $tree]} { continue }

        foreach component $componentIds {
            set group [$component get ComponentGroup]

            set var $tree,$component
            if {$group ne ""} { set var $tree,$group }

            if {![info exists Components($var)] || $Components($var) eq ""} {
                set checked [$component get Checked]
                if {[$component get RequiredComponent]} { set checked 1 }

                if {$group eq ""} {
                    set Components($var) [string is true $checked]
                } elseif {$checked} {
                    set Components($var) $component
                }
            } else {
                if {$group eq ""} {
                    set Components($var) [string is true [$component active]]
                } elseif {[$component active]} {
                    set Components($var) $component
                }
            }
        }
    }

    if {$_args(-updateinfo)} { ::InstallJammer::UpdateInstallInfo }
}

proc ::InstallAPI::ConfigAPI { args } {
    ::InstallAPI::ParseArgs _args $args {
        -usenativefiledialog      { boolean 0 }
        -usenativemessagebox      { boolean 0 }
        -usenativedirectorydialog { boolean 0 }
    }

    global conf

    if {$conf(unix) && !$conf(osx)} {
        ## UNIX platforms have no native dialog, so no matter
        ## what we're told, always use our own dialogs.
        foreach arg [array names _args -usenative*] {
            set _args($arg) 0
        }
    }

    if {[info exists _args(-usenativefiledialog)]} {
        set conf(NativeChooseFile) $_args(-usenativefiledialog)
    }

    if {[info exists _args(-usenativemessagebox)]} {
        set conf(NativeMessageBox) $_args(-usenativemessagebox)
    }

    if {[info exists _args(-usenativedirectorydialog)]} {
        set conf(NativeChooseDirectory) $_args(-usenativedirectorydialog)
    }
}

proc ::InstallAPI::CopyObject { args } {
    ::InstallAPI::ParseArgs _args $args {
        -object    { string 1 }
        -newobject { string 0 }
    }

    set obj [::InstallJammer::ID $_args(-object)]
    if {![::InstallJammer::ObjExists $obj]} {
        return -code error "object \"$obj\" does not exist"
    }

    if {[info exists _args(-newobject)]} {
        set new ::$_args(-newobject)
        if {[::InstallJammer::ObjExists $new]} {
            return -code error "object \"$new\" already exists"
        }
    } else {
        set new ::[::InstallJammer::uuid]
    }

    set opts {}
    foreach {opt val} [$obj serialize] {
        if {$opt eq "-id"} { continue }
        if {$opt eq "-alias"} { continue }
        lappend opts $opt $val
    }

    eval [list [$obj class] $new] $opts

    $obj properties props

    set opts {}
    foreach {prop val} [array get props] {
        if {$prop eq "Alias"} { continue }
        lappend opts $prop $val
    }
    $new set $opts

    set map [list $obj, [namespace tail $new],]
    foreach lang [::InstallJammer::GetLanguageCodes] {
        upvar #0 ::msgcat::Msgs_$lang msgs
        foreach {msg string} [array get msgs $obj,*] {
            set msgs([string map $map $msg]) $string
        }
    }

    return $new
}

proc ::InstallAPI::DestroyWidget { args } {
    if {![::InstallJammer::InGuiMode]} { return }

    ::InstallAPI::ParseArgs _args $args {
        -widgets { string 1 }
    }

    foreach w $_args(-widgets) {
        set widget [::InstallAPI::GetWidgetPath -frame 1 -widget $w]
        if {$widget ne ""} { destroy $widget }
    }
}

proc ::InstallAPI::DecodeURL { args } {
    ::InstallAPI::ParseArgs _args $args {
        -url { string 1 }
    }

    global conf

    variable urlDecodeMap
    if {![info exists urlDecodeMap]} {
        for {set i 0} {$i < 256} {incr i} {
            set c [format %c $i]
            if {$c eq "?" || $c eq "=" || $c eq "&"} { continue }
            if {![string match {[a-zA-Z0-9]} $c]} {
                lappend urlDecodeMap %[format %02x $i] $c
            }
        }
    }

    return [string map $urlDecodeMap $_args(-url)]
}

proc ::InstallAPI::EncodeURL { args } {
    ::InstallAPI::ParseArgs _args $args {
        -url { string 1 }
    }

    global conf

    variable urlEncodeMap
    if {![info exists urlEncodeMap]} {
        for {set i 0} {$i < 256} {incr i} {
            set c [format %c $i]
            if {$c eq "?" || $c eq "=" || $c eq "&"} { continue }
            if {![string match {[a-zA-Z0-9]} $c]} {
                lappend urlEncodeMap $c %[format %02x $i]
            }
        }
    }

    lassign [split $_args(-url) ?] url query
    if {$query ne ""} {
        set query [string map $urlEncodeMap $query]
        append url "?$query"
    }

    if {[file exists $_args(-url)]} {
        if {$conf(windows)} {
            return "file:///$url"
        } else {
            return "file://$url"
        }
    }

    return $url
}

proc ::InstallAPI::ErrorMessage { args } {
    ::InstallAPI::ParseArgs _args $args {
        -title   { string 0 "<%ErrorTitle%>" }
        -message { string 1 }
    }

    ::InstallJammer::Message -icon "error" \
        -title [sub $_args(-title)] -message [sub $_args(-message)]
}

proc ::InstallAPI::ExecuteAction { args } {
    ::InstallAPI::ParseArgs _args $args {
        -action          { string  1 }
        -parent          { string  0 "" }
        -checkconditions { boolean 0 1 }
    }

    ::InstallJammer::ExecuteActions $_args(-action) \
        -parent $_args(-parent) -conditions $_args(-checkconditions)
}

proc ::InstallAPI::FetchURL { args } {
    ::InstallAPI::ParseArgs _args $args {
        -blocksize           { string 0 "8192" }
        -file                { string 0 "" }
        -progressvirtualtext { string 0 }
        -proxyhost           { string 0 "" }
        -proxyport           { string 0 "" }
        -statusvirtualtext   { string 0 "Status" }
        -timeout             { string 0 }
        -url                 { string 1 }
        -variable            { string 0 "" }
        -virtualtext         { string 0 "" }
    }

    package require http

    set urls  [split $_args(-url) \;]
    set len   [llength $urls]
    set total 0

    set files        $_args(-file)
    set variables    $_args(-variable)
    set virtualtexts $_args(-virtualtext)

    if {$len > 1} {
        set files        [split $_args(-files) \;]
        set variables    [split $_args(-variable) \;]
        set virtualtexts [split $_args(-virtualtext) \;]
    }

    http::config -proxyhost $_args(-proxyhost)
    http::config -proxyport $_args(-proxyport)

    if {[info exists _args(-progressvirtualtext)]} {
        ::InstallAPI::SetVirtualText \
            -virtualtext $_args(-progressvirtualtext) -value 0 -autoupdate 1

        foreach url $urls {
            if {[catch { http::geturl $url -validate 1 } tok]} {
                if {$_args(-returnerror)} {
                    return -code error $tok
                }

                set error $tok
                return 0
            }

            upvar #0 $tok state
            incr total $state(totalsize)
            http::cleanup $tok
        }

        ::InstallJammer::StartProgress \
            ::info($_args(-progressvirtualtext)) $total
    }

    set i 0
    foreach url $urls file $files var $variables virtualtext $virtualtexts {
        set file        [string trim $file]
        set virtualtext [string trim $virtualtext]

        set opts [list -blocksize $_args(-blocksize)]

        if {$file ne ""} {
            set fp [open $file w]
            fconfigure $fp -translation binary
            lappend opts -channel $fp
        }

        if {$total > 0} {
            ::InstallJammer::ResetProgress
            lappend opts -progress ::InstallJammer::UpdateProgress
        }

        if {$_args(-statusvirtualtext) ne ""} {
            set varName ::info($_args(-statusvirtualtext))

            if {$len == 1} {
                set $varName "<%DownloadingFilesText%>"
            } else {
                set $varName "<%DownloadingFilesText%> ([incr i]/$len)"
            }
        }

        if {[catch { eval http::geturl [list $url] $opts } token]} {
            if {[info exists fp]} {
                close $fp
                file delete -force $file
            }

            if {$_args(-returnerror)} {
                return -code error $token
            }

            set error $token
            return 0
        }

        upvar #0 $token state

        if {[info exists fp]} { close $fp }

        if {$state(status) ne "ok" && $file ne ""} {
            file delete -force $file
        }

        if {$state(status) eq "ok" && [http::ncode $token] == 302} {
            ## This URL is a redirect.  We need to fetch the redirect URL.

            array set meta $state(meta)
            http::cleanup $token

            if {![info exists meta(Location)]} {
                return -code error "302 Redirect without new Location"
            }

            set _args(-url) $meta(Location)
            debug "URL Redirected to $_args(-url)."

            eval ::InstallAPI::FetchURL [array get _args]

            continue
        }

        if {$var ne ""} {
            upvar 1 $var body
            set body $state(body)
        }

        if {$virtualtext ne ""} {
            set ::info($virtualtext) $state(body)
        }

        http::cleanup $token
    }

    return 1
}

proc ::InstallAPI::FindObjects { args } {
    ::InstallAPI::ParseArgs _args $args {
        -active    { boolean 0 }
        -alias     { string  0 }
        -component { string  0 }
        -glob      { boolean 0 }
        -name      { string  0 }
        -parent    { string  0 }
        -type      { string  0 }
    }

    if {[info exists _args(-alias)]} {
        set id [::InstallJammer::ID $_args(-alias)]
        if {[::InstallJammer::ObjExists $id]} { return $id }
        return
    }

    set check 0
    foreach x {type name active parent component} {
        set chk${x} 0
        if {[info exists _args(-$x)]} {
            incr check
            set chk${x} 1
            set $x $_args(-$x)
        }
    }

    if {!$chktype} {
        set type "all"
        set objects [::itcl::find objects]
    } else {
        set type [string tolower $type]
        incr check -1
        set chktype 0
        switch -- $type {
            "file" { set class ::File }
            "filegroup" { set class ::FileGroup }
            "component" { set class ::Component }
            "setuptype" { set class ::SetupType }
            "condition" { set class ::Condition }
            "action" - "actiongroup" - "pane" {
                incr check
                set chktype 1
                set class ::InstallComponent
            }

            default {
                return -code error [BWidget::badOptionString type $_args(-type)\
                    {action actiongroup pane file filegroup component
                        setuptype condition}]
            }
        }
        set objects [::itcl::find objects -class $class]
        if {$type eq "file"} {
            set objects [::itcl::find objects -class $class]
            if {$chkcomponent} {
                ## Files don't have a component.
                incr check -1
                set chkcomponent 0
            }
        } else {
            ## All other types besides files have a root
            ## parent object that we don't want to show up.
            set objects {}
            foreach obj [::itcl::find objects -class $class] {
                if {[$obj parent] eq ""} { continue }
                lappend objects $obj
            }
        }
    }

    if {$chkparent} {
        set check   0
        set parent  [::InstallJammer::ID $parent]
        set objects {}
        if {[::InstallJammer::ObjExists $parent]} {
            set objects [$parent children]
        }
    }

    if {!$check} { return $objects }

    set glob 0
    if {$chkname && [info exists _args(-glob)]} { set glob 1 }

    set found {}
    foreach obj $objects {
        if {$chktype && [$obj type] ne $type} { continue }
        if {$chkparent && [$obj parent] ne $parent} { continue }
        if {$chkcomponent && [$obj component] ne $component} { continue }
        if {$chkactive} {
            set state [$obj active]
            if {($state && !$active) || (!$state && $active)} { continue }
        }
        if {$chkname} {
            set objname [$obj name]
            if {$type eq "file"} { set objname [file tail $objname] }
            if {($glob && ![string match $name $objname])
                || (!$glob && $objname ne $name)} { continue }
        }
        lappend found $obj
    }
    return $found
}

proc ::InstallAPI::FindProcesses { args } {
    global conf

    ::InstallAPI::ParseArgs _args $args {
        -pid   { string  0 }
        -glob  { boolean 0 0}
        -name  { string  0 }
        -user  { string  0 }
        -group { string  0 }
    }

    if {$conf(windows)} {
        if {[info exists _args(-pid)]} {
            set pid $_args(-pid)
            return [expr {[twapi::process_exists $pid] ? $pid : ""}]
        }

        set opts {}

        if {$_args(-glob)} {
            lappend opts -glob
        }

        if {[info exists _args(-name)]} {
            lappend opts -name $_args(-name)
        }

        if {[info exists _args(-user)]} {
            lappend opts -user $_args(-user)
        }

        return [eval twapi::get_process_ids $opts]
    } else {
        if {![info exists conf(OldPS)]} {
            set conf(OldPS) [catch { exec ps -C ps }]
        }

        set ps     [list ps]
        set all    0
        set format "pid"

        if {[info exists _args(-pid)]} {
            lappend ps -p $_args(-pid)
        }

        if {[info exists _args(-name)]} {
            if {$conf(OldPS)} {
                set all 1
                lappend format comm
            } else {
                lappend ps -C $_args(-name)
            }
        }

        if {[info exists _args(-user)]} {
            set all 0
            lappend ps -U $_args(-user)
        }

        if {[info exists _args(-group)]} {
            set all 0
            lappend ps -G $_args(-group)
        }

        if {$all} { lappend ps -ae }

        lappend ps -o $format

        if {![catch { eval exec $ps } result]} {
            set pids [list]
            foreach list [lrange [split [string trim $result] \n] 1 end] {
                if {[llength $list] > 1} {
                    set command [file tail [lindex $list 1]]
                    if {$_args(-name) ne $command} { continue }
                }
                lappend pids [lindex $list 0]
            }
            return $pids
        }
    }
}

proc ::InstallAPI::GetComponentsForSetupType { args } {
    ::InstallAPI::ParseArgs _args $args {
        -setuptype  { string  1 }
    }

    if {[::InstallJammer::ObjExists $_args(-setuptype)]} {
        set obj  $_args(-setuptype)
        set name [$obj name]

        if {![$obj is setuptype]} {
            return -code error "$obj is not a valid Setup Type object"
        }
    } else {
        set name $_args(-setuptype)

        set setups [SetupTypes children]
        set obj [::InstallJammer::FindObjByName $name [SetupTypes children]]
        if {$obj eq ""} {
            return -code error "Could not find Setup Type '$name'"
        }
    }

    return [$obj get Components]
}

proc ::InstallAPI::GetDisplayText { args } {
    ::InstallAPI::ParseArgs _args $args {
        -object     { string  1 }
    }

    set object [::InstallJammer::ID $_args(-object)]
    if {![::InstallJammer::ObjExists $object]} {
        return -code error "object '$_args(-object)' does not exist"
    }

    set text ""
    switch -- [$object type] {
        "filegroup" {
            set text [sub [$object get DisplayName]]
            if {$text eq ""} { set text [$object name] }
        }

        "component" - "setuptype" {
            set text [::InstallJammer::GetText $object DisplayName]
            if {$text eq ""} { set text [$object name] }
        }
    }

    return $text
}

proc ::InstallAPI::GetInstallSize { args } {
    ::InstallAPI::ParseArgs _args $args {
        -object     { string  0 "" }
        -activeonly { boolean 0 1  }
    }

    set total      0
    set object     [::InstallJammer::ID $_args(-object)]
    set activeonly $_args(-activeonly)

    if {$object eq ""} {
        global info
        set setups [SetupTypes children]
        set object [::InstallJammer::FindObjByName $info(InstallType) $setups]
        if {$object eq ""} { return -1 }
    }

    set filegroups {}
    switch -- [$object type] {
        "setuptype" {
            foreach component [$object get Components] {
                if {$activeonly && ![$component active]} { continue }
                set size [$component get Size]
                if {$size ne ""} {
                    incr total $size
                } else {
                    eval lappend filegroups [$component get FileGroups]
                }
            }
        }

        "component" {
            foreach component [concat $object [$object children recursive]] {
                if {$activeonly && ![$component active]} { continue }
                set size [$component get Size]
                if {$size ne ""} {
                    incr total $size
                } else {
                    eval lappend filegroups [$component get FileGroups]
                }
            }
        }

        "filegroup" {
            set filegroups [list $object]
        }
    }

    foreach filegroup $filegroups {
        if {$activeonly && ![$filegroup active]} { continue }
        set size [$filegroup get Size]
        if {$size eq ""} { set size [$filegroup get FileSize] }
        incr total $size
    }

    return $total
}

proc ::InstallAPI::GetSelectedFiles { args } {
    global info

    ::InstallAPI::ParseArgs _args $args {
        -fileids { boolean 0 0 }
    }

    set setups [SetupTypes children]
    set setup  [::InstallJammer::FindObjByName $info(InstallType) $setups]

    if {$setup eq ""} { return }

    set files [list]
    foreach component [$setup get Components] {
        if {![$component active]} { continue }

        foreach filegroup [$component get FileGroups] {
            if {![$filegroup active]} { continue }

            foreach file [$filegroup children] {
                if {![$file active]} { continue }

                if {$_args(-fileids)} {
                    lappend files $file
                } else {
                    if {[$file is dir]} {
                        lappend files [$file destdir]
                    } else {
                        lappend files [$file destfile]
                    }
                }
            }
        }
    }

    return $files
}

proc ::InstallAPI::GetSystemPackageManager { args } {
    ::InstallAPI::ParseArgs _args $args {}

    if {[auto_execok rpm] ne ""} { return RPM }
    if {[auto_execok dpkg] ne ""} { return DPKG }
}

proc ::InstallAPI::GetWidgetChildren { args } {
    if {![::InstallJammer::InGuiMode]} { return }

    ::InstallAPI::ParseArgs _args $args {
        -includeparent { boolean 0 0 }
        -widget        { string 1 }
        -window        { string 0 }
    }

    set widget $_args(-widget)
    if {[info exists _args(-window)]} {
        set window $_args(-window)
    } else {
        set window $info(CurrentPane)
    }

    set widget [::InstallAPI::GetWidgetPath -widget $widget -window $window]
    if {$widget eq ""} { return }

    set widgets {}
    if {$_args(-includeparent)} { lappend widgets $widget }

    set class [winfo class $widget]
    if {$class eq "Frame" || $class eq "TFrame"} {
        eval lappend widgets [winfo children $widget]
    }

    return $widgets
}

proc ::InstallAPI::GetWidgetPath { args } {
    global conf
    global info

    if {![::InstallJammer::InGuiMode]} { return }

    ::InstallAPI::ParseArgs _args $args {
        -frame  { boolean 0 0 }
        -widget { string  1 }
        -window { string  0 }
    }

    set window noop
    set widget $_args(-widget)

    if {[info exists info(CurrentPane)]} { set window $info(CurrentPane) }

    ## Look to see if the widget is in the form of PANE.WIDGET
    lassign [split $_args(-widget) .] pane wid
    if {$wid ne ""} {
        set pane [::InstallJammer::ID $pane]
        if {[::InstallJammer::ObjExists $pane]} {
            set widget $wid
            set window $pane
        }
    }

    if {[info exists _args(-window)]} {
        set obj [::InstallJammer::ID $_args(-window)]
        if {[::InstallJammer::ObjExists $obj] && [$obj ispane]} {
            set window $obj
        }
    }

    set name [join [::InstallJammer::ID $widget] ""]

    if {[lsearch -exact $conf(ButtonWidgets) $name] > -1} {
        set name [string tolower [string map {Button ""} $name]]
        set widg [$info(Wizard) widget get $name]
    } else {
        if {[::InstallJammer::IsID $name]
            && [::InstallJammer::ObjExists $name]} {
            set widg [$name window]
        } else {
            if {![::InstallJammer::ObjExists $window]} { return }
            set widg [$window widget get $name]
        }

        if {![winfo exists $widg]} { return }
        if {$_args(-frame)} { return $widg }
        set class [winfo class $widg]
        if {$class eq "Frame" || $class eq "TFrame" || $class eq "Labelframe"} {
            foreach w [winfo children $widg] {
                set class [winfo class $w]
                if {$class eq "Label" || $class eq "TLabel"} { continue }
                set widg $w
                break
            }
        }
    }

    return $widg
}

proc ::InstallAPI::GetWindowsRegistryKeys { args } {
    ::InstallAPI::ParseArgs _args $args {
        -key { string 1 }
    }

    if {![catch { registry keys $_args(-key) } keys]} {
        return $keys
    }
}

proc ::InstallAPI::EnvironmentVariableExists { args } {
    ::InstallAPI::ParseArgs _args $args {
        -variable { string 1 }
    }

    return [info exists ::env($_args(-variable))]
}

proc ::InstallAPI::Exit { args } {
    global conf
    global info

    ::InstallAPI::ParseArgs _args $args {
        -exitcode { string 0 }
        -exittype { choice 0 "finish" {cancel finish} }
    }

    if {[info exists _args(-exitcode)]} {
        set conf(ExitCode) $_args(-exitcode)
    }

    if {$_args(-exittype) eq "cancel"} {
        set info(WizardCancelled) 1
    }

    foreach command {::Exit ::InstallJammer::exit ::exit} {
        if {[::InstallJammer::CommandExists $command]} {
            $command
        }
    }
}

proc ::InstallAPI::LanguageAPI { args } {
    ::InstallAPI::ParseArgs _args $args {
        -do       { choice 1 "" "setlanguage" }
        -language { string 0 "" }
    }

    global info

    if {$_args(-do) eq "setlanguage"} {
        set code [::InstallJammer::GetLanguageCode $_args(-language)]
        if {$code eq ""} { return 0 }
        debug "Setting language to $code"
        set info(Language) $code
        ::msgcat::mclocale ""
        ::msgcat::mclocale en $info(Language)
        ::InstallJammer::UpdateWidgets -buttons 1
    }

    return 1
}

proc ::InstallAPI::LoadMessageCatalog { args } {
    ::InstallAPI::ParseArgs _args $args {
        -data     { string 0 }
        -dir      { string 0 }
        -encoding { string 0 }
        -file     { string 0 }
        -language { string 0 }
        -object   { string 0 }
    }

    set code ""
    if {[info exists _args(-language)]} {
        set code [::InstallJammer::GetLanguageCode $_args(-language)]
        if {$code eq ""} {
            return -code error "Invalid language '$_args(-language)'"
        }
    }

    set langs {}
    set files {}
    if {[info exists _args(-dir)]} {
        if {![file exists $_args(-dir)]} {
            return -code error "Directory '$_args(-dir)' does not exist."
        }

        foreach file [recursive_glob $_args(-dir) *.msg] {
            lappend files $file
            if {$code ne ""} {
                lappend langs $code
            } else {
                lappend langs [file root [file tail $file]]
            }
        }
    }

    if {[info exists _args(-file)]} {
        if {![file exists $_args(-file)]} {
            return -code error "File '$_args(-file)' does not exist."
        }

        lappend files $_args(-file)
        if {$code ne ""} {
            lappend langs $code
        } else {
            lappend langs [file root [file tail $_args(-file)]]
        }
    }

    if {[info exists _args(-object)]} {
        set obj [::InstallJammer::ID $_args(-object)]
        if {![::InstallJammer::ObjExists $obj]} {
            return -code error "Object '$_args(-object)' does not exist."
        }
        if {[$obj type] ne "file"} {
            return -code error "Object '$_args(-object)' is not a file object."
        }

        lappend files [$obj srcfile]
        if {$code ne ""} {
            lappend langs $code
        } else {
            lappend langs [file root [file tail [$obj name]]]
        }
    }

    foreach file $files lang $langs {
        set opts {}
        if {[info exists _args(-encoding)]} {
            lappend opts -encoding $_args(-encoding)
        }

        set data [eval read_textfile [list $file] r $opts]
        if {[catch { ::msgcat::mcmset $lang $data } error]} {
            return -code error "error reading message catalog '$file': $error"
        }
    }

    if {[info exists _args(-data)]} {
        if {$code eq ""} {
            return -code error "You must specify -language with -data"
        }
        lappend langs $code
        ::msgcat::mcmset $code $_args(-data)
    }

    return [lsort -unique $langs]
}

proc ::InstallAPI::ModifyWidget { args } {
    global conf
    global info
    global hidden

    if {![::InstallJammer::InGuiMode]} { return }

    ::InstallAPI::ParseArgs _args $args {
        -state   { choice 0 "" {disabled hidden normal readonly}}
        -widget  { string 1 }
        -window  { string 0 }
    }

    if {[info exists _args(-window)]} {
        set window $_args(-window)
    } else {
        set window $info(CurrentPane)
    }

    foreach widget [split $_args(-widget) \;] {
        foreach widget [::InstallAPI::GetWidgetChildren -window $window \
            -widget $widget -includeparent 1] {
            if {[info exists _args(-state)]} {
                set state $_args(-state)
                if {$state eq "hidden" && ![info exists hidden($widget)]} {
                    set manager [winfo manager $widget]
                    set options [$manager info $widget]
                    set hidden($widget) \
                        [concat $manager configure $widget $options]
                    $manager forget $widget
                } elseif {$state eq "normal" && [info exists hidden($widget)]} {
                    eval $hidden($widget)
                    unset hidden($widget)
                } else {
                    $widget configure -state $state
                }
            }
        }
    }
}

proc ::InstallAPI::ParseArgs { _arrayName _arglist optionspec } {
    if {[verbose]} { debug "API Call: [info level -1]" }

    upvar 1 $_arrayName array

    if {[expr {[llength $_arglist] % 2}]} {
        if {$_arglist ne "-?"} {
            set proc [lindex [info level -1] 0]
            return -code error "invalid number of arguments passed to $proc:\
                    all arguments must be key-value pairs"
        }
    }

    array set options {
        -subst       { string  0 0 }
        -errorvar    { string  0 }
        -returnerror { boolean 0 }
    }

    array set options $optionspec

    set optionlist [lsort [array names options]]

    set required [list]
    foreach option $optionlist {
        if {[lindex $options($option) 1]} {
            lappend required $option
        } elseif {[llength $options($option)] > 2} {
            set array($option) [lindex $options($option) 2]
        }
    }

    if {(![llength $_arglist] && [llength $required]) || $_arglist eq "-?"} {
        set help "Usage: [lindex [info level -1] 0] ?option value ...?"
        append help "\n\nOptions:"
        foreach option $optionlist {
            set type     [lindex $options($option) 0]
            set required [lindex $options($option) 1]
            set default  [lindex $options($option) 2]
            set choices  [lindex $options($option) 3]

            append help "\n\t"

            if {!$required} { append help ? }
            append help $option

            if {$type eq "choice"} {
                append help " [join $choices " | "]"
            } elseif {$type eq "boolean"} {
                append help " 0 | 1"
            } else {
                append help " [string range $option 1 end]"
            }

            if {$default ne ""} { append help " (Default: $default)" }

            if {!$required} { append help ? }
        }

        return -code error $help
    }

    if {[expr {[llength $_arglist] % 2}]} {
        return -code error "invalid number of arguments"
    }

    foreach {option value} $_arglist {
        set option [string tolower $option]

        if {![info exists options($option)]} {
            return -code error "invalid option $option"
        }

        if {$option eq "-do"} { set value [join [string tolower $value] ""] }
        set array($option) $value

        set type [lindex $options($option) 0]
        if {$type eq "string"} {
            if {$array(-subst)} {
                set array($option) [::InstallJammer::SubstText $value]
            }
        } elseif {$type eq "boolean"} {
            if {![string is boolean -strict $value]} {
                return -code error "invalid boolean value for $option"
            }
        } elseif {$type eq "choice"} {
            set values [lindex $options($option) 3]
            if {[lsearch -exact $values $value] < 0} {
                set x "[string range $option 1 end] value"
                return -code error [BWidget::badOptionString $x $value $values]
            }
        }
    }

    foreach option $required {
        if {![info exists array($option)]} {
            return -code error "missing required option $option"
        }
    }

    unset array(-subst)

    if {![info exists array(-returnerror)]} {
        set array(-returnerror) 1
        if {[info exists array(-errorvar)]} {
            set array(-returnerror) 0
            uplevel 1 [list upvar 1 $array(-errorvar) error]
        }
    }
}

proc ::InstallAPI::PromptForDirectory { args } {
    global conf

    ::InstallJammer::SetDialogArgs ChooseDirectory _args

    ::InstallAPI::ParseArgs _args $args {
        -title         { string 0 "<%PromptForDirectoryTitle%>"}
        -message       { string 0 "<%PromptForDirectoryMessage%>"}
        -newfoldertext { string 0 "<%PromptForDirectoryNewFolderText%>"}
        -variable      { string 0 }
        -initialdir    { string 0 }
        -normalize     { string 0 "platform" }
        -virtualtext   { string 0 }
    }

    set normalize $_args(-normalize)
    unset _args(-normalize)

    if {[info exists _args(-virtualtext)]} {
        set _args(-variable) ::info($_args(-virtualtext))
        unset _args(-virtualtext)
    }

    if {[info exists _args(-variable)]} {
        set varName $_args(-variable)
        upvar 1 $varName dir
        unset _args(-variable)
    }

    if {[info exists _args(-initialdir)]} {
        set dir $_args(-initialdir)
    } elseif {[info exists dir]} {
        set _args(-initialdir) $dir
    }

    foreach x {-title -message -newfoldertext} {
        set _args($x) [::InstallJammer::SubstText $_args($x)]
    }
    set _args(-oktext)      [::InstallJammer::SubstText "<%OK%>"]
    set _args(-canceltext)  [::InstallJammer::SubstText "<%Cancel%>"]

    if {$_args(-usenative)} {
        set res [eval ::ij_chooseDirectory [array get _args]]
    } else {
        unset -nocomplain _args(-usenative)
        if {[llength $conf(ParentWindow)] > 1} {
            wm withdraw [lindex $conf(ParentWindow) end]
            set _args(-parent) [::InstallJammer::TransientParent]
        }

        set res [eval ::ChooseDirectory .__choose_directory [array get _args]]

        if {[llength $conf(ParentWindow)] > 1} {
            wm deiconify [lindex $conf(ParentWindow) end]
        }
    }

    if {$res ne ""} {
        set dir $res
        if {$conf(windows) && [file exists $dir]} {
            set dir [file attributes $dir -longname]
        }

        set dir [::InstallJammer::Normalize $dir $normalize]

        if {[info exists varName]} { set $varName $dir }

        ::InstallJammer::UpdateWidgets

        return $dir
    }
}

proc ::InstallAPI::PromptForFile { args } {
    global conf
    
    ::InstallJammer::SetDialogArgs ChooseFile _args

    ::InstallAPI::ParseArgs _args $args {
        -type             { choice  0 "open" {open save} }
        -title            { string  0 }
        -message          { string  0 }
        -variable         { string  0 }
        -multiple         { boolean 0 }
        -normalize        { string  0 "platform" }
        -filetypes        { string  0 }
        -initialdir       { string  0 }
        -initialfile      { string  0 }
        -virtualtext      { string  0 }
        -defaultextension { string  0 }
    }

    set normalize $_args(-normalize)
    unset _args(-normalize)

    if {[info exists _args(-virtualtext)]} {
        set _args(-variable) ::info($_args(-virtualtext))
        unset _args(-virtualtext)
    }

    if {[info exists _args(-variable)]} {
        set varName $_args(-variable)
        upvar 1 $varName file
        unset _args(-variable)
    }

    if {$_args(-usenative)} {
        set type [string toupper $_args(-type) 0]
        set res  [eval [list ij_get${type}File] [array get _args]]
    } else {
        unset -nocomplain _args(-usenative)

        if {[llength $conf(ParentWindow)] > 1} {
            wm withdraw [lindex $conf(ParentWindow) end]
            set _args(-parent) [::InstallJammer::TransientParent]
        }

        set res [eval ::ChooseFile .__choose_file [array get _args]]

        if {[llength $conf(ParentWindow)] > 1} {
            wm deiconify [lindex $conf(ParentWindow) end]
        }
    }

    if {$res ne ""} {
        set file $res
        if {$conf(windows) && [file exists $file]} {
            set file [file attributes $file -longname]
        }

        set file [::InstallJammer::Normalize $file $normalize]

        if {[info exists varName]} { set $varName $file }

        ::InstallJammer::UpdateWidgets

        return $file
    }
}

proc ::InstallAPI::PropertyFileAPI { args } {
    ::InstallAPI::ParseArgs _args $args {
        -array       { string 1 }
        -do          { choice 1 "" {append data keys read set unset write}}
        -file        { string 0 }
        -key         { string 0 }
        -line        { string 0 }
        -separator   { string 0 "=" }
        -value       { string 0 }
    }

    upvar 1 $_args(-array) array

    set sep $_args(-separator)
    if {$_args(-do) eq "read"} {
        if {![info exists _args(-file)]} {
            return -code error "missing required option -file"
        }

        if {![info exists array(!keys)]} { set array(!keys) {} }

        set fp [open $_args(-file)]

        set i -1
        set append 0
        while {[gets $fp line] != -1} {
            incr i
            lappend array(!lines) $line
            set trimmed [string trim $line]

            ## Skip empty lines.
            if {![string length $trimmed]} { set append 0; continue }

            ## Skip comments.
            set x [string index $trimmed 0]
            if {$x eq "#" || $x eq "!"} { continue }

            set noback [string trimright $trimmed \\]

            if {!$append} {
                if {![regexp -indices {[^\\][:=]} $noback indexes]} {
                    ## We couldn't find a key separator.  The whole line
                    ## is the key, and the value is empty.
                    set array($trimmed) ""
                    continue
                }

                set idx1 [lindex $indexes 0]
                set idx2 [expr {[lindex $indexes 1] + 1}]
                set key  [string trim [string range $noback 0 $idx1]]
                set array($key) \
                    [string trimleft [string range $noback $idx2 end]]
                if {[lsearch -exact $array(!keys) $key] < 0} {
                    lappend array(!keys) $key
                }
                lappend array($key!lines) $i
            } else {
                append array($key) $noback
                lappend array($key!lines) $i
            }

            ## See if the last character of the line is a \.
            ## If so, we want to append the next line to our
            ## current line before processing it.
            set chk    [string length $noback]
            set len    [string length $trimmed]
            set append [expr {($len - $chk != 0) && ($len - $chk % 2)}]
        }

        close $fp
    } elseif {$_args(-do) eq "write"} {
        if {![info exists _args(-file)]} {
            return -code error "missing required option -file"
        }

        set data [::InstallAPI::PropertyFileAPI -do data -array array]

        set fp [open $_args(-file) w]
        puts $fp $data
        close $fp
    } elseif {$_args(-do) eq "set"} {
        if {![info exists _args(-key)]} {
            return -code error "missing required option -key"
        }
        if {![info exists _args(-value)]} {
            return -code error "missing required option -value"
        }

        if {![info exists array(!lines)]} { set array(!lines) {} }

        set key   $_args(-key)
        set value $_args(-value)
        set array($key) $value
        if {[info exists array($key!lines)]} {
            foreach x [lreverse $array($key!lines)] {
                set array(!lines) [lreplace $array(!lines) $x $x]
            }
            set array(!lines) [linsert $array(!lines) $x "$key$sep$value"]
            set array($key!lines) $x
        } else {
            lappend array(!keys) $key
            lappend array(!lines) "$key$sep$value"
            set array($key!lines) [expr {[llength $array(!lines)] - 1}]
        }
    } elseif {$_args(-do) eq "unset"} {
        if {![info exists _args(-key)]} {
            return -code error "missing required option -key"
        }

        set key $_args(-key)
        unset -nocomplain array($key)
        if {[info exists array($key!lines)] && [info exists array(!lines)]} {
            foreach x [lreverse $array($key!lines)] {
                set array(!lines) [lreplace $array(!lines) $x $x]
            }
            unset array($key!lines)
        }
        if {[info exists array(!keys)]} {
            set array(!keys) [lremove $array(!keys) $key]
        }
    } elseif {$_args(-do) eq "append"} {
        if {![info exists _args(-line)]} {
            return -code error "missing required option -line"
        }
        lappend array(!lines) $_args(-line)
    } elseif {$_args(-do) eq "data"} {
        set lines {}
        if {[info exists array(!lines)]} {
            set lines $array(!lines)
        } elseif {[info exists array(!keys)]} {
            foreach key $array(!keys) {
                if {![info exists array($key)]} { continue }
                lappend lines "$key$sep$array($key)"
            }
        } else {
            foreach key [lsort [array names array]] {
                if {[string match "*!*" $key]} { continue }
                lappend lines "$key$sep$array($key)"
            }
        }

        return [join $lines \n]
    } elseif {$_args(-do) eq "keys"} {
        if {[info exists array(!keys)]} { return $array(!keys) }
    }

    return
}

proc ::InstallAPI::ReadInstallInfo { args } {
    global conf
    global info

    ::InstallAPI::ParseArgs _args $args {
        -array          { string 1 }
        -prefix         { string 0 "" }
        -installid      { string 0 "" }
        -applicationid  { string 0 "<%ApplicationID%>" }
    }

    upvar 1 $_args(-array) array

    set pre $_args(-prefix)
    set pattern *.info
    if {$_args(-installid) ne ""} { set pattern $_args(-installid).info }

    set array(${pre}IDs)       {}
    set array(${pre}Count)     0
    set array(${pre}Exists)    0
    set array(${pre}DirExists) 0

    ## Check for old installer registry versions and update them to
    ## the current format before reading install info.
    ::InstallJammer::CheckAndUpdateInstallRegistry

    ::InstallJammer::GetInstallInfoDir
    set appid [sub $_args(-applicationid)]
    set dir [file join $info(InstallJammerRegistryDir) $appid]
    foreach file [glob -nocomplain -dir $dir $pattern] {
        set id [file root [file tail $file]]

        set array(${pre}Exists) 1

        set tmp(ID) $id
        ::InstallJammer::ReadPropertyFile $file tmp

        set mtime [file mtime $file]
        if {[info exists tmp(Date)]} { set mtime $tmp(Date) }

        lappend sort [list $mtime $id $tmp(Dir)]

        foreach {var val} [array get tmp] {
            set array($id,$var) $val
        }

        ## If we were passed an InstallID we can only match
        ## one install, so just break out after the first loop.
        if {$_args(-installid) ne ""} { break }
    }

    if {![info exists sort]} { return }

    set installids  {}
    set installdirs {}
    foreach list [lsort -integer -index 0 $sort] {
        set id  [lindex $list 1]
        set dir [lindex $list 2]

        if {$conf(windows)} {
            set dir [string tolower [::InstallJammer::Normalize $dir]]
        }

        lappend installids  $id
        lappend installdirs $dir
    }

    ## Grab the last ID by date and set the array's common
    ## values based on that ID.  This populates the array
    ## with the value of the most recent installation.
    foreach {var val} [array get array $id,*] {
        set var [string range $var [string length $id,] end]
        set array(${pre}$var) $val
    }

    set array(${pre}IDs)       $installids
    set array(${pre}Count)     [llength [lsort -unique $installdirs]]
    set array(${pre}DirExists) [file exists $array(${pre}Dir)]

    return $installids
}

proc ::InstallAPI::ResponseFileAPI { args } {
    ::InstallAPI::ParseArgs _args $args {
        -do          { choice  1 "" {add read remove write}}
        -file        { string  0 "" }
        -virtualtext { string  0 "" }
    }

    global conf
    global info

    if {$_args(-do) eq "add"} {
        foreach var $_args(-virtualtext) {
            if {[lsearch -exact $conf(SaveResponseVars) [lindex $var 0]] < 0} {
                lappend conf(SaveResponseVars) $var
            }
        }
    }

    if {$_args(-do) eq "remove"} {
        foreach var $conf(SaveResponseVars) {
            if {[lsearch -exact $_args(-virtualtext) [lindex $var 0]] < 0} {
                lappend vars $var
            }
        }
        set conf(SaveResponseVars) $vars
    }

    if {$_args(-do) eq "read" && [file exists $_args(-file)]} {
        ::InstallJammer::ReadPropertyFile $_args(-file) tmp

        foreach list $conf(SaveResponseVars) {
            lassign $list var type
            if {![info exists tmp($var)]} { continue }

            set val $tmp($var)
            if {$type eq "boolean"} {
                if {![string is boolean -strict $val]} { continue }
            } elseif {$type eq "list"} {
                set elems ""
                foreach elem [split $val ,] {
                    lappend elems [string trim $elem]
                }
                set val $elems
            }

            set info($var) $val
        }

        ::InstallJammer::SetupModeVariables
    }

    if {$_args(-do) eq "write" && $_args(-file) ne ""} {
        set fp [open $_args(-file) w]
        foreach list $conf(SaveResponseVars) {
            lassign $list var type

            set val [sub "<%$var%>"]
            if {$val eq "<%$var%>"} { continue }

            if {$type eq "boolean"} {
                if {[string is true -strict $val]} { set val "Yes" }
                if {[string is false -strict $val]} { set val "No" }
            } elseif {$type eq "list"} {
                set val [join $val ,]
            }

            puts $fp "$var: $val"
        }
        close $fp
    }

    return $conf(SaveResponseVars)
}

proc ::InstallAPI::RollbackInstall { args } {
    ::InstallJammer::CleanupCancelledInstall
}

proc ::InstallAPI::SetActiveSetupType { args } {
    global conf
    global info

    ::InstallAPI::ParseArgs _args $args {
        -setuptype  { string  1 }
    }

    if {[::InstallJammer::ObjExists $_args(-setuptype)]} {
        set obj  $_args(-setuptype)
        set name [$obj name]

        if {![$obj is setuptype]} {
            return -code error "$obj is not a valid Setup Type object"
        }
    } else {
        set name $_args(-setuptype)
        set obj  [::InstallAPI::FindObjects -type setuptype -name $name]
        if {$obj eq ""} {
            return -code error "Could not find Setup Type '$name'"
        }
    }

    debug "Setting active setup type to $name ([$obj id])."

    set info(InstallType)   $name
    set info(InstallTypeID) [$obj id]
    unset -nocomplain conf(PopulatedSetupType)

    ::InstallJammer::SelectSetupType $info(InstallTypeID)

    foreach var [array names ::InstallJammer::Components] {
        set ::InstallJammer::Components($var) ""
    }

    set components [$info(InstallTypeID) get Components]
    foreach c [Components children recursive] {
        if {[lsearch -exact $components $c] < 0} {
            ::InstallAPI::ComponentAPI -components $c -active 0 -updateinfo 0
        } else {
            ::InstallAPI::ComponentAPI -components $c -active 1 -updateinfo 0
        }
    }

    ::InstallJammer::UpdateInstallInfo

    return $info(InstallTypeID)
}

proc ::InstallAPI::SetExitCode { args } {
    global conf

    ::InstallAPI::ParseArgs _args $args {
        -exitcode  { string 1 }
    }

    set conf(ExitCode) $_args(-exitcode)
}

proc ::InstallAPI::SetFileTypeEOL { args } {
    global conf

    ::InstallAPI::ParseArgs _args $args {
        -eol       { string 1 }
        -extension { string 1 }
    }

    set eol [string map {unix lf windows crlf} $_args(-eol)]
    foreach ext [split $_args(-extension) \;] {
        set conf(eol,$ext) $eol
    }
}

proc ::InstallAPI::SetInstallPassword { args } {
    ::InstallAPI::ParseArgs _args $args {
        -password  { string 1 }
    }

    crapvfs::setPassword $_args(-password)
}

proc ::InstallAPI::SetObjectProperty { args } {
    ::InstallAPI::ParseArgs _args $args {
        -object   { string 1 }
        -property { string 1 }
        -value    { string 1 }
    }

    set id [::InstallJammer::ID $_args(-object)]

    if {![::InstallJammer::ObjExists $id]} {
        return -code error "Error in ::InstallAPI::SetObjectProperty:\
                object \"$id\" does not exist"
    }

    $id set $_args(-property) $_args(-value)
}

proc ::InstallAPI::SetUpdateWidgets { args } {
    global conf

    if {![::InstallJammer::InGuiMode]} { return }

    ::InstallAPI::ParseArgs _args $args {
        -widgets  { string 1 }
    }

    set conf(UpdateWidgets) {}
    foreach widget $_args(-widgets) {
        lappend conf(UpdateWidgets) [join $widget ""]
    }
}

proc ::InstallAPI::SetVirtualText { args } {
    variable ::InstallJammer::UpdateVarCmds
    variable ::InstallJammer::AutoUpdateVars

    ::InstallAPI::ParseArgs _args $args {
        -action      { string  0 }
        -autoupdate  { boolean 0 }
        -command     { string  0 }
        -language    { string  0 None }
        -object      { string  0 }
        -value       { string  0 }
        -virtualtext { string  1 }
    }

    set val  ""
    set var  $_args(-virtualtext)
    set lang $_args(-language)

    if {$lang eq "None"} {
        upvar #0 ::InstallJammer::UpdateVarCmds  cmds
        upvar #0 ::InstallJammer::AutoUpdateVars vars
    } else {
        if {[string equal -nocase $lang "all"]} {
            set langs [::InstallJammer::GetLanguageCodes]
        } else {
            set langs [::InstallJammer::GetLanguageCode $lang]
        }
        if {![llength $langs]} {
            return -code error "invalid language '$lang'"
        }
        upvar #0 ::InstallJammer::UpdateTextCmds cmds
        upvar #0 ::InstallJammer::AutoUpdateText vars
    }

    if {[info exists _args(-object)]} {
        set object [::InstallJammer::ID $_args(-object)]
        set var $object,$var
    }
    
    if {[info exists _args(-value)]} {
        set val $_args(-value)

        if {$lang eq "None"} {
            set ::info($var) $val
        } else {
            foreach lang $langs {
                ::msgcat::mcset $lang $var $val
            }
            if {[info exists cmds($var)]} {
                uplevel #0 $cmds($var)
            }
        }
    }

    if {[info exists _args(-action)] && $_args(-action) ne ""} {
        set command [list ::InstallJammer::ExecuteActions $_args(-action)]
    }

    if {[info exists _args(-command)] && $_args(-command) ne ""} {
        set command $_args(-command)
    }

    if {[info exists command]} {
        lappend cmds($var) $command

        if {$lang eq "None"} {
            if {[info exists ::info($var)]} {
                uplevel #0 $command
            }
        } else {
            foreach lang $langs {
                if {[::msgcat::mcexists $var $lang]} {
                    uplevel #0 $command
                    break
                }
            }
        }
    }

    if {[info exists _args(-autoupdate)]} {
        set auto $_args(-autoupdate)
        if {$auto && ![info exists vars($var)]} {
            set vars($var) $val
            ::InstallJammer::UpdateWidgets -updateidletasks 1
        } elseif {!$auto && [info exists vars($var)]} {
            unset vars($var)
            ::InstallJammer::UpdateWidgets -updateidletasks 1
        }
    }
}

proc ::InstallAPI::SkipPane { args } {
    ::InstallAPI::ParseArgs _args $args {
        -pane { string 0 }
    }

    global conf

    if {![info exists _args(-pane)] || $_args(-pane) eq ""} {
        set conf(skipPane) 1
        set conf(moveToPane) stop
    } else {
        set pane [::InstallJammer::ID $_args(-pane)]
        if {![::InstallJammer::ObjExists $pane]} {
            return -code error "pane \"$pane\" does not exist"
        }

        lappend conf(panesToSkip) $pane
    }
}

proc ::InstallAPI::Stop { args } {
    global conf
    set conf(moveToPane) stop
}

proc ::InstallAPI::SubstVirtualText { args } {
    ::InstallAPI::ParseArgs _args $args {
        -virtualtext { string 1 }
    }

    return [::InstallJammer::SubstText $_args(-virtualtext)]
}

proc ::InstallAPI::URLIsValid { args } {
    ::InstallAPI::ParseArgs _args $args {
        -proxyhost           { string 0 "" }
        -proxyport           { string 0 "" }
        -returnerror         { boolean 0 0 }
        -url                 { string 1 }
    }

    package require http

    set return 0

    http::config -proxyhost $_args(-proxyhost)
    http::config -proxyport $_args(-proxyport)

    if {[catch { http::geturl $_args(-url) -validate 1 } tok]} {
        if {$_args(-returnerror)} {
            return -code error $tok
        }

        set error $tok
        return 0
    }

    upvar #0 $tok state

    set code [http::ncode $tok]

    if {$code == 200} {
        set return 1
    } elseif {$code == 302} {
        ## This URL is a redirect.  We need to fetch the redirect URL.
        array set meta $state(meta)

        if {![info exists meta(Location)]} {
            return -code error "302 Redirect without new Location"
        }

        set _args(-url) $meta(Location)
        debug "URL Redirected to $_args(-url)."

        set return [eval ::InstallAPI::URLIsValid [array get _args]]
    }

    http::cleanup $tok

    return $return
}

proc ::InstallAPI::VirtualTextAPI { args } {
    ::InstallAPI::ParseArgs _args $args {
        -do          { choice 1 "" "settype"}
        -type        { choice 0 "" "boolean directory"}
        -virtualtext { string 1 }
    }

    if {$_args(-do) eq "settype"} {
        if {![info exists _args(-type)]} {
            return -code error "missing required option -type"
        }

        foreach var $_args(-virtualtext) {
            set ::InstallJammer::VTTypes($var) $_args(-type)
        }
    }
}

proc ::InstallAPI::VirtualTextExists { args } {
    ::InstallAPI::ParseArgs _args $args {
        -language    { string 0 None }
        -virtualtext { string 1 }
    }

    return [::msgcat::mcexists $_args(-virtualtext) $_args(-language)]
}

proc ::InstallAPI::WizardAPI { args } {
    ::InstallAPI::ParseArgs _args $args {
        -checkconditions { boolean 0 0 }
        -do              { choice  1 "" {back next}}
        -exit            { boolean 0 1 }
    }

    global info

    set opts {1 0}
    if {$_args(-checkconditions)} { set opts {1 1} }

    if {$_args(-do) eq "back"} {
        eval ::InstallJammer::Wizard back $opts
    } elseif {$_args(-do) eq "next"} {
        set next [$info(Wizard) step next]
        if {$next eq ""} {
            if {$_args(-exit)} { ::InstallAPI::Exit }
            return
        }
        eval ::InstallJammer::Wizard next $opts
    }
}
Added lib/installkit.tcl.




























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

## Create a generic InstallKit from the current running process.
proc ::installkit::base { {installkit ""} args } {
    global conf
    global info

    if {[info exists conf(BuildingInstallkit)]} {
        ## An installkit is already being built.  We need to wait
        ## for that one to finish, and then we'll just return back
        ## to the caller.
        vwait ::conf(BuildingInstallkit)
    }

    set conf(BuildingInstallkit) 1

    if {$installkit eq ""} {
        set installkit [::InstallJammer::TmpDir installkit$info(Ext)]
    }

    set res 0
    if {![file exists $installkit]} {
        set res [catch {
            eval ::InstallJammer::Wrap -o [list $installkit] $args
        } err]
    }

    unset conf(BuildingInstallkit)

    if {$res} { return -code error $err }

    return [::InstallJammer::Normalize $installkit]
}

proc ::installkit::Mount { crapFile mountPoint } {
    crapvfs::mount $crapFile $mountPoint
}

proc ::installkit::Unmount { mountPoint } {
    crapvfs::unmount $mountPoint
}
Added lib/main.tcl.














































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

if {[info exists ::InstallJammer]} { return }

namespace eval ::InstallJammer {}

proc ::InstallJammer::DisplayUsageInformation { {message ""} } {
    global conf

    uplevel #0 source [list [file join $conf(lib) common.tcl]]

    append message {
Usage: installjammer ?options? ?--? ?projectFile?

Options:
    --                        denotes the end of options
    --build                   build the installers for the given project file
    --build-dir <directory>   directory to use for temporary build files
    --build-for-release       build the installers for final release
    --build-log-file          path to the file to log build messages in
    --control-script <file>   load script file before building
    --debug-log               run installjammer with a debug log
    --help                    display this information
    --output-dir <directory>  directory to store finished installers in
    --platform <platform>     specify a platform to add to the build list
    --quick-build             do a quick rebuild and not a full build
    --quiet                   only build errors will be reported
    --test                    test the installer when it is done building
    --test-without-installing test the installer without installing files
    --verbose                 output verbose logging when building
    --version                 display InstallJammer version information

    -D<virtualText> <value>   set <virtualText> to <value> before building
}

    ::InstallJammer::Message -message $message
    ::exit 0
}

proc ParseCommandLineArgs {} {
    global argv
    global conf
    global info

    set switches {
        --build
        --build-for-release
        --debug-log
        --quick-build
        --test
        --test-without-installing
        --quiet
        --verbose
        -v -version --version
        -help --help
	-b -t -S
    }

    set options {
        -d -p
	--build-dir
        --build-log-file
        --command-port
        --control-script
	--output-dir
        --platform
    }

    set len  [llength $argv]
    set args {}
    set file ""
    for {set i 0} {$i < $len} {incr i} {
	set arg [lindex $argv $i]

	if {[lsearch -exact $switches $arg] > -1} {
	    if {[info exists val]} {
	        lappend args [join $val]
		unset val
	    }

	    lappend args $arg ""
	} elseif {[lsearch -exact $options $arg] > -1
	    	    || [string match "-D*" $arg]} {
	    if {[info exists val]} {
	        lappend args [join $val]
		unset val
	    }

	    lappend args $arg
	} elseif {$arg eq "--"} {
	    if {[info exists val]} {
	        lappend args [join $val]
		unset val
	    }

	    set file [join [lrange $argv [incr i] end]]
	    break
	} else {
	    lappend val $arg
	}
    }

    if {[info exists val]} {
    	set file [join $val]
	unset val
    }

    foreach {opt val} $args {
	switch -glob -- $opt {
	    "--build" - "-b" {
                # Build the install of the given project.
		set conf(cmdline) 1
	    }

	    "--build-dir" {
		set conf(cmdline) 1
	    	set conf(BuildDir) $val
	    }

            "--build-for-release" {
		set conf(cmdline) 1
                set conf(buildForRelease) 1
            }

            "--build-log-file" {
                set conf(buildLogFile) $val
            }

            "--command-port" {
                set conf(commandPort) $val
            }

	    "--control-script" - "-d" {
		set conf(cmdline) 1
		lappend conf(CommandLineOptionFiles) $val
	    }

            "--debug-log" {
                set conf(debugLogFile) $val
            }

            "--help" - "-help" {
                ::InstallJammer::DisplayUsageInformation
            }

	    "--output-dir" {
		set conf(cmdline) 1
	    	set conf(OutputDir) $val
	    }

	    "--platform" - "-p" {
		set conf(cmdline) 1
		lappend conf(platformBuildList) $val
	    }

	    "--quiet" {
                # Supress messages to stdout.  Errors will go to stderr.
		set conf(silent) 1
	    }

            "--quick-build" {
		set conf(cmdline) 1
                set conf(rebuildOnly) 1
            }

	    "--test" - "-t" {
                # Build and then test the given project.
		set conf(cmdline) 1
		set conf(buildAndTest) 1
	    }

            "--test-without-installing" {
		set conf(buildAndTest) 1
                set conf(testInTestMode) 1
            }

	    "--verbose" {
		set conf(verbose) 1
	    }

            "--version" - "-version" - "-v" {
                puts "$conf(Version) ($conf(BuildVersion))"
                puts ""
                puts "InstallJammer version $conf(Version)"
                ::exit 0
            }

	    "-D*" { ; # Set an option in the info array.
		set opt [string range $opt 2 end]
		lappend conf(CommandLineOptions) $opt $val
	    }

	    default {
                ::InstallJammer::DisplayUsageInformation \
                        "\ninvalid option \"$opt\"\n"
	    }
	}
    }

    if {$conf(cmdline) && $file eq ""} {
        ::InstallJammer::DisplayUsageInformation
    }

    set argv {}
    if {$file ne ""} {
        if {[lsearch -exact $options $file] > -1
	    || [lsearch -exact $switches $file] > -1
	    || [string match "-D*" $file]} {
            ::InstallJammer::DisplayUsageInformation \
                "\nNo project file specified.\n"
        }

        if {![file exists $file]} {
            ::InstallJammer::DisplayUsageInformation \
                "\nProject file \"$file\" does not exist.\n"
        }

        set file [file normalize $file]
        if {[file isdirectory $file]} {
            set tail [file tail $file]
            if {[file exists [file join $file $tail.mpi]]} {
                set file [file join $file $tail.mpi]
            } else {
                set files [glob -nocomplain -type f -dir $file *.mpi]
                if {[llength $files] > 1} {
                    ::InstallJammer::DisplayUsageInformation \
                        "\nPlease specify which project file in $file.\n"
                }
                set file [lindex $files 0]
            }
        }

        set argv [list $file]
    }
}

proc ::InstallJammer::InstallJammerHome { {file ""} } {
    global conf

    if {[file exists [file join $conf(pwd) preferences]]} {
        set conf(home) $conf(pwd)
        set conf(InstallJammerHome) $conf(pwd)
    }

    if {![info exists conf(home)] || ![info exists conf(InstallJammerHome)]} {
        if {[info exists env(USERPROFILE)]} {
            set home $env(USERPROFILE)
        }

        if {[info exists env(HOME)]} {
            set home $env(HOME)
        }

        if {[info exists env(INSTALLJAMMER_HOME)]} {
            set home $env(INSTALLJAMMER_HOME)
        }

        if {![info exists home]} {
            switch $::tcl_platform(platform) {
                "windows" {
                    if {$conf(windows98)} {
                        set home [installkit::Windows::getFolder MYDOCUMENTS]
                    } else {
                        set home [installkit::Windows::getFolder PROFILE]
                    }
                }

		default {
		    set home [file normalize ~]
		}
            }
        }

        set conf(home) $home

        set ijhome [file join $conf(home) .installjammer]
        if {$conf(osx)} {
            set ijhome [file join ~ Library InstallJammer]
        }

        set conf(InstallJammerHome) [file normalize $ijhome]

        if {![file exists $conf(InstallJammerHome)]} {
            file mkdir $conf(InstallJammerHome)
        }
    }

    set return $conf(InstallJammerHome)
    if {$file ne ""} { set return [file join $return $file] }

    return $return
}

proc ::InstallJammer::GuiInit {} {
    global conf

    DynamicHelp::configure -topbg #000000 -bd 1 -bg #FFFFDC -padx 2 -pady 3

    IconLibrary InstallJammerIcons

    option add *font                                        TkTextFont
    option add *Menu.tearOff                                0

    option add *Installjammer*highlightThickness            0
    option add *Installjammer*Listbox.background            #FFFFFF
    option add *Installjammer*ListBox.background            #FFFFFF
    option add *Installjammer*Listbox.selectBorderWidth     0
    option add *Installjammer*Entry.selectBorderWidth       0
    option add *Installjammer*Text.selectBorderWidth        0
    option add *Installjammer*Menu.activeBorderWidth        0
    option add *Installjammer*Menu.highlightThickness       0
    option add *Installjammer*Menu.borderWidth              2
    option add *Installjammer*Menubutton.activeBorderWidth  2
    option add *Installjammer*Menubutton.highlightThickness 0
    option add *Installjammer*Menubutton.borderWidth        2
    option add *Installjammer*Tree.background               #FFFFFF
    option add *Installjammer*Properties*editfinishcommand  \
        [list ::InstallJammer::EditFinishProperty %W %n]

    option add *Tree*highlightThickness                     0
    option add *ComboBox*Entry*background                   #FFFFFF

    #option add *Installjammer*Panedwindow.borderWidth       0
    #option add *Installjammer*Panedwindow.sashWidth         3
    #option add *Installjammer*Panedwindow.showHandle        0
    #option add *Installjammer*Panedwindow.sashPad           0
    #option add *Installjammer*Panedwindow.sashRelief        flat
    #option add *Installjammer*Panedwindow.relief            flat

    image create photo logo  -file [file join $conf(icons) logo.png]

    ## See if we have the tkdnd package for drag-and-drop support.  If not,
    ## create a dummy command so the dnd commands will do nothing.
    if {[catch { package require tkdnd }]} { proc ::dnd {args} {} }

    InitializeBindings

    Status "Creating images..."
    SetIconTheme
}

proc ::InstallJammer::Debug { string } {
    global conf
    if {$conf(debugLogFile) eq ""} { return }
    if {![info exists conf(debugfp)]} {
        set home [::InstallJammer::InstallJammerHome]
        set conf(debugfp) [open $conf(debugLogFile) w]
    }
    puts $conf(debugfp) $string
}

proc ClearStatus {} {
    set ::conf(status) ""
}

proc ::InstallJammer::StatusPrefix { {prefix ""} } {
    set ::conf(statusPrefix) $prefix
    Status ""
}

proc Status { string {time ""} } {
    global conf
    if {![info exists ::tk_patchLevel]} { return }
    if {[winfo exists .splash]} {
	.splash.c itemconfigure $::widg(SplashText) -text $string
        ::InstallJammer::Debug $string
    } else {
	set conf(status) $conf(statusPrefix)$string
    }
    if {[info exists conf(statusTimer)]} { after cancel $conf(statusTimer) }
    if {$time ne ""} { set conf(statusTimer) [after $time ClearStatus] }

    update idletasks
}

proc init {} {
    global info
    global conf
    global Components
    global SetupTypes
    global preferences

    catch { wm withdraw . }
    catch { console hide }

    set conf(osx)     [string equal $::tcl_platform(os) "Darwin"]
    set conf(unix)    [expr {[string equal $::tcl_platform(platform) "unix"]
			&& !$conf(osx)}]
    set conf(windows) [string equal $::tcl_platform(platform) "windows"]

    set conf(windows98) 0
    if {$conf(windows) && $::tcl_platform(osVersion) < 5.0} {
        set conf(windows98) 1
    }

    set conf(vista) 0
    if {$conf(windows) && $::tcl_platform(osVersion) >= 6.0} {
        set conf(vista) 1
    }

    array set conf {
        Version                 1.2.15
	InstallJammerVersion	1.2.15.2
	projectLoaded		0
	silent			0
        verbose                 0
	cmdline			0
	modified		0
        filesModified           0
        exiting                 0
        closing                 0
	loading			0
	building		0
        statusPrefix            ""
        renameAfterId           ""
        demo                    0
	stop			.stop
	pause			.pause
	RecentProjects		{}
        buildStopped            0
        buildForRelease         0
	buildMainTclOnly	0
        fullBuildRequired       0
	saveMainTcl		1
	logBuild		1
	buildAndTest		0
        testInTestMode          0
	backgroundBuild 	1
	rebuildOnly		0
	SaveTempDir		0
	TestWithoutFiles	0
	TestAllDefaults		0
	TestSilent		0
        TestConsole             0
	TestWithConsole		0
        SelectedProject         ""
	ThemeDirs		{Install Uninstall}
        DefaultTheme            "Modern_Wizard"
        ThemeSourceDirs         {Install Uninstall Common}
        Tabs                    {Product}
        TestCommandLineOptions  {}
        VirtualTextLanguage     "None"
        Archives                {}
        TreeFocus               ""
        clipboard               {}
        debugLogFile            ""

        TestUninstallSilentMode         0
        TestUninstallConsoleMode        0
        TestUninstallWithConsole        0
        TestUninstallWithoutFiles       0
        TestUninstallCommandLineOptions {}

        InstallTypes {Common Standard Default Console Silent ActionGroups}

        InstallModes            {Console Default Silent Standard}
        UninstallModes          {Console Silent Standard}

        InstallsDir             "InstallJammerProjects"

        HomePage                "http://www.installjammer.com/"
        HelpURL                 "http://www.installjammer.com/docs/"
        ForumsURL               "http://www.installjammer.com/forums/"
        HelpTopic               "Welcome"
        DefaultHelpTopic        "Welcome"

        PaneCheckConditions {
            "After Pane is Cancelled"
            "Before Next Pane is Displayed"
            "Before Pane is Cancelled"
            "Before Pane is Displayed"
            "Before Pane is Finished"
            "Before Previous Pane is Displayed"
        }

        ActionCheckConditions {
            "Before Action is Executed"
            "Before Next Action is Executed"
        }
    }

    set conf(CompressionMethods) {lzma "lzma (solid)" none zlib "zlib (solid)"}

    if {![catch { package require miniarc::crap::lzma }]} {
        set conf(CompressionMethods) {none zlib "zlib (solid)"}
    }

    if {![catch { package require miniarc::tar }]} {
        lappend conf(Archives) TarArchive
    }

    if {![catch { package require miniarc::zip }]} {
        lappend conf(Archives) ZipArchive
    }

    if {$conf(windows)} {
        set conf(InstallsDir) "My InstallJammer Projects"
        if {$::tcl_platform(osVersion) > 5.1} {
            set conf(InstallsDir) "InstallJammer Projects"
        }
    } elseif {$conf(osx)} {
        set conf(InstallsDir) "projects"
    }

    array set preferences {
        CustomThemeDir          ""
        CustomActionDir         ""
        CustomConditionDir      ""
	Theme			crystal
        Editor                  ""
	HelpBrowser		""
        RecentProjects          {}

        CheckForUpdates         0
        UseProxyServer          0
        ProxyHost               ""
        ProxyPort               8080
    }

    if {$conf(windows)} {
	set preferences(HelpBrowser) "Windows Help"
    }

    ## A list of variables to store in the install when building.
    ## Only variables in this list and the platform specific
    ## variables will be stored from the info array.
    set conf(InstallVars) {
        AllowLanguageSelection
	AppName
        ApplicationID
        ApplicationURL
        BuildVersion
	CancelledInstallAction
	CleanupCancelledInstall
	Company
        CompressionMethod
        Copyright
        DefaultLanguage
        DefaultToSystemLanguage
        EnableResponseFiles
        ExtractSolidArchivesOnStartup
        Icon
        Image
	IncludeDebugging
	InstallVersion
        MajorVersion
        MinorVersion
        PackageDescription
        PackageLicense
        PackageMaintainer
        PackageName
        PackagePackager
        PackageRelease
        PackageSummary
        PackageVersion
        PatchVersion
        ShortAppName
        UpgradeApplicationID
	Version
        WizardHeight
        WizardWidth
    }

    ## A list of platform-specific variables that get stored in the
    ## install when building.
    set conf(PlatformVars) {
        DefaultDirectoryPermission
        DefaultFilePermission
        FallBackToConsole
        InstallDir
        InstallMode
        InstallType
        ProgramExecutable
        ProgramFolderAllUsers
        ProgramFolderName
        ProgramLicense
        ProgramName
        ProgramReadme
        PromptForRoot
        RequireAdministrator
        RequireRoot
        RootInstallDir
    }

    set conf(WindowsSpecialDirs) {
	DESKTOP
	INTERNET 
	PROGRAMS
	CONTROLS 
	PRINTERS
	PERSONAL 
	FAVORITES
	STARTUP 
	RECENT
	SENDTO 
	BITBUCKET
	STARTMENU 
	DESKTOPDIRECTORY
	DRIVES 
	NETWORK
	NETHOOD 
	FONTS
	TEMPLATES 
	APPDATA
	PRINTHOOD 
	ALTSTARTUP
	INTERNET_CACHE 
	COOKIES
	HISTORY 
	COMMON_ALTSTARTUP 
	COMMON_FAVORITES
	COMMON_STARTMENU
	COMMON_PROGRAMS 
	COMMON_STARTUP
	COMMON_DESKTOPDIRECTORY 
	WINDOWS
	SYSTEM
	SYSTEM32
	PROGRAM_FILES
	QUICK_LAUNCH
    }
    set conf(WindowsSpecialDirs) [lsort $conf(WindowsSpecialDirs)]

    set ::InstallJammer $conf(InstallJammerVersion)

    namespace eval ::InstallJammer {}
    namespace eval ::InstallJammer::theme {}
    namespace eval ::InstallJammer::preview {}
    namespace eval ::InstallJammer::actions {}
    namespace eval ::InstallJammer::loadtheme {}
    namespace eval ::InstallJammer::conditions {}
    namespace eval ::InstallJammer::loadactions {}
    namespace eval ::InstallJammer::loadconditions {}

    set conf(gui)     $::tcl_platform(platform)
    set conf(lib)     [file join $conf(pwd) lib]
    set conf(help)    [file join $conf(pwd) docs]
    set conf(icons)   [file join $conf(lib) Icons]
    set conf(images)  [file join $conf(pwd) Images]
    set conf(winico)  [file join $conf(pwd) Images "Windows Icons"]
    set conf(bwidget) [file join $conf(lib) BWidget]

    if {$conf(osx)} { set conf(gui) "osx" }

    ::ParseCommandLineArgs

    ::InstallJammer::Debug "Initializing InstallJammer..."

    uplevel #0 source [list [file join $conf(lib) common.tcl]]
    uplevel #0 source [list [file join $conf(lib) utils.tcl]]

    if {[info exists conf(commandPort)]} {
        set conf(commandSock) [socket -server \
            ::InstallJammer::AcceptCommandConnection $conf(commandPort)]
    }

    set conf(bin) [file join $conf(pwd) Binaries [::InstallJammer::Platform]]

    ## We want our directories in front incase the user has an older
    ## version of the libraries we're using.
    set ::auto_path [linsert $::auto_path 0 $conf(lib) $conf(bin)]

    set bindir [file dirname [info nameofexecutable]]
    if {!$conf(windows) && [lsearch -exact $::auto_path $bindir] < 0} {
        lappend ::auto_path $bindir
    }

    set verfile [file join $conf(pwd) .buildversion]
    set gitfile [file join $conf(pwd) .git refs heads v1.2]
    if {[file exists $verfile]} {
        set conf(BuildVersion) [string trim [read_file $verfile]]
    } elseif {[file exists $gitfile]} {
        set conf(BuildVersion) [string range [read_file $gitfile] 0 6]
    } else {
        set conf(BuildVersion) "unknown"
    }

    if {!$conf(cmdline)} {
	if {[catch { package require Tk } version]} {
	    puts "InstallJammer must be run in a graphical environment."
	    exit
	}

	wm withdraw .

        ::InstallJammer::Debug "Loading generic GUI code..."
        package require tile 0.5

	if {[package vcompare $version 8.5.0]} {
	    namespace import ::ttk::style
	}

	## Source in the common GUI code.
	uplevel #0 [list source [file join $conf(lib) gui-common.tcl]]

        ## Source in the platform-specific GUI code.
        uplevel #0 [list source [file join $conf(lib) gui-$conf(gui).tcl]]

        ## Display the splash screen.
        source [file join $conf(lib) splash.tcl]

        wm title    . "InstallJammer"
        wm client   . [info hostname]
        wm command  . [linsert $::argv 0 $::argv0]

        if {$conf(windows)} {
            wm iconbitmap . -default [file join $conf(icons) InstallJammer.ico]
        }

	Window.splash
	grab set .splash
	update idletasks

        Status "Loading libraries..."
    }

    ## Source in all the library files.
    foreach file [glob [file join $conf(lib) *.tcl]] {
        if {[string match "*gui-*" $file]} { continue }
        if {[string match "*common.tcl" $file]} { continue }
	uplevel #0 source [list $file]
    }

    ::InstallJammer::CommonInit

    Status "Loading user preferences..."

    ::InstallJammer::LoadPreferences

    Status "Loading actions..."

    ::InstallJammer::LoadActions

    Status "Loading conditions..."

    ::InstallJammer::LoadConditions

    Status "Loading messages..."
    ::InstallJammer::LoadMessages
    ::InstallJammer::LoadReservedVirtualText

    ## Establish a list of available install themes.
    ::InstallJammer::ThemeList

    ## Initialize some objects.
    Platform  ::PlatformObject
    ::PlatformObject set Active Yes

    ::InstallJammer::File      ::FileObject
    ::InstallJammer::FileGroup ::FileGroupObject
    ::InstallJammer::Component ::ComponentObject
    ::InstallJammer::SetupType ::SetupTypeObject
    ::InstallJammer::ActionGroup ::ActionGroupObject

    ## If we're running in command-line mode, we don't need to go any
    ## further.  If we're not in command-line mode, and we don't have
    ## a display, we exit out.  CheckRunStatus figures all this out.
    CheckRunStatus

    Status "Loading packages..."

    package require Tktags
    package require BWidget 2.0
    BWidget::use png
    BWidget::use ttk
    set ::BWidget::iconLibrary InstallJammerIcons

    if {$conf(osx)} {
        BWidget::use aqua
    }

    if {$conf(windows) && $::tcl_platform(osVersion) >= 5.0} {
        package require twapi
    }

    if {$conf(osx)} {
	set conf(installs) [::InstallJammer::InstallJammerHome projects]
    } elseif {$conf(unix)} {
	set conf(installs) [::InstallJammer::HomeDir $conf(InstallsDir)]
    } else {
	set docs [::InstallJammer::WindowsDir MYDOCUMENTS]
	set conf(installs) [file join $docs $conf(InstallsDir)]
    }

    if {![info exists preferences(ProjectDir)]
    	|| ![file exists $preferences(ProjectDir)]} {
        set preferences(ProjectDir) $conf(installs)
    } else {
	set conf(installs) $preferences(ProjectDir)
    }
    set conf(lastdir) $preferences(ProjectDir)

    file mkdir $conf(installs)

    if {$conf(unix)} {
        append ::env(PATH) ":[file join $conf(pwd) lib packages xdg-utils]"
    }

    ::InstallJammer::GuiInit

    return
}

proc main {} {
    global conf

    set base .installjammer

    Status "Building windows..."

    ## Build the main window first.
    Window show $base

    tag configure project -state disabled

    Window show $base

    raise .splash

    Status "InstallJammer loaded" 3000

    ## Hold the splash image for half a second and then fade it out.
    after 500 {
        ::InstallJammer::FadeWindowOut .splash 1
        image delete ::icon::splash
    }

    tkwait window .splash
    grab release  .splash

    UpdateRecentProjects

    #if {[GetPref CheckForUpdates]} {
        #::InstallJammer::DownloadVersionInfo
    #}

    if {[llength $::argv]} {
        set file [lindex $::argv 0]
        set file [file normalize $file]
        Open $file
    }

    if {[info exists conf(commandPort)]} {
        ::InstallJammer::SendReadySignal
    }

    return
}

if {!$tcl_interactive} { init; main }
Added lib/msgs/installer/ar.msg.




























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
RemoveDongleCaption
"\u202B\u0623\u062E\u0631\u062C \u0645\u0641\u062A\u0627\u062D \u0631\u062E\u0635\u0629 USB"

RemoveDongleMessage
"\u202B\u0625\u0630\u0627 \u0643\u0627\u0646 \u0645\u0641\u062A\u0627\u062D \u0631\u062E\u0635\u0629 USB \u0645\u0648\u0635\u0648\u0644\u0627 \u0628\u062C\u0647\u0627\u0632\u0643\u060C \u064A\u062C\u0628 \u0639\u0644\u064A\u0643 \u0625\u062E\u0631\u0627\u062C\u0647 \u0627\u0644\u0622\u0646 \u0642\u0628\u0644 \u0627\u0644\u0634\u0631\u0648\u0639 \u0628\u0639\u0645\u0644\u064A\u0629 \u0627\u0644\u062A\u0631\u0643\u064A\u0628.\n\u202B\n\u202B\u0644\u0627 \u062A\u062F\u062E\u0644 \u0645\u0641\u062A\u0627\u062D \u0631\u062E\u0635\u0629  USB\u062D\u062A\u0649 \u0625\u0639\u0644\u0627\u0645\u0643 \u0628\u0630\u0644\u0643."

InsertDongleCaption
"\u202B\u0623\u062F\u062E\u0644 \u0645\u0641\u062A\u0627\u062D \u0631\u062E\u0635\u0629 USB"

InsertDongleMessage
"\u202B\u0627\u0644\u0631\u062C\u0627\u0621 \u0625\u062F\u062E\u0627\u0644 \u0645\u0641\u062A\u0627\u062D \u0631\u062E\u0635\u0629 USB \u0627\u0644\u0622\u0646.\n\u202B\n\u202B\u0625\u0630\u0627 \u0643\u0627\u0646 \u0647\u0630\u0627 \u0627\u0644\u062A\u0631\u0643\u064A\u0628 \u0644\u0623\u0648\u0644 \u0645\u0631\u0629\u060C \u0625\u0646\u062A\u0638\u0631 \u0648\u064A\u0646\u062F\u0648\u0632 \u062D\u062A\u0649 \u062A\u062C\u062F \u0627\u0644\u0645\u0641\u062A\u0627\u062D (\u064A\u0645\u0643\u0646 \u0623\u0646 \u062A\u0633\u062A\u063A\u0631\u0642 \u0627\u0644\u0639\u0645\u0644\u064A\u0629 \u0628\u0636\u0639 \u062B\u0648\u0627\u0646). \u0639\u0646\u062F \u0638\u0647\u0648\u0631 \u0645\u0639\u0627\u0644\u062C \u0625\u0636\u0627\u0641\u0629 \u0627\u0644\u0645\u0643\u0648\u0646\u0627\u062A \u0627\u0644\u0635\u0644\u0628\u0629\u060C \u0639\u0644\u064A\u0643 \u0625\u062A\u0628\u0627\u0639 \u0627\u0644\u062E\u0637\u0648\u0627\u062A \u0623\u062F\u0646\u0627\u0647.\n\u202B\n\u202B1.	\u0625\u0630\u0627 \u0637\u0644\u0628 \u0645\u0646\u0643 \u0627\u0644\u0625\u062A\u0635\u0627\u0644 \u0644\u062A\u062D\u062F\u064A\u062B \u0627\u0644\u0648\u064A\u0646\u062F\u0648\u0632\u060C \u0625\u062E\u062A\u0627\u0631 '\u0644\u0627\u060C \u0644\u064A\u0633 \u0647\u0630\u0627 \u0627\u0644\u0648\u0642\u062A' \u062B\u0645 \u0623\u0646\u0642\u0631 \u0627\u0644\u062A\u0627\u0644\u064A.\n\u202B2.	\u0625\u062E\u062A\u0627\u0631 \u062A\u0631\u0643\u064A\u0628 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C \u062A\u0644\u0642\u0627\u0626\u064A\u0627\u064B \u062B\u0645 \u0623\u0646\u0642\u0631 \u0627\u0644\u062A\u0627\u0644\u064A.\n\u202B3.	\u0623\u0646\u0642\u0631 \u0625\u0646\u062A\u0647\u0627\u0621.\n\u202B4.	\u0623\u0643\u0645\u0644 \u0639\u0645\u0644\u064A\u0629 \u0627\u0644\u062A\u0631\u0643\u064A\u0628 \u0628\u0646\u0642\u0631\u0643 \u0627\u0644\u0646\u0627\u0644\u064A."

ApplicationReadmeText
"\u202B\u0645\u0644\u0641 \u0627\u0644\u0645\u0633\u0627\u0639\u062F \u0644\u0628\u0631\u0646\u0627\u0645\u062C <%AppName%>"

Back
"\u202B\u0631\u062C\u0648\u0639"

Browse
"\u202B\u0625\u0633\u062A\u0637\u0644\u0627\u0639..."

BuildFileText
"\u202B\u0628\u0646\u0627\u0621 <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"\u202B\u0628\u0646\u0627\u0621 \u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C..."

Cancel
"\u202B\u0625\u0644\u063A\u0627\u0621"

CleanupInstallText
"\u202B\u062A\u0646\u0638\u064A\u0641 \u0627\u0644\u062A\u0631\u0643\u064A\u0628..."

Close
"\u202B\u0623\u063A\u0644\u0642"

ConsolePauseQuitText
"-- Press space to continue or 'q' to quit --"

ConsolePauseText
"-- Press space to continue --"

ConsoleSelectDestinationText
"\u202B\u0623\u064A\u0646 \u062A\u0631\u064A\u062F \u062A\u0631\u0643\u064A\u0628 <%AppName%>\u061F"

CreateDesktopShortcutText
"\u202B\u0625\u0646\u0634\u0627\u0621 \u0637\u0631\u064A\u0642 \u0645\u062E\u062A\u0635\u0631 \u0644\u0633\u0637\u062D \u0627\u0644\u0645\u0643\u062A\u0628"

CreateQuickLaunchShortcutText
"\u202B\u0625\u0646\u0634\u0627\u0621 \u0625\u062E\u062A\u0635\u0627\u0631 \u0644\u0644\u062A\u0641\u0639\u064A\u0644 \u0627\u0644\u0633\u0631\u064A\u0639"

CustomInstallDescription
"\u202B\u0625\u062E\u062A\u0627\u0631 \u0645\u0643\u0648\u0646\u0627\u062A \u0645\u0641\u0635\u0644\u0629 \u0644\u0639\u0645\u0644\u064A\u0629 \u0627\u0644\u062A\u0631\u0643\u064A\u0628."

DirectoryPermissionText
"\u202B\u0644\u0627 \u064A\u0633\u0645\u062D \u0644\u0643 \u0628\u0627\u0644\u0643\u062A\u0627\u0628\u0629 \u0641\u064A \u0627\u0644\u0645\u062C\u0644\u062F <%Dir%>."

DownloadingFilesText
"\u202B\u062A\u0646\u0632\u064A\u0644 \u0645\u0644\u0641\u0627\u062A..."

ExitText
"\u202B\u0647\u0644 \u0623\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u0627\u0644\u062E\u0631\u0648\u062C \u0645\u0646 \u0647\u0630\u0627 \u0627\u0644\u0625\u0639\u062F\u0627\u062F\u061F"

FileBeingInstalledText
"\u202B\u0646\u0633\u062E <%FileBeingInstalled%>"

FileBeingUninstalledText
"\u202B\u062D\u0630\u0641 <%FileBeingUnistalled%>"

FileOverwriteText
"\u202B\u0627\u0644\u0645\u0644\u0641 <%FileBeingInstalled%> \u0645\u0648\u062C\u0648\u062F \u062D\u0627\u0644\u064A\u0627\u064B \u0647\u0644 \u062A\u0631\u064A\u062F \u0627\u0644\u0643\u062A\u0627\u0628\u0629 \u0641\u0648\u0642\u0647\u061F"

Finish
"\u202B\u0625\u0646\u062A\u0647\u0627\u0621"

GroupBeingInstalledText
"\u202B\u062A\u0631\u0643\u064A\u0628 <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"\u202B\u062D\u0630\u0641 <%GroupBeingUnistalled%>"

Help
"\u202B\u0645\u0633\u0627\u0639\u062F\u0629"

InstallApplicationText
"\u202B\u062A\u0631\u0643\u064A\u0628 <%AppName%>"

InstallationCompleteText
"\u202B\u0625\u0646\u062A\u0647\u0627\u0621 \u0639\u0645\u0644\u064A\u0629 \u0627\u0644\u062A\u0631\u0643\u064A\u0628."

InstallCompleteText
"\u202B\u0625\u0646\u062A\u0647\u0627\u0621 \u0639\u0645\u0644\u064A\u0629 \u062A\u0631\u0643\u064A\u0628 \u0627\u0644\u0645\u0644\u0641..."

InstallingApplicationText
"\u202B\u062A\u0631\u0643\u064A\u0628 <%AppName%>..."

InstallPrepareText
"\u202B\u0627\u0644\u062A\u062D\u0636\u064A\u0631 \u0644\u0644\u062A\u0631\u0643\u064A\u0628..."

InstallStartupText
"\u202B\u0633\u0648\u0641 \u064A\u062A\u0645\u0651 \u062A\u0631\u0643\u064A\u0628 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%> \u0639\u0644\u0649 \u062C\u0647\u0627\u0632\u0643.  \u0623\u0643\u0645\u0644\u061F"

LaunchApplicationText
"\u202B\u0625\u0646\u0637\u0644\u0627\u0642 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%>"

Next
"\u202B\u0627\u0644\u062A\u0627\u0644\u064A"

No
"\u202B\u0644\u0627"

OK
"\u202B\u0645\u0648\u0627\u0641\u0642"

ProgramFilesDescription
"\u202B\u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0627\u0644\u0645\u0634\u062A\u0631\u0643\u0629"

PromptForRootText
"\u202B\u0627\u0644\u0631\u062C\u0627\u0621 \u0625\u062F\u062E\u0627\u0644 \u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631."

RequireRootText
"\u202B\u064A\u062C\u0628 \u0623\u0646 \u062A\u0643\u0648\u0646 \u0627\u0644\u062C\u0630\u0631 \u0644\u0643\u064A \u062A\u0642\u0648\u0645 \u0628\u062A\u0634\u063A\u064A\u0644 \u0647\u0630\u0627 \u0627\u0644\u062A\u0631\u0643\u064A\u0628."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"\u202B\u0627\u0644\u062A\u0631\u0643\u064A\u0628 \u0627\u0644\u0625\u0639\u062A\u064A\u0627\u062F\u064A."

UninstallApplicationText
"\u202B\u0625\u0632\u0627\u0644\u0629 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%>"

UninstallPrepareText
"\u202B\u0627\u0644\u062A\u062D\u0636\u064A\u0631 \u0644\u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0646\u0631\u0646\u0627\u0645\u062C..."

UpdateRegistryText
"\u202B\u062A\u062D\u062F\u064A\u062B \u0633\u062C\u0644\u0651 Windows..."

UninstallingApplicationText
"\u202B\u0625\u0632\u0627\u0644\u0629 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%>..."

UninstallCompleteText
"\u202B\u0625\u0646\u062A\u0647\u0627\u0621 \u0625\u0632\u0627\u0644\u0629 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C."

UninstallStartupText
"\u202B\u0633\u0648\u0641 \u064A\u062A\u0645\u0651 \u062D\u0630\u0641 \u0646\u0647\u0627\u0626\u064A \u0644\u0644\u0628\u0631\u0646\u0627\u0645\u062C <%AppName%> \u0645\u0646 \u062C\u0647\u0627\u0632\u0643.  \u0647\u0644 \u0623\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u0647\u0630\u0627 \u0627\u0644\u062D\u0630\u0641\u061F"

UninstallLeftoverText
"\u202B\u0628\u0639\u0636 \u0627\u0644\u0645\u0643\u0648\u0646\u0627\u062A \u0644\u0645 \u064A\u062A\u0645\u0643\u0646 \u0645\u0646 \u062D\u0630\u0641\u0647\u0627.  \u0647\u0644 \u062A\u0631\u064A\u062F \u062D\u0630\u0641\u0647\u0627 (\u0644\u0627 \u064A\u0641\u0636\u0644 \u0630\u0644\u0643)\u061F"

VersionHelpText
"\u202B\u0647\u0630\u0647 \u0627\u0644\u0639\u0645\u0644\u064A\u0629 \u0633\u062A\u0642\u0648\u0645 \u0628\u062A\u0631\u0643\u064A\u0628 \u0628\u0631\u0646\u0627\u0645\u062C <%AppName%> \u0625\u0635\u062F\u0627\u0631 \u0631\u0642\u0645 <%Version%>."

ViewReadmeText
"\u202B\u062A\u0635\u0641\u062D \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0645\u0633\u0627\u0639\u062F"

Yes
"\u202B\u0646\u0639\u0645"

ConsolePause {
    Message
    "\u202B<%ConsolePauseText%>"
}

LocateJavaRuntime {
    PromptMessage
    "\u202B\u0627\u0644\u0631\u062C\u0627\u0621 \u0625\u0639\u0644\u0627\u0645\u0646\u0627 \u0623\u064A\u0646 \u0645\u0648\u0642\u0639 \u0628\u0631\u0646\u0627\u0645\u062C \u0648\u0642\u062A \u062A\u0634\u063A\u064A\u0644 Java"

    StatusMessage
    "\u202B\u0645\u062D\u0627\u0648\u0644\u0629 \u0625\u064A\u062C\u0627\u062F \u0648\u0642\u062A \u062A\u0634\u063A\u064A\u0644 Java..."
}

TextWindow {
    Title
    "\u202B\u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u0646\u0627\u0641\u0630\u0629"

    Caption
    "\u202B\u0639\u0646\u0648\u0627\u0646"

    Message
    "\u202B\u0636\u0639 \u0627\u0644\u0631\u0633\u0627\u0644\u0629 \u0647\u0646\u0627."

    CloseButton
    "\u202B<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/ca.msg.




























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
ApplicationReadmeText
"<%AppName%> Llegiu-me"

Back
"Retrocedeix"

Browse
"Examinar..."

BuildFileText
"Generant <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Generant el desinstal·lador..."

Cancel
"Cancel·lar"

CleanupInstallText
"Netejant la instal·lació..."

Close
"Tanca"

CreateDesktopShortcutText
"Crear icona a l'Escriptori"

CreateQuickLaunchShortcutText
"Crear icona a la Barra de Tasques"

CustomInstallDescription
"Seleccioni els components de la instal·lació."

DirectoryPermissionText
"No teniu permisos per a escriure a <%Dir%>."

ExitText
"De debò voleu sortir de la instal·lació?"

FileBeingInstalledText
"Copiant <%FileBeingInstalled%>"

FileBeingUninstalledText
"Eliminant <%FileBeingUninstalled%>"

Finish
"Finalitzar"

GroupBeingInstalledText
"Instal·lant <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"Eliminant <%GroupBeingUninstalled%>"

Help
"Ajuda"

InstallApplicationText
"Instal·lar <%AppName%>"

InstallCompleteText
"Instal·lació completa..."

InstallPrepareText
"Preparant la instal·lació..."

InstallStartupText
"Es va a instal·lar <%AppName%> en el seu equip. Voleu continuar?"

LaunchApplicationText
"Executar <%AppName%>"

Next
"Següent"

No
"No"

OK
"Si"

ProgramFilesDescription
"Arxius de Programa Comuns"

RequireRootText
"Necessiteu tenir permisos d'administrador per executar l'instal·lador."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Una instal·lació típica."

UninstallApplicationText
"Desinstal·lar <%AppName%>"

UninstallPrepareText
"Preparant la desinstal·lació..."

UpdateRegistryText
"Actualizant el Registre de Windows..."

UninstallStartupText
"S'eliminarà completament <%AppName%> del seu sistema. De debò ho desitgeu?"

UninstallLeftoverText
"No ha estat possible eliminar alguns components. Tot i així, desitgeu\
 eliminar-los? (no recomenat)"

ViewReadmeText
"Veure Llegiu-me"

Yes
"Si"


LocateJavaRuntime {
    PromptMessage
    "Si us plau, localitzeu el vostre Entorn d'Execució Java (JRE)"

    StatusMessage
    "Cercant l'Entorn d'Execució Java (JRE)..."
}

TextWindow {
    Title
    "Ròtul de la Finestra"

    Caption
    "Llegenda"

    Message
    "Missatge aquí."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/cs.msg.




























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# options: -encoding utf-8

ApplicationReadmeText
"ÄŒtiMÄ› pro <%AppName%>"

Back
"Zpět"

Browse
"Procházet..."

BuildFileText
"Vytváří se <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Vytváří se odinstalace..."

Cancel
"Zrušit"

CleanupInstallText
"ProÄisÅ¥uje se instalace..."

Close
"Zavřít"

ConsolePauseQuitText
"-- StisknÄ›te mezeru k pokraÄování nebo 'q' ke skonÄení --"

ConsolePauseText
"-- K pokraÄování stisknÄ›te mezeru --"

ConsoleSelectDestinationText
"Kam chcete nainstalovat <%AppName%>?"

CreateDesktopShortcutText
"Vytvořit zástupce na ploše"

CreateQuickLaunchShortcutText
"Vytvořit zástupce snadného spuštění"

CustomInstallDescription
"Zvolte vlastní souÄásti k instalaci."

DirectoryNameErrorText
"Název složky nemůže obsahovat žádný z následujících znaků:
        \\ / : * ? \" < > |"

DirectoryPermissionText
"Nemáte oprávnění zapisovat do <%Dir%>."

DisplayName
"<%AppName%>"

DownloadingFilesText
"Stahování souborů..."

ExitText
"Opravdu chcete ukonÄit tento instalátor?"

FileBeingInstalledText
"Kopírování <%FileBeingInstalled%>"

FileBeingUninstalledText
"Odstraňování <%FileBeingUninstalled%>"

FileOverwriteText
"Soubor <%FileBeingInstalled%> již existuje. Chcete jej přepsat?"

Finish
"DokonÄit"

GroupBeingInstalledText
"Instalace <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"Odstraňování <%GroupBeingUninstalled%>"

Help
"Nápověda"

InsertDiscText
"Vložte disk nazvaný <%RequiredDiscName%> a stiskněte OK."

InstallApplicationText
"Instalace programu <%AppName%>"

InstallationCompleteText
"Instalace dokonÄena."

InstallCompleteText
"Instalace souborů dokonÄena..."

InstallingApplicationText
"Instalace <%AppName%>..."

InstallErrorText
"Během instalace došlo k chybě."

InstallPrepareText
"Příprava na instalaci..."

InstallStartupText
"Program <%AppName%> bude nainstalován na váš poÄítaÄ. PokraÄovat?"

InstallTitleText
"Instalace programu <%AppName%>"

LaunchApplicationText
"Spustit <%AppName%>"

Next
"Vpřed"

No
"Ne"

OK
"OK"

PasswordIncorrectText
"Heslo není správné."

ProgramFilesDescription
"Běžné soubory programu"

PromptForDirectoryMessage
"Vyberte prosím složku a zvolte OK."

PromptForDirectoryNewFolderText
"Vytvořit novou složku"

PromptForDirectoryTitle
"Procházet složky"

PromptForRootText
"Zadejte prosím vaše heslo roota."

RequireAdministratorText
"Tento program vyžaduje pro provedení instalace práva správce systému."

RequireRootText
"Pro spuštění instalátoru musíte být root."

SelectLanguageText
"Prosím zvolte jazyk instalace"

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Typická instalace."

UninstallApplicationText
"Odinstalovat <%AppName%>"

UninstallPrepareText
"Příprava odinstalace..."

UpdateRegistryText
"Aktualizace registrů Windows..."

UninstallingApplicationText
"Odinstalace <%AppName%>..."

UninstallCompleteText
"Odinstalace dokonÄena."

UninstallStartupText
"Program <%AppName%> bude kompletně odstraněn z vašeho systému. Opravdu to\
 chcete udělat?"

UninstallLeftoverText
"NÄ›které souÄásti nemohly být odstranÄ›ny. Chcete je i pÅ™esto smazat\
 (není doporuÄeno)?"

UninstallTitleText
"Odinstalovat <%AppName%>"

UnpackingFilesText
"Rozbalování souborů..."

VersionHelpText
"Tento program nainstaluje aplikaci <%AppName%> verze <%Version%>."

ViewReadmeText
"Zobrazit ÄŒtiMÄ›"

Yes
"Ano"

ConsolePause {
    Message
    "<%ConsolePauseText%>"
}

LocateJavaRuntime {
    PromptMessage
    "Prosím sdělte nám, kde je umístěno vaše Java Runtime"

    StatusMessage
    "Hledání Java Runtime..."
}

TextWindow {
    Title
    "Název okna"

    Caption
    "Titulek"

    Message
    "Zde bude zpráva."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/de.msg.




































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
ApplicationReadmeText
"<%AppName%> LiesMich"

Back
"Zurück"

Browse
"Durchsuchen..."

BuildFileText
"Erstelle <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Erstelle Deinstallation..."

Cancel
"Abbrechen"

CleanupInstallText
"Installation wird aufgeräumt..."

Close
"Schließen"

CreateDesktopShortcutText
"Desktop Verknüpfung anlegen"

CreateQuickLaunchShortcutText
"Verknüpfung Schnellstartleiste anlegen"

CustomInstallDescription
"Auswahl der benutzerdefinierten Komponenten zur Installation."

DirectoryPermissionText
"Sie haben keine Schreibberechtigung für das Verzeichnis <%Dir%>."

ExitText
"Wollen Sie dieses Setup wirklich beenden?"

FileBeingInstalledText
"Kopiere <%FileBeingInstalled%>"

FileBeingUninstalledText
"Entferne <%FileBeingUninstalled%>"

Finish
"Beenden"

GroupBeingInstalledText
"Installiere <%GroupBeingInstalled%>"

GroupBeingUninstalledText
"Entferne <%GroupBeingUninstalled%>"

Help
"Hilfe"

InstallApplicationText
"Installiere <%AppName%>"

InstallCompleteText
"Installation der Dateien fertig..."

InstallPrepareText
"Vorbereitung der Installation..."

InstallStartupText
"Dies wird <%AppName%> auf Ihrem Computer installieren. Weitermachen?"

LaunchApplicationText
"Starte <%AppName%>"

Next
"Weiter"

No
"Nein"

OK
"OK"

ProgramFilesDescription
"Allgemeine Programmdateien"

RequireRootText
"Sie müssen root sein, um diese Installationsroutine auszuführen."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Eine typische Installation."

UninstallApplicationText
"Deinstalliere <%AppName%>"

UninstallPrepareText
"Vorbereitung der Deinstallation..."

UpdateRegistryText
"Die Windows Registry wird aktualisiert..."

UninstallStartupText
"Dies wird <%AppName%> vollkommen von Ihrem System entfernen. Wollen Sie dies\
wirklich durchführen?"

UninstallLeftoverText
"Einige Komponenten konnten nicht entfernt werden. Möchten Sie diese trotzdem\
löschen (nicht empfohlen)?"

VersionHelpText
"Dieses Program wird <%AppName%> Version <%Version%> installieren."

ViewReadmeText
"Liesmich ansehen"

Yes
"Ja"


LocateJavaRuntime {
    PromptMessage
    "Bitte sagen Sie uns, wo Ihre Java Runtime zu finden ist."

    StatusMessage
    "Suche Java Runtime..."
}

TextWindow {
    Title
    "Window Titel"

    Caption
    "Überschrift"

    Message
    "Meldung kommt hier."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/en.msg.












































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
ApplicationReadmeText
"<%AppName%> Readme"

Back
"Back"

Browse
"Browse..."

BuildFileText
"Building <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Building uninstall..."

Cancel
"Cancel"

CleanupInstallText
"Cleaning up install..."

Close
"Close"

ConsolePauseQuitText
"-- Press space to continue or 'q' to quit --"

ConsolePauseText
"-- Press space to continue --"

ConsoleSelectDestinationText
"Where do you want to install <%AppName%>?"

CreateDesktopShortcutText
"Create Desktop Shortcut"

CreateQuickLaunchShortcutText
"Create Quick Launch Shortcut"

CustomInstallDescription
"Select custom components for installation."

DirectoryNameErrorText
"A directory name cannot contain any of the following characters:
        \\ / : * ? \" < > |"

DirectoryNotEmptyText
"<%Dir%> is not empty."

DirectoryPermissionText
"You do not have permission to write to <%Dir%>."

DisplayName
"<%AppName%>"

DownloadingFilesText
"Downloading files..."

ErrorTitle
"Install Error"

ExitText
"Are you sure you want to exit this setup?"

ExitTitle
"Exit Setup"

FileBeingInstalledText
"Copying <%FileBeingInstalled%>"

FileBeingUninstalledText
"Removing <%FileBeingUninstalled%>"

FileOverwriteText
"The file <%FileBeingInstalled%> already exists.  Do you want to overwrite it?"

Finish
"Finish"

GroupBeingInstalledText
"Installing <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"Removing <%GroupBeingUninstalled%>"

Help
"Help"

InsertDiscText
"Insert the disc labeled <%RequiredDiscName%> and then click OK."

InstallApplicationText
"Install <%AppName%>"

InstallationCompleteText
"Installation complete."

InstallCompleteText
"File installation complete..."

InstallingApplicationText
"Installing <%AppName%>..."

InstallErrorText
"An error has occurred during installation."

InstallPrepareText
"Preparing to install..."

InstallStartupText
"This will install <%AppName%> v<%Version%> on your computer.\n\nContinue?\n"

InstallTitleText
"<%AppName%> Setup"

LaunchApplicationText
"Launch <%AppName%>"

Next
"Next"

No
"No"

OK
"OK"

PasswordIncorrectText
"Password is incorrect."

ProgramFilesDescription
"Common Program Files"

PromptForAdministratorText
"This program requires administrator privileges.  Please enter your password."

PromptForDirectoryMessage
"Please choose a directory, then select OK."

PromptForDirectoryNewFolderText
"Make New Folder"

PromptForDirectoryTitle
"Browse for Folder"

PromptForRootText
"Please enter your root password."

RequireAdministratorText
"This program requires administrator privileges to install."

RequireRootText
"You must be root to run this installer."

RequireRootTitleText
"Root Required"

RequireRootUninstallText
"You must be root to uninstall this application."

SelectLanguageText
"Please select the installation language"

SeparatorText
"InstallJammer"

String.database.entries
"database entries"

String.directories
"directories"

String.environment.variables
"environment variables"

String.files
"files"

String.package.entries
"package entries"

String.registry.entries
"registry entries"

String.shortcuts
"shortcuts"

TypicalInstallDescription
"A typical installation."

UninstallApplicationText
"Uninstall <%AppName%>"

UninstallPrepareText
"Preparing to uninstall..."

UpdateRegistryText
"Updating Windows Registry..."

UninstallingApplicationText
"Uninstalling <%AppName%>..."

UninstallCompleteText
"Uninstall complete."

UninstallStartupText
"This will completely remove <%AppName%> from your system.  Are you sure\
 you want to do this?"

UninstallLeftoverText
"Some components could not be removed.  Do you wish to delete them anyway\
 (not recommended)?"

UninstallPrepareText
"Preparing to uninstall..."

UninstallTitleText
"Uninstall <%AppName%>"

UnpackingFilesText
"Unpacking files..."

VersionHelpText
"This program will install <%AppName%> version <%Version%>."

ViewReadmeText
"View Readme"

Yes
"Yes"

ConsolePause {
    Message
    "<%ConsolePauseText%>"
}

LocateJavaRuntime {
    PromptMessage
    "Please tell us where your Java Runtime is located"

    StatusMessage
    "Locating Java Runtime..."
}

TextWindow {
    Title
    "Window Title"

    Caption
    "Caption"

    Message
    "Message goes here."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/es.msg.




























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
ApplicationReadmeText
"<%AppName%> Léeme"

Back
"Atrás"

Browse
"Examinar..."

BuildFileText
"Generando <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Generando desinstalador..."

Cancel
"Cancelar"

CleanupInstallText
"Limpiando instalación..."

Close
"Cerrar"

CreateDesktopShortcutText
"Crear icono en Escritorio"

CreateQuickLaunchShortcutText
"Crear icono en Barra de Tareas"

CustomInstallDescription
"Seleccione los componentes de la instalación."

DirectoryPermissionText
"No tiene permisos para escribir en <%Dir%>."

ExitText
"¿Seguro que desea salir de la instalación?"

FileBeingInstalledText
"Copiando <%FileBeingInstalled%>"

FileBeingUninstalledText
"Borrando <%FileBeingUninstalled%>"

Finish
"Finalizar"

GroupBeingInstalledText
"Instalando <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"Borrando <%GroupBeingUninstalled%>"

Help
"Ayuda"

InstallApplicationText
"Instalar <%AppName%>"

InstallCompleteText
"Instalación completa..."

InstallPrepareText
"Preparando instalación..."

InstallStartupText
"Se va a instalar <%AppName%> en su equipo.  ¿Continuar?"

LaunchApplicationText
"Ejecutar <%AppName%>"

Next
"Siguiente"

No
"No"

OK
"OK"

ProgramFilesDescription
"Archivos de Programa Comunes"

RequireRootText
"Necesita tener permisos de administrador para ejecutar el instalador."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Una instalación típica."

UninstallApplicationText
"Desinstalar <%AppName%>"

UninstallPrepareText
"Preparando desinstalación..."

UpdateRegistryText
"Actualizando Registro de Windows..."

UninstallStartupText
"Se eliminará completamente <%AppName%> de su sistema. ¿Seguro que desea esto?"

UninstallLeftoverText
"Algunos componentes no pudieron ser eliminados. ¿Desea borrarlos de todos\
 modos? (no recomendado)"

ViewReadmeText
"Ver Léeme"

Yes
"Sí"


LocateJavaRuntime {
    PromptMessage
    "Por favor, localice su Entorno de Ejecución Java (JRE)"

    StatusMessage
    "Buscando Entorno de Ejecución Java (JRE)..."
}

TextWindow {
    Title
    "Título de la Ventana"

    Caption
    "Leyenda"

    Message
    "Mensaje aquí."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/fr.msg.




































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
ApplicationReadmeText
"<%AppName%> Readme"

Back
"Précédent"

Browse
"Parcourir..."

BuildFileText
"Génération <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Génération de la désinstallation..."

Cancel
"Annuler"

CleanupInstallText
"Nettoyage de l'installation..."

Close
"Fermer"

CreateDesktopShortcutText
"Créer le raccourci sur le bureau"

CreateQuickLaunchShortcutText
"Créer un raccourci de lancement rapide"

CustomInstallDescription
"Sélectionner les composants pour l'installation."

DirectoryPermissionText
"Vous n'avez pas la permission d'écrire dans le dossier <%Dir%>."

ExitText
"Etes-vous certain de vouloir quitter ce programme d'installation?"

FileBeingInstalledText
"Copie de <%FileBeingInstalled%>"

FileBeingUninstalledText
"Suppression de <%FileBeingUninstalled%>"

Finish
"Terminer"

GroupBeingInstalledText
"Installation de <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"Suppression de <%GroupBeingUninstalled%>"

Help
"Aide"

InstallApplicationText
"Installer <%AppName%>"

InstallCompleteText
"Installation des fichiers terminée..."

InstallPrepareText
"Préparation de l'installation..."

InstallStartupText
"Ceci installera <%AppName%>  sur votre ordinateur.  Continuer?"

LaunchApplicationText
"Lancer <%AppName%>"

Next
"Suivant"

No
"Non"

OK
"OK"

ProgramFilesDescription
"Fichiers programme communs"

RequireRootText
"Vous devez être ROOT pour exécuter cette installeur."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Une installation typique."

UninstallApplicationText
"Désinstaller <%AppName%>"

UninstallPrepareText
"Préparation de la désinstallation..."

UpdateRegistryText
"Mise à jour de la base de registre Windows..."

UninstallStartupText
"Ceci supprimera complètement <%AppName%> de votre ordinateur.  Etes-vous\
 certain de vouloir faire cela?"

UninstallLeftoverText
"Certain composants n'ont pu être supprimés. Souhairez vous quand même les\
 effacer (non recommandé)?"

ViewReadmeText
"Lire le fichier Readme"

VersionHelpText
"Ce programme va installer <%AppName%> version <%Version%>."

Yes
"Oui"


LocateJavaRuntime {
    PromptMessage
    "Merci de préciser la localisation de votre Runtime Java"

    StatusMessage
    "Localisation du Runtime Java..."
}

TextWindow {
    Title
    "Titre de la fenêtre"

    Caption
    "Légende"

    Message
    "Saisir le message ici."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/hu.msg.


















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
ApplicationReadmeText
"<%AppName%> OlvassaEl"

Back
"Vissza"

Browse
"Tallózás..."

BuildFileText
"<%Tail <%FileBeingInstalled%>%> szerkesztése..."

BuildUninstallText
"Uninstall szerkesztése..."

Cancel
"Mégsem"

CleanupInstallText
"Telepítés takarítása..."

Close
"Bezárás"

ConsolePauseQuitText
"-- Nyomjon egy szóközt a folytatáshoz, vagy egy 'q'-t a kilépéshez --"

ConsolePauseText
"-- Nyomjon egy szóközt a folytatáshoz --"

ConsoleSelectDestinationText
"Hova akarja telepíteni a <%AppName%> alkalmazást?"

CreateDesktopShortcutText
"Hozzon létre parancsikont az Asztalon"

CreateQuickLaunchShortcutText
"Hozzon létre a Gyorsindítóban parancsikont"

CustomInstallDescription
"Válassza ki az egyéni komponenseket a telepítéshez."

DirectoryPermissionText
"Nincs elég joga a <%Dir%> könyvtárba írni."

DisplayName
"<%AppName%>"

DownloadingFilesText
"Állományok letöltése..."

ExitText
"Biztos, hogy ki akar lépni a telepít\u0151b\u0151l?"

FileBeingInstalledText
"<%FileBeingInstalled%> másolása"

FileBeingUninstalledText
"<%FileBeingUninstalled%> törlése"

FileOverwriteText
"A <%FileBeingInstalled%> file már létezik.  Felül akarja írni?"

Finish
"Befejezés"

GroupBeingInstalledText
"<%GroupBeingInstalled%> telepítése..."

GroupBeingUninstalledText
"<%GroupBeingUninstalled%> eltávolítása"

Help
"Sugó"

InstallApplicationText
"<%AppName%> telepítése"

InstallationCompleteText
"A telepítés befejez\u0151d\u0151tt."

InstallCompleteText
"Az állomány telepítése befejez\u0151d\u0151tt..."

InstallingApplicationText
"<%AppName%> telepítése..."

InstallPrepareText
"Felkészülés a telepítésre..."

InstallStartupText
"Ez a <%AppName%> programot fogja telepíteni a számítógépére.  Folytatja?"

InstallTitleText
"<%AppName%> Setup"

LaunchApplicationText
"<%AppName%> betöltése"

Next
"Következ\u0151"

No
"Nem"

OK
"OK"

PasswordIncorrectText
"Érvénytelen jelszó."

ProgramFilesDescription
"Általános program állományok"

PromptForDirectoryMessage
"Kérem válasszon egy könyvtárat, majd kattintson az OK-ra."

PromptForDirectoryTitle
"Könyvtár tallózása"

PromptForRootText
"Kérem gépelje be a root jelszót."

RequireRootText
"root-nak kell lenni a telepít\u0151 futtatásához."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Tipikus telepítés."

UninstallApplicationText
"<%AppName%> eltávolítása"

UninstallPrepareText
"Felkészülés az eltávolításra..."

UpdateRegistryText
"A Windows Registry frissítése..."

UninstallingApplicationText
"<%AppName%> eltávolítása..."

UninstallCompleteText
"Eltávolítás befejez\u0151d\u0151tt."

UninstallStartupText
"Ez teljesen letörli a <%AppName%> alkalmazást a rendszerér\u0151l. \
 Biztos abban, hogy ezt akarja?"

UninstallLeftoverText
"Néhány elemet nem kellene eltávolítani. \
 Mindenáron töröljük \u0151ket (nem javasolt)?"

UninstallTitleText
"<%AppName%> eltávolítása"

UnpackingFilesText
"Állományok kicsomagolása..."

VersionHelpText
"Ez a program a <%AppName%> program <%Version%> verzióját fogja telepíteni."

ViewReadmeText
"OlvassaEl állomány elolvasása"

Yes
"Igen"

ConsolePause {
    Message
    "<%ConsolePauseText%>"
}

LocateJavaRuntime {
    PromptMessage
    "Kérem mondja meg, hogy a Java futtatási környezet hol található"

    StatusMessage
    "A Java futtatási környezet keresése..."
}

TextWindow {
    Title
    "Ablak cím"

    Caption
    "Fejléc"

    Message
    "Az üzenet jön ide."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/it.msg.


















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
ApplicationReadmeText
"<%AppName%> Leggimi"

Back
"Indietro"

Browse
"Sfoglia..."

BuildFileText
"Generazione di <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Generazione della disinstallazione..."

Cancel
"Annulla"

CleanupInstallText
"Pulizia dei file di installazione..."

Close
"Chiudi"

ConsolePauseQuitText
"-- Premere spazio per proseguire o 'q' per uscire --"

ConsolePauseText
"-- Premere spazio per proseguire --"

ConsoleSelectDestinationText
"Dove si desidera installare <%AppName%>?"

CreateDesktopShortcutText
"Crea collegamento sul Desktop"

CreateQuickLaunchShortcutText
"Crea collegamento in Avvio rapido"

CustomInstallDescription
"Seleziona in modo personalizzato le parti da installare."

DirectoryPermissionText
"Non si dispone dei permessi di scrittura in <%Dir%>."

DisplayName
"<%AppName%>"

DownloadingFilesText
"Scaricamento dei file..."

ExitText
"Si è sicuri di voler uscire dal programma di installazione?"

FileBeingInstalledText
"Copia di <%FileBeingInstalled%>"

FileBeingUninstalledText
"Rimozione di <%FileBeingUninstalled%>"

FileOverwriteText
"Il file <%FileBeingInstalled%> esiste già. Lo si vuole sovrascrivere?"

Finish
"Fine"

GroupBeingInstalledText
"Installazione di <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"Rimozione di <%GroupBeingUninstalled%>"

Help
"Aiuto"

InstallApplicationText
"Installa <%AppName%>"

InstallationCompleteText
"Installazione completata."

InstallCompleteText
"Completamento dell'installazione dei file..."

InstallingApplicationText
"Installazione di <%AppName%>..."

InstallPrepareText
"Preparazione dell'installazione..."

InstallStartupText
"<%AppName%> sarà installato sul computer. Proseguire?"

InstallTitleText
"Installazione di <%AppName%>"

LaunchApplicationText
"Eseguire <%AppName%>"

Next
"Avanti"

No
"No"

OK
"OK"

PasswordIncorrectText
"La parola chiave è errata."

ProgramFilesDescription
"Programmi Comuni"

PromptForDirectoryMessage
"Si prega di scegliere una directory, poi selezionare OK."

PromptForDirectoryTitle
"Sfoglia le cartelle"

PromptForRootText
"Si prega di inserire la parola chiave di root."

RequireRootText
"E' necessario essere root per eseguire il programma di installazione."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Installazione tipica."

UninstallApplicationText
"Disinstalla <%AppName%>"

UninstallPrepareText
"Preparazione della disinstallazione..."

UpdateRegistryText
"Aggiornamento del Registro di Windows..."

UninstallingApplicationText
"Disinstallazione di <%AppName%>..."

UninstallCompleteText
"Disinstallazione completata."

UninstallStartupText
"<%AppName%> sarà rimosso completamente dal sistema. Si è sicuri di voler\
 procedere?"

UninstallLeftoverText
"Alcune parti non possono essere rimosse. Si desidera cancellarle comunque\
 (sconsigliato)?"

UninstallTitleText
"Disinstalla <%AppName%>"

UnpackingFilesText
"Decompressione dei file..."

VersionHelpText
"Il programma sta per installare <%AppName%> nella versione <%Version%>."

ViewReadmeText
"Visualizza il file Leggimi"

Yes
"Sì"

ConsolePause {
    Message
    "<%ConsolePauseText%>"
}

LocateJavaRuntime {
    PromptMessage
    "Si prega di comunicare dove si trova la Java Runtime"

    StatusMessage
    "Individuazione della Java Runtime in corso..."
}

TextWindow {
    Title
    "Titolo della finestra"

    Caption
    "Didascalia"

    Message
    "Il messaggio va qui."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/lt.msg.






































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
ApplicationReadmeText
"<%AppName%> Skaityk"

Back
"Atgal"

Browse
"Parinkti..."

BuildFileText
"Kuriamas <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Kuriama ðalinimo programa..."

Cancel
"Atsisakyti"

CleanupInstallText
"Iðvalomas diegimas..."

Close
"Uþverti"

ConsolePauseQuitText
"-- Spauskite tarpà tam kad tæsti arba 'q' kad baigti --"

ConsolePauseText
"-- Spauskite tarpà tam kad tæsti --"

ConsoleSelectDestinationText
"Kur norëtumëte ádiegti <%AppName%>?"

CreateDesktopShortcutText
"Sukurti darbalaukio ðaukiná"

CreateQuickLaunchShortcutText
"Sukurti sparèiosios paleisties ðaukiná"

CustomInstallDescription
"Pasirinkiti komponentus ádiegimui."

DirectoryNameErrorText
"Katalogas negali turëti ðiø þenklø:
        \\ / : * ? \" < > |"

DirectoryPermissionText
"Jûs neturite teisës raðyti á <%Dir%>."

DisplayName
"<%AppName%>"

DownloadingFilesText
"Atsiunèiami failai..."

ExitText
"Ar jûs ásitikinæs, kad norite iðeiti ið ðios diegimo programos?"

FileBeingInstalledText
"Kopijuojama <%FileBeingInstalled%>"

FileBeingUninstalledText
"Ðalinama <%FileBeingUninstalled%>"

FileOverwriteText
"Failas <%FileBeingInstalled%> jau yra. Ar norëtumëte já perraðyti?"

Finish
"Pabaiga"

GroupBeingInstalledText
"Diegiama <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"Ðalinama <%GroupBeingUninstalled%>"

Help
"Pagalba"

InstallApplicationText
"Ádiegti <%AppName%>"

InstallationCompleteText
"Diegimas baigtas."

InstallCompleteText
"Failo diegimas baigtas..."

InstallingApplicationText
"Diegema <%AppName%>..."

InstallErrorText
"Diegimo metu ávyko klaida."

InstallPrepareText
"Ruoðiamasi diegimui..."

InstallStartupText
"Tai ádiegs <%AppName%> á jûsø kompiuterá. Tæsti?"

InstallTitleText
"<%AppName%> Ádiegimo programa"

LaunchApplicationText
"Paleisti <%AppName%>"

Next
"Toliau"

No
"Ne"

OK
"Gerai"

PasswordIncorrectText
"Slaptaþodis yra neteisingas."

ProgramFilesDescription
"Bendri Programos Failai"

PromptForDirectoryMessage
"Praðom pasirinkti katalogà, tada pasirinkti Gerai."

PromptForDirectoryNewFolderText
"Sukurti naujà katalogà"

PromptForDirectoryTitle
"Parinkti katalogà"

PromptForRootText
"Praðom ávesti jûsø root slaptaþodá."

RequireRootText
"Jûs turite bûti root kad paleistumëte ðià diegimo programà."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Tipinis diegimas."

UninstallApplicationText
"Paðalinti programà <%AppName%>"

UninstallPrepareText
"Ruoðiamasi paðalinti programà..."

UpdateRegistryText
"Atnaujinamas Windows registras..."

UninstallingApplicationText
"Paðalinama programa <%AppName%>..."

UninstallCompleteText
"Programos paðalinimas atliktas."

UninstallStartupText
"Tai visiðkai paðalins <%AppName%> ið jûsø sistemos.  Ar jûs ásitikinæs\
 kad norite tai atlikti?"

UninstallLeftoverText
"Kai kurie komponentai negali bûti paðalinti. Ar norëtumëte juos paðalinti\
 betkuriuo atvëju (nerekomenduojama)?"

UninstallTitleText
"Programos paðalinimas <%AppName%>"

UnpackingFilesText
"Iðpakuojami failai..."

VersionHelpText
"Programa <%AppName%> versija <%Version%> bus ádiegta."

ViewReadmeText
"Perþiûrëti apraðymà"

Yes
"Taip"

ConsolePause {
    Message
    "<%ConsolePauseText%>"
}

LocateJavaRuntime {
    PromptMessage
    "Praðom pasakyti kur jûsø Java Runtime randasi"

    StatusMessage
    "Ieðkome Java Runtime..."
}

TextWindow {
    Title
    "Lango Antraðtë"

    Caption
    "Pavadinimas"

    Message
    "Praneðimas ávedamas èia."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/nl.msg.


















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
ApplicationReadmeText
"<%AppName%> Readme"

Back
"Terug"

Browse
"Bladeren..."

BuildFileText
"Bouwen <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Bouwen deïnstallatie..."

Cancel
"Annuleren"

CleanupInstallText
"Opschonen installatie..."

Close
"Sluiten"

ConsolePauseQuitText
"-- Druk op spatie om door te gaan of op 'q' om te stoppen --"

ConsolePauseText
"-- Druk op spatie om door te gaan --"

ConsoleSelectDestinationText
"Waar wilt u <%AppName%> installeren?"

CreateDesktopShortcutText
"Maak bureaublad snelkoppeling"

CreateQuickLaunchShortcutText
"Maak Snel Start snelkoppeling"

CustomInstallDescription
"Selecteer afzonderlijke componenten voor installatie."

DirectoryPermissionText
"U heeft geen toestemming om te schrijven naar <%Dir%>."

DisplayName
"<%AppName%>"

DownloadingFilesText
"Bestanden downloaden..."

ExitText
"Weet u zeker dat u wilt stoppen met deze installatie?"

FileBeingInstalledText
"Kopiëren <%FileBeingInstalled%>"

FileBeingUninstalledText
"Verwijderen <%FileBeingUninstalled%>"

FileOverwriteText
"Het bestand <%FileBeingInstalled%> bestaat al.  Wilt u het overschrijven?"

Finish
"Klaar"

GroupBeingInstalledText
"Installeren <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"Verwijderen <%GroupBeingUninstalled%>"

Help
"Help"

InstallApplicationText
"Installeer <%AppName%>"

InstallationCompleteText
"Installatie afgerond."

InstallCompleteText
"Bestand installatie afgerond..."

InstallingApplicationText
"<%AppName%> installeren..."

InstallPrepareText
"Installatie voorbereiden..."

InstallStartupText
"Dit zal <%AppName%> op uw computer installeren.  Doorgaan?"

InstallTitleText
"<%AppName%> Setup"

LaunchApplicationText
"Start <%AppName%>"

Next
"Volgende"

No
"Nee"

OK
"OK"

PasswordIncorrectText
"Wachtwoord is onjuist."

ProgramFilesDescription
"Algemene bestanden"

PromptForDirectoryMessage
"Selecteer een directory, klik daarna op OK."

PromptForDirectoryTitle
"Blader naar map"

PromptForRootText
"Vul uw root wachtwoord in."

RequireRootText
"U moet root zijn om dit programma te installeren."

SeparatorText
"SemLab"

TypicalInstallDescription
"Een standaard installatie."

UninstallApplicationText
"Verwijderen <%AppName%>"

UninstallPrepareText
"Deïnstallatie voorbereiden..."

UpdateRegistryText
"Windows Register bijwerken..."

UninstallingApplicationText
"<%AppName%> verwijderen..."

UninstallCompleteText
"Deïnstallatie klaar."

UninstallStartupText
"Dit verwijderd <%AppName%> geheel van uw systeem.  Weet u zeker\
 dat u dit wilt doen?"

UninstallLeftoverText
"Sommige componenten konden niet worden verwijderd.  Wilt u ze toch verwijderen\
 (niet aangeraden)?"

UninstallTitleText
"Verwijder <%AppName%>"

UnpackingFilesText
"Bestanden uitpakken..."

VersionHelpText
"Dit programma zal <%AppName%> versie <%Version%> installeren."

ViewReadmeText
"Bekijk Readme"

Yes
"Ja"

ConsolePause {
    Message
    "<%ConsolePauseText%>"
}

LocateJavaRuntime {
    PromptMessage
    "Wijs uw Java Runtime locatie aan"

    StatusMessage
    "Java Runtime lokaliseren..."
}

TextWindow {
    Title
    "Scherm titel"

    Caption
    "Bijschrift"

    Message
    "Bericht gaat hier."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/pl.msg.












































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# options: -encoding utf-8

ApplicationReadmeText
"<%AppName%> Readme"

Back
"Wstecz"

Browse
"PrzeglÄ…daj..."

BuildFileText
"Budowanie <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Budowanie deinstalatora..."

Cancel
"Anuluj"

CleanupInstallText
"Czyszczenie instalacji..."

Close
"Zamknij"

ConsolePauseQuitText
"-- Wciśnij spację, aby kontynuować lub 'q', aby wyjść --"

ConsolePauseText
"-- Wciśnij spację, aby kontynuować --"

ConsoleSelectDestinationText
"Gdzie chcesz zainstalować <%AppName%>?"

CreateDesktopShortcutText
"Utwórz skrót na pulpicie"

CreateQuickLaunchShortcutText
"Utwórz skrót szybkiego uruchamiania"

CustomInstallDescription
"Zaznacz wybrane komponenty do instalacji."

DirectoryPermissionText
"Nie masz uprawniwń, aby zapisywać w <%Dir%>."

DownloadingFilesText
"Pobieranie plików..."

ExitText
"Czy na pewno chcesz opuścić instalator?"

FileBeingInstalledText
"Kopiowanie <%FileBeingInstalled%>"

FileBeingUninstalledText
"Usuwanie <%FileBeingUninstalled%>"

FileOverwriteText
"Plik <%FileBeingInstalled%> już istnieje.  Czy chcesz go naspisać?"

Finish
"Zakończ"

GroupBeingInstalledText
"Instalowanie <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"Usuwanie <%GroupBeingUninstalled%>"

Help
"Pomoc"

InstallApplicationText
"Instaluj <%AppName%>"

InstallationCompleteText
"Instalacja zakończona."

InstallCompleteText
"Instalacja pliku zakończona..."

InstallingApplicationText
"Instalowanie <%AppName%>..."

InstallPrepareText
"Przygotowywanie do instalacji..."

InstallStartupText
"Instalator zainstaluje <%AppName%> na twoim komputerze. Kontynuować?"

LaunchApplicationText
"Uruchom <%AppName%>"

Next
"Dalej"

No
"Nie"

OK
"OK"

ProgramFilesDescription
"Common Program Files"

PromptForRootText
"Proszę wpisać hasło administratora."

RequireRootText
"Musisz być administratorem (root), aby uruchomić ten instalator."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Instalacja typowa."

UninstallApplicationText
"Usuń <%AppName%>"

UninstallPrepareText
"Przygotowywanie do deinstalacji..."

UpdateRegistryText
"Uaktualnianie rejestru Windows..."

UninstallingApplicationText
"Deinstalacja <%AppName%>..."

UninstallCompleteText
"Deinstalacja zakończona."

UninstallStartupText
"<%AppName%> zostanie kompletnie usunięty z twojego systemu.  Czy\
 na pewno chcesz tego?"

UninstallLeftoverText
"Niektóre komponenty nie mogły zostać usunięte.  Czy pomimo to chcesz\
 je usunąć (niezalecane)?"

VersionHelpText
"Ten program zainstaluje <%AppName%> w wersji <%Version%>."

ViewReadmeText
"Pokaż Readme"

Yes
"Tak"

ConsolePause {
    Message
    "<%ConsolePauseText%>"
}

LocateJavaRuntime {
    PromptMessage
    "Proszę powiedzieć, gdzie zainstalowano Java Runtime Environment."

    StatusMessage
    "Szukanie Java Runtime..."
}

TextWindow {
    Title
    "Okno tytułowe"

    Caption
    "Nagłówek"

    Message
    "Wyjście wiadomości."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/pt_br.msg.




































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
ApplicationReadmeText
"<%AppName%> Readme"

Back
"Voltar"

Browse
"Navegar..."

BuildFileText
"Construindo <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Construindo desinstalado..."

Cancel
"Cancelar"

CleanupInstallText
"Limpando instalação..."

Close
"Fechar"

CreateDesktopShortcutText
"Criando atalho no Desktop"

CreateQuickLaunchShortcutText
"Criação de atalho na barra de inicialização rápida"

CustomInstallDescription
"Selecionar componentes personalizados para instalação."

DirectoryPermissionText
"Você não tem permissão para escrever em <%Dir%>."

ExitText
"Você está certo que deseja sair do instalador?"

FileBeingInstalledText
"Copiando <%FileBeingInstalled%>"

FileBeingUninstalledText
"Removendo <%FileBeingUninstalled%>"

Finish
"Concluir"

GroupBeingInstalledText
"Instalando <%GroupBeingInstalled%>"

GroupBeingUninstalledText
"Removendo <%GroupBeingUninstalled%>"

Help
"Ajuda"

InstallApplicationText
"Instalar <%AppName%>"

InstallCompleteText
"Instalação de arquivos completa..."

InstallPrepareText
"Preparando para instalar..."

InstallStartupText
"Será instalado <%AppName%> em seu computador.  Continuar?"

LaunchApplicationText
"Iniciar <%AppName%>"

Next
"Próximo"

No
"Não"

OK
"OK"

ProgramFilesDescription
"Arquivos comuns de programa"

RequireRootText
"Você precisa ser root para executar o instalador."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Uma instalação típica."

UninstallApplicationText
"Desinstalar <%AppName%>"

UninstallPrepareText
"Preparando para desinstalar..."

UpdateRegistryText
"Atualizando Registro do Windows..."

UninstallStartupText
"<%AppName%> será removido completamento do seu computador.  Você tem\
certeza que deseja continuar?"

UninstallLeftoverText
"Alguns componentes não puderam ser removidos. Você deseja deletá-los assim mesmo\
 (não recomendado)?"

VersionHelpText
"Este programa irá instalar <%AppName%> versão <%Version%>."

ViewReadmeText
"Veja o Readme"

Yes
"Sim"


LocateJavaRuntime {
    PromptMessage
    "Por favor informe onde o Java Runtime está instalado"

    StatusMessage
    "Localizando Java Runtime..."
}

TextWindow {
    Title
    "Título da Janela"

    Caption
    "Caption"

    Message
    "Mensagens aparecerão aqui."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/installer/ru.msg.


















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
ApplicationReadmeText
"Èíôîðìàöèÿ î <%AppName%>"

Back
"Íàçàä"

Browse
"Ïðîñìîòð..."

BuildFileText
"Ñîçäà¸òñÿ <%Tail <%FileBeingInstalled%>%>..."

BuildUninstallText
"Ñîçäà¸òñÿ ïðîãðàììà äåèíñòàëëÿöèè..."

Cancel
"Îòìåíà"

CleanupInstallText
"×èñòêà ïðîãðàììû èíñòàëëÿöèè..."

Close
"Çàêðûòü"

ConsolePauseQuitText
"-- Íàæìèòå ïðîáåë äëÿ ïðîäîëæåíèÿ èëè 'q' äëÿ âûõîäà --"

ConsolePauseText
"-- Íàæìèòå ïðîáåë äëÿ ïðîäîëæåíèÿ --"

ConsoleSelectDestinationText
"Ãäå âû õîòèòå óñòàíîâèòü <%AppName%>?"

CreateDesktopShortcutText
"Ñîçäàòü ÿðëûê íà ðàáî÷åì ñòîëå"

CreateQuickLaunchShortcutText
"Ñîçäàòü ÿðëûê â ïàíåëè áûñòðîãî çàïóñêà"

CustomInstallDescription
"Âûáåðèòå êîìïîíåíòû äëÿ óñòàíîâêè."

DirectoryPermissionText
"Íåò äîñòóïà íà çàïèñü â <%Dir%>."

DisplayName
"<%AppName%>"

DownloadingFilesText
"Èä¸ò çàãðóçêà ôàéëîâ..."

ExitText
"Âû óâåðåíû, ÷òî õîòèòå çàâåðøèòü ðàáîòó ïðîãðàììû óñòàíîâêè ?"

FileBeingInstalledText
"Êîïèðóåòñÿ <%FileBeingInstalled%>"

FileBeingUninstalledText
"Óäàëÿåòñÿ <%FileBeingUninstalled%>"

FileOverwriteText
"Ôàéë <%FileBeingInstalled%> óæå ñóùåñòâóåò.  Æåëàåòå ïåðåçàïèñàòü åãî ?"

Finish
"Ãîòîâî"

GroupBeingInstalledText
"Óñòàíàâëèâàåòñÿ <%GroupBeingInstalled%>..."

GroupBeingUninstalledText
"Óäàëÿåòñÿ <%GroupBeingUninstalled%>"

Help
"Ïîìîùü"

InstallApplicationText
"Óñòàíîâêà <%AppName%>"

InstallationCompleteText
"Óñòàíîâêà çàâåðøåíà."

InstallCompleteText
"Óñòàíîâêà ôàéëà çàâåðøåíà."

InstallingApplicationText
"Óñòàíàâëèâàåòñÿ <%AppName%>..."

InstallPrepareText
"Ïîäãîòîâêà ê óñòàíîâêå..."

InstallStartupText
"<%AppName%> áóäåò óñòàíîâëåíà íà âàøåì êîìïüþòåðå. Ïðîäîëæèòü ?"

InstallTitleText
"Óñòàíîâêà <%AppName%>"

LaunchApplicationText
"Çàïóñê <%AppName%>"

Next
"Äàëåå"

No
"Íåò"

OK
"OK"

PasswordIncorrectText
"Íåâåðíûé ïàðîëü."

ProgramFilesDescription
"Îáùèå Ïðîãðàììíûå Ôàéëû"

PromptForDirectoryMessage
"Ïîæàëóéñòà, âûáåðèòå êàòàëîã è ù¸ëêíèòå íà OK."

PromptForDirectoryTitle
"Âûáîð êàòàëîãà"

PromptForRootText
"Ïîæàëóéñòà, ââåäèòå ïàðîëü ïîëüçîâàòåëÿ root."

RequireRootText
"Âû äîëæíû èìåòü ïðàâà ïîëüçîâàòåëÿ root äëÿ çàïóñêà ýòîé ïðîãðàììû óñòàíîâêè."

SeparatorText
"InstallJammer"

TypicalInstallDescription
"Ñòàíäàðòíàÿ óñòàíîâêà."

UninstallApplicationText
"Äåèíñòàëëÿöèÿ <%AppName%>"

UninstallPrepareText
"Èä¸ò ïîäãîòîâêà ê äåèíñòàëëÿöèè..."

UpdateRegistryText
"Âíîñÿòñÿ èçìåíåíèÿ â ðååñòð Windows..."

UninstallingApplicationText
"Èä¸ò äåèíñòàëëÿöèÿ <%AppName%>..."

UninstallCompleteText
"Äåèíñòàëëÿöèÿ çàâåðøåíà."

UninstallStartupText
"<%AppName%> áóäåò ïîëíîñòüþ óäàëåíà èç âàøåé ñèñòåìû. Âû óâåðåíû, ÷òî\
 ñîáèðàåòåñü ýòî ñäåëàòü ?"

UninstallLeftoverText
"Íåêîòîðûå êîìïîíåíòû íå ìîãóò áûòü óäàëåíû. Âû âñ¸-òàêè æåëàåòå èõ óäàëèòü\
 (íå ðåêîìåíäóåòñÿ) ?"

UninstallTitleText
"Äåèíñòàëëèðîâàòü <%AppName%>"

UnpackingFilesText
"Èä¸ò ðàñïàêîâêà ôàéëîâ..."

VersionHelpText
"Ýòà ïðîãðàììà óñòàíîâèò <%AppName%> <%Version%>."

ViewReadmeText
"Ïðîñìîòð èíôîðìàöèè"

Yes
"Äà"

ConsolePause {
    Message
    "<%ConsolePauseText%>"
}

LocateJavaRuntime {
    PromptMessage
    "Ïîæàëóéñòà, óêàæèòå ãäå íàõîäèòñÿ Java Runtime"

    StatusMessage
    "Èä¸ò ïîèñê Java Runtime..."
}

TextWindow {
    Title
    "Çàãîëîâîê îêíà"

    Caption
    "Ïîäïèñü"

    Message
    "Çäåñü äîëæíî áûòü ñîîáùåíèå."

    CloseButton
    "<%Close%>"
}

UnzipFile {
    StatusText
    "<%FileBeingInstalledText%>"
}
Added lib/msgs/languages.txt.


























>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
ca    "CatalÃ"
cs    "Czech"
de    "German"
en    "English"
es    "Spanish"
fr    "French"
hu    "Magyar"
it    "Italian"
lt    "Lithuanian"
nl    "Nederlands"
pl    "Polish"
pt_br "Brazilian Portuguese"
ru    "Russian"
Added lib/new.tcl.


















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

namespace eval ::InstallJammer::new {}

proc ::InstallJammer::SetProjectDefaults { {force 0} } {
    global info

    set vars {
        AllowLanguageSelection          "Yes"
	AppName			        "Your Application Name"
        ApplicationID                   ""
        ApplicationURL                  ""
        AutoRefreshFiles                "Yes"
	BuildFailureAction              "Fail (recommended)"
	CancelledInstallAction	        "Rollback and Stop"
	CleanupCancelledInstall         "Yes"
	CommandLineFailureAction        "Fail (recommended)"
	Company			        "Your Company Name"
        CompressionLevel                6
        CompressionMethod               "zlib"
        Copyright                       ""
        DefaultDirectoryLocation        ""
        DefaultLanguage                 "English"
        DefaultToSystemLanguage         "Yes"
        EnableResponseFiles             "Yes"
        ExtractSolidArchivesOnStartup   "No"
        IgnoreDirectories               ""
        IgnoreFiles                     ""
	IncludeDebugging	        "Yes"
        InstallPassword                 ""
	InstallVersion		        "1.0.0.0"
        LastIgnoreDirectories           ""
        LastIgnoreFiles                 ""
        PackageDescription              ""
        PackageLicense                  ""
        PackageMaintainer               ""
        PackageName                     "<%ShortAppName%>"
        PackagePackager                 ""
        PackageRelease                  "<%PatchVersion%>"
        PackageSummary                  ""
        PackageVersion                  "<%MajorVersion%>.<%MinorVersion%>"
        PreserveFileAttributes          "Yes"
        PreserveFilePermissions         "Yes"
        SaveOnlyToplevelDirs            "No"
        ShortAppName                    ""
	SkipUnusedFileGroups	        "Yes"
        UpgradeApplicationID            ""
	Version			        "1.0"
    }

    foreach code [::InstallJammer::GetLanguageCodes] {
        lappend vars Language,$code Yes
    }

    if {$force} {
	array set info $vars
    } else {
	SafeArraySet info $vars
    }
}

proc ::InstallJammer::new::SetDefaults {} {
    global conf
    global info
    global widg
    global newinfo

    variable ::NewInstall::vars
    variable ::NewInstall::platforms

    ::InstallJammer::SetProjectDefaults 1
    lassign_array [split $info(InstallVersion) .] info \
        MajorVersion MinorVersion PatchVersion BuildVersion
    array set newinfo [array get info]
    set newinfo(ShortAppName) "yourapp"

    set themes [::InstallJammer::ThemeList]
    if {[lsearch -exact $themes $conf(DefaultTheme)] > -1} {
        set theme $conf(DefaultTheme)
    } else {
        set theme [file tail [lindex $themes 0]]
    }

    set vars(theme) $theme

    set name [NextProjectName "Install Project" 1]

    set vars(applocation)        ""
    set vars(projectname)        $name
    set vars(projectdirprefix)   [GetPref ProjectDir]
    set vars(projectdir)         [file join [GetPref ProjectDir] $name]
    set vars(programShortcut)    1
    set vars(includeCustomSetup) 1
    set vars(includeUninstall)   1
    set vars(uninstallRegistry)  1
    set vars(uninstallShortcut)  1

    set vars(UNIXAppExecutable)    ""
    set vars(WindowsAppExecutable) ""

    set vars(ViewReadmeCheckbutton)          1
    set vars(LaunchAppCheckbutton)           1
    set vars(DesktopShortcutCheckbutton)     1
    set vars(QuickLaunchShortcutCheckbutton) 1

    foreach platform [concat [AllPlatforms] $conf(Archives)] {
        set platforms($platform) 0
    }

    set platforms([::InstallJammer::Platform]) 1
}

proc New {} {
    if {![Close]} { return 0 }
    ::InstallJammer::new::SetDefaults
    ::NewInstall::Done
}

proc NewFromWizard {} {
    global conf
    global info
    global widg
    global newinfo

    variable ::NewInstall::vars
    variable ::NewInstall::platforms

    ## Close any previously opened project.
    if {![Close]} { return 0 }

    set w $widg(InstallJammer).newWizard
    set ::NewInstall::base $w

    ::InstallJammer::SetProjectDefaults 1
    array set newinfo [array get info]
    set newinfo(ShortAppName) "yourapp"

    set width  475
    set bwidth 12
    set height 350
    if {!$conf(windows)} {
	set bwidth 6
	set height 400
    }

    SimpleWizard $w -createstep 0 \
    	-parent $widg(InstallJammer) \
    	-title "Install Project Wizard" \
        -separatortext "Install Project Wizard" \
    	-finishbutton 1 -helpbutton 1 \
	-minwidth $width -minheight $height -buttonwidth $bwidth

    bind $w <Escape> [list $w cancel 1]

    ::InstallJammer::Grab $w

    set step 0

    $w insert step end root project \
    	-text1 "Step [incr step]" \
    	-text2 "Project Information" \
    	-text3 "Fill in the information required for this project below" \
    	-createcommand ::NewInstall::project \
    	-nextcommand   ::NewInstall::CheckProjectName

    $w insert step end root application \
    	-text1 "Step [incr step]" \
    	-text2 "Application Strings" \
    	-text3 "Fill in the information about your application below" \
    	-createcommand ::NewInstall::application

    $w insert step end root appinfo -createstep 0 \
    	-text1 "Step [incr step]" \
    	-text2 "Application Information" \
    	-text3 "Fill in the information about your application below" \
    	-createcommand ::NewInstall::appinfo

    set    text "This is the location of your application on the local "
    append text "system.  This directory will be applied to your install "
    append text "project as the initial source of files for the install, "
    append text "and you will be able to add other files and directories "
    append text "to your project later."
    append text "\n\nThis directory should be the main directory of the "
    append text "application you will be installing."

    $w insert step end root applocation \
    	-text1 "Step [incr step]" \
    	-text2 "Application Location" \
    	-text3 "$text" \
    	-createcommand ::NewInstall::applocation

    if {[llength [::InstallJammer::ThemeList]] > 1} {
	$w insert step end root themes \
	    -text1 "Step [incr step]" \
	    -text2 "Theme Selection" \
	    -text3 "Select the theme for this install" \
	    -createcommand ::NewInstall::themes
    }

    set platformlist [concat [AllPlatforms] $conf(Archives)]

    if {[llength $platformlist] > 1} {
	$w insert step end root platforms \
	    -text1 "Step [incr step]" \
	    -text2 "Platform Selection" \
	    -text3 "Select the platforms for this install" \
	    -createcommand ::NewInstall::platforms \
	    -nextcommand   ::NewInstall::CheckPlatforms
    }

    $w insert step end root additions \
    	-text1 "Step [incr step]" \
    	-text2 "Additional Features" \
    	-text3 "Select the additional features you would like in your install" \
    	-createcommand ::NewInstall::additions

    set    text "InstallJammer is now ready to build your install\n\n"
    append text "Click the Finish button to build your new install "
    append text "project, or click the Cancel button to cancel this "
    append text "project.\n\n"
    append text "Click Back to go back and change your settings "
    append text "before creating this project."

    $w insert step end root done \
    	-text1 "Final Step" \
    	-text2 "Create Install" \
    	-text3 $text

    ## The user should still be able to cancel and go back on the last step.
    bind $w <<WizardLastStep>> {
	%W itemconfigure back   -state normal
	%W itemconfigure cancel -state normal
    }

    ## Leave the finish button on all the time.
    bind $w <<WizardStep>> {
	%W itemconfigure finish -state normal
    }

    bind $w <<WizardCancel>> {
        destroy %W
        unset ::info
        unset ::newinfo
    }

    bind $w <<WizardHelp>> [list Help CreateANewInstallStep-by-Step]

    ## Finish the wizard and create the install.
    bind $w <<WizardFinish>> { ::NewInstall::Done }

    ::InstallJammer::new::SetDefaults

    $w next 1

    BWidget::place $w 0 0 center $widg(InstallJammer)

    $w show
}

namespace eval ::NewInstall {
    variable base ""

proc ::NewInstall::CreateWindow { wizard step } {
    set base  [$wizard widget get $step]
    set frame $base.titleframe

    grid rowconfigure    $base 3 -weight 1
    grid columnconfigure $base 0 -weight 1

    frame $frame -bd 0 -relief flat -background #FFFFFF
    grid  $frame -row 0 -column 0 -sticky nsew

    grid rowconfigure    $frame 1 -weight 1
    grid columnconfigure $frame 0 -weight 1

    Label $frame.title -background #FFFFFF -anchor nw -justify left \
        -autowrap 1 -font TkCaptionFont \
        -textvariable [$wizard variable $step -text1]
    grid $frame.title -row 0 -column 0 -sticky new -padx 5 -pady 5
    $wizard widget set Title -step $step -widget $frame.title

    Label $frame.subtitle -background #FFFFFF -anchor nw -autowrap 1 \
        -justify left -textvariable [$wizard variable $step -text2]
    grid $frame.subtitle -row 1 -column 0 -sticky new -padx [list 20 5]
    $wizard widget set Subtitle -step $step -widget $frame.subtitle

    label $frame.icon -borderwidth 0 -background #FFFFFF -anchor c
    grid  $frame.icon -row 0 -column 1 -rowspan 2
    $wizard widget set Icon -step $step -widget $frame.icon

    Separator $base.separator -relief groove -orient horizontal
    grid $base.separator -row 1 -column 0 -sticky ew 

    Label $base.caption -anchor nw -justify left -autowrap 1 \
        -textvariable [$wizard variable $step -text3]
    grid $base.caption -row 2 -sticky nsew -padx 8 -pady [list 8 4]
    $wizard widget set Caption -step $step -widget $base.caption

    frame $base.clientarea
    grid  $base.clientarea -row 3 -sticky nsew -padx 8 -pady 4
    $wizard widget set clientArea -step $step -widget $base.clientarea

    Label $base.message -anchor nw -justify left -autowrap 1 \
        -textvariable [$wizard variable $step -text4]
    grid $base.message -row 4 -sticky nsew -padx 8 -pady [list 4 8]
    $wizard widget set Message -step $step -widget $base.message
}

proc project {} {
    variable base
    variable vars

    set f [$base widget get clientArea -step project]

    label $f.l1 -text "Project Name" -underline 0
    ENTRY $f.e1 -width 40 -textvariable ::NewInstall::vars(projectname) \
        -validate key -validatecommand "::NewInstall::AdjustProjectName %P"
    pack  $f.l1 -anchor w -pady [list 2 0]
    pack  $f.e1 -anchor w -padx 3

    label $f.l2 -text "Project Root Directory" -underline 8
    pack  $f.l2 -anchor w -pady [list 2 0]

    set f1 [frame $f.projectdir]
    pack $f1 -anchor w -padx 3 -fill x

    ENTRY $f1.e -textvariable ::NewInstall::vars(projectdirprefix) \
        -validate key -validatecommand "::NewInstall::AdjustProjectPrefix %P"
    pack  $f1.e -side left -expand 1 -fill x

    BrowseButton $f1.b -command ::NewInstall::SetProjectDir
    pack $f1.b -side left

    label $f.l3 -text "Project Directory"
    pack  $f.l3 -anchor w -pady [list 2 0]

    Label $f.l4 -relief sunken -bd 2 -padx 2 \
        -elide 1 -elidepadx 10 -elideside center \
        -textvariable ::NewInstall::vars(projectdir)
    pack  $f.l4 -anchor w -fill x

    bind $base <Alt-p> "focus $f.e1"

    focus $f.e1
    $f.e1 selection range 0 end
}

proc application {} {
    variable base

    set f1 [$base widget get clientArea -step application]

    $f1 configure -bd 2 -padx 6

    label $f1.l1 -text "Application Name" -underline 0
    pack  $f1.l1 -anchor w -pady [list 2 0]
    ENTRY $f1.e1 -width 40 -textvariable newinfo(AppName)
    pack  $f1.e1 -anchor w -padx 3
    DynamicHelp::add $f1.l1 -text "The full name of your application not\
        including a version"

    label $f1.l5 -text "Short Application Name" -underline 0
    pack  $f1.l5 -anchor w -pady [list 2 0]
    ENTRY $f1.e5 -width 40 -textvariable newinfo(ShortAppName)
    pack  $f1.e5 -anchor w -padx 3
    DynamicHelp::add $f1.l5 -text "A short name for your application like\
        you would use for a UNIX directory name"

    label $f1.l2 -text "Version" -underline 0
    pack  $f1.l2 -anchor w -pady [list 2 0]
    ENTRY $f1.e2 -width 40 -textvariable newinfo(Version)
    pack  $f1.e2 -anchor w -padx 3
    DynamicHelp::add $f1.l2 -text "The current version of your application\
        (like: 1.0, 2.0a1, 2.0 Build 200, etc...)"

    label $f1.l3 -text "Company" -underline 0
    pack  $f1.l3 -anchor w -pady [list 2 0]
    ENTRY $f1.e3 -width 40 -textvariable newinfo(Company)
    pack  $f1.e3 -anchor w -padx 3
    DynamicHelp::add $f1.l3 -text "Your name or the name of the organization\
        or company who develops this application"

    bind $base <Alt-a> "focus $f1.e1"
    bind $base <Alt-v> "focus $f1.e2"
    bind $base <Alt-c> "focus $f1.e3"

    focus $f1.e1
    $f1.e1 selection range 0 end
}

proc appinfo {} {
    variable base

    variable ::NewInstall::vars

    set f1 [$base widget get clientArea -step appinfo]

    set vars(UNIXAppExecutable)    $::newinfo(ShortAppName)
    set vars(WindowsAppExecutable) $::newinfo(ShortAppName).exe

    label $f1.l4 -text "Install Version"
    pack  $f1.l4 -anchor w -pady [list 2 0]
    VersionFrame $f1.version ::newinfo
    pack $f1.version -anchor w -padx 4
    DynamicHelp::add $f1.l4 -text "The Install Version is used by InstallJammer\
        to track the version of files in your application for upgrade\
        installations."

    label $f1.l6 -text "Windows Application Executable \
        (like: myapp.exe, yourapp.exe, etc...)"
    pack  $f1.l6 -anchor w -pady [list 2 0]
    ENTRY $f1.e6 -width 40 \
        -textvariable ::NewInstall::vars(WindowsAppExecutable)
    pack  $f1.e6 -anchor w -padx 3
    DynamicHelp::add $f1.l6 -text "This is the name of the main executable\
        of your application on a Windows platform.  This should be relative\
        to the target install directory."

    label $f1.l5 -text "UNIX Application Executable \
        (like: myapp, bin/yourapp.sh, etc...)"
    pack  $f1.l5 -anchor w -pady [list 2 0]
    ENTRY $f1.e5 -width 40 -textvariable ::NewInstall::vars(UNIXAppExecutable)
    pack  $f1.e5 -anchor w -padx 3
    DynamicHelp::add $f1.l5 -text "This is the name of the main executable\
        of your application on a non-Windows platform.  This should be\
        relative to the target install directory."
}

proc applocation {} {
    variable base

    set f [$base widget get clientArea -step applocation]

    label $f.l -text "Your Application Directory:"
    pack  $f.l -anchor w

    set f1 [frame $f.apploc]
    pack $f1 -anchor w -fill x

    ENTRY $f1.e -textvariable ::NewInstall::vars(applocation)
    pack  $f1.e -side left -expand 1 -fill x

    BrowseButton $f1.b -command \
    	[list GetDir ::NewInstall::vars(applocation) -parent $base]
    pack $f1.b -side left
}

proc themes {} {
    global info
    variable base
    variable vars

    set themes [::InstallJammer::ThemeList]

    if {[llength $themes] == 1} {
	set theme [lindex $themes 0]
        set vars(theme) [file tail $theme]
    	return
    }

    set f [$base widget get clientArea -step themes]

    set sw [ScrolledWindow $f.sw]
    set t  [OPTIONTREE $sw.t -height 5]
    $sw setwidget $t
    foreach theme [lsort $themes] {
	set name [split $theme _]
        $t insert end root #auto -type radiobutton \
            -variable ::NewInstall::vars(theme) -text $name -value $theme
    }
    pack $sw -expand 1 -fill both
}

proc additions {} {
    global conf

    variable base
    variable vars

    set f [$base widget get clientArea -step additions]

    set sw [ScrolledWindow $f.sw]
    set t  [OPTIONTREE $sw.t -height 5 -deltay 25]
    $sw setwidget $t

    $t insert end root #auto -type checkbutton \
        -variable ::NewInstall::vars(includeCustomSetup) \
        -text "Allow users to select custom components in your install"

    set i [$t insert end root #auto -type checkbutton -open 1 \
        -drawcross never \
    	-variable ::NewInstall::vars(includeUninstall) \
    	-text "Include an uninstaller"]

    $t insert end $i #auto -type checkbutton \
    	-variable ::NewInstall::vars(uninstallRegistry) \
    	-text "Add the uninstaller to the Windows Add/Remove Programs registry"

    $t insert end $i #auto -type checkbutton \
    	-variable ::NewInstall::vars(uninstallShortcut) \
    	-text "Add a Windows Program shortcut component for the uninstaller"

    $t insert end root #auto -type checkbutton \
    	-variable ::NewInstall::vars(programShortcut) \
    	-text "Add a Windows Program shortcut component for this application"

    set i [$t insert end root #auto -drawcross never -open 1 \
        -font TkCaptionFont -text "Setup Complete Pane Options"]

        $t insert end $i #auto -type checkbutton \
            -variable ::NewInstall::vars(ViewReadmeCheckbutton) \
            -text "Add a View Readme checkbutton"

        $t insert end $i #auto -type checkbutton \
            -variable ::NewInstall::vars(LaunchAppCheckbutton) \
            -text "Add a Launch Application checkbutton"

        $t insert end $i #auto -type checkbutton \
            -variable ::NewInstall::vars(DesktopShortcutCheckbutton) \
            -text "Add a Create Desktop Shortcut checkbutton"

        $t insert end $i #auto -type checkbutton \
            -variable ::NewInstall::vars(QuickLaunchShortcutCheckbutton) \
            -text "Add a Create Quick Launch checkbutton"

    $t insert end root #auto

    pack $sw -expand 1 -fill both

    focus $t
}

proc platforms {} {
    global conf
    global info
    variable base
    variable platforms

    set platformlist [concat [AllPlatforms] $conf(Archives)]

    set f [$base widget get clientArea -step platforms]

    set sw [ScrolledWindow $f.sw]
    set t  [OPTIONTREE $sw.t -height 5]
    $sw setwidget $t
    foreach platform $platformlist {
        $t insert end root #auto -type checkbutton \
	    -variable ::NewInstall::platforms($platform) \
	    -text [PlatformText $platform]
    }
    pack $sw -expand 1 -fill both
}

proc CheckProjectName {} {
    global conf

    variable base
    variable vars

    if {[lempty $vars(projectname)]} {
    	::InstallJammer::MessageBox -parent $base -title "No Project Name" \
            -message "You must specify a Project Name for this project."
	focus [$base widget get clientArea].e1
	return 0
    }

    if {[file exists $vars(projectdir)]} {
    	::InstallJammer::MessageBox -parent $base -title "Directory Exists" \
            -message "This directory already exists.  There may be another\
                        project using this name."
	focus [$base widget get clientArea].e1
	return 0
    }

    return 1
}

proc SetProjectDir {} {
    variable base
    GetDir ::NewInstall::vars(projectdirprefix) -parent $base
    ::NewInstall::AdjustProjectPrefix
}

proc AdjustProjectPrefix { {new ""} } {
    variable vars
    if {![string length $new]} { set new $vars(projectdirprefix) }
    set vars(projectdir) [file join $new $vars(projectname)]
    return 1
}

proc AdjustProjectName { {new ""} } {
    variable vars
    if {![string length $new]} { set new $vars(projectname) }
    set vars(projectdir) [file join $vars(projectdirprefix) $new]
    return 1
}

proc CheckPlatforms {} {
    variable base
    variable platforms

    set found 0
    foreach platform [array names platforms] {
    	if {!$platforms($platform)} { continue }
	set found 1
	break
    }

    if {!$found} {
    	::InstallJammer::MessageBox -parent $base -title "No Platform" \
            -message "You must specify at least one platform."
	return 0
    }

    return 1
}

proc ::NewInstall::AddConsoleInstall {} {
    ## Create the default Console install.
    set act [::InstallJammer::AddAction Install ConsoleAskYesOrNo \
        -parent ConsoleInstall -title "Prompt to continue installation"]
    $act set Prompt "<%InstallStartupText%>"
    $act set Default "Yes"

    set act [::InstallJammer::AddAction Install Exit -parent ConsoleInstall \
        -title "Exit if they said no"]
        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set String   "<%Answer%>"
        $con set Operator "false"

    set act [::InstallJammer::AddAction Install ConsoleGetUserInput \
        -parent ConsoleInstall -title "Prompt for install destination"]
    $act set Prompt "<%ConsoleSelectDestinationText%>"
    $act set VirtualText InstallDir

        set con [::InstallJammer::AddCondition FilePermissionCondition \
            -parent $act]
        $con set Filename       "<%InstallDir%>"
        $con set Permission     "can create"
        $con set FailureMessage "<%DirectoryPermissionText%>"
        $con set CheckCondition "Before Next Action is Executed"

    set act [::InstallJammer::AddAction Install ConsoleMessage \
        -parent ConsoleInstall -title "Output Installing Message"]
    $act setText all Message "<%InstallingApplicationText%>"

    set act [::InstallJammer::AddAction Install ExecuteAction \
        -parent ConsoleInstall -title "Install Everything"]
    $act set Action "Install Actions"

    set act [::InstallJammer::AddAction Install ConsoleMessage \
        -parent ConsoleInstall -title "Output Install Complete Message"]
    $act setText all Message "<%InstallationCompleteText%>"

    set act [::InstallJammer::AddAction Install Exit -parent ConsoleInstall]
    $act set ExitType Finish


    ## Create the default Console uninstall.
    set act [::InstallJammer::AddAction Uninstall ConsoleAskYesOrNo \
        -parent ConsoleUninstall]
    $act set Prompt "<%UninstallStartupText%>"
    $act set Default "Yes"

    set act [::InstallJammer::AddAction Uninstall Exit -parent ConsoleUninstall]
        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set String   "<%Answer%>"
        $con set Operator "false"

    set act [::InstallJammer::AddAction Uninstall ConsoleMessage \
        -parent ConsoleUninstall]
    $act setText all Message "<%UninstallingApplicationText%>"

    set act [::InstallJammer::AddAction Uninstall ExecuteAction \
        -parent ConsoleUninstall]
    $act set Action "Uninstall Actions"

    set act [::InstallJammer::AddAction Uninstall ConsoleMessage \
        -parent ConsoleUninstall]
    $act setText all Message "<%UninstallCompleteText%>"

    set act [::InstallJammer::AddAction Uninstall Exit -parent ConsoleUninstall]
    $act set ExitType Finish
}

proc Done {} {
    global conf
    global info
    global widg
    global newinfo

    variable ::InstallJammer::panes

    variable base
    variable vars
    variable platforms

    ::InstallJammer::StatusPrefix "Creating new project...  "

    ::InstallJammer::SetProjectDefaults 1

    set info(Theme)       $vars(theme)
    set info(ThemeDir)    $vars(theme)

    set info(Project)       $vars(projectname)
    set info(ProjectID)     [::InstallJammer::uuid]
    set info(ProjectDir)    $vars(projectdir)
    set info(ProjectFile)   [file join $info(ProjectDir) $info(Project).mpi]

    set conf(ActiveProject) $vars(projectname)

    ::InstallJammer::AddDefaultCommandLineOptions

    ::InstallJammer::InitializeObjects

    foreach pf [array names platforms] {
        $pf set Active [expr {$platforms($pf) ? "Yes" : "No"}]

        if {$pf eq "Windows"} {
            if {[string length $vars(WindowsAppExecutable)]} {
                $pf set ProgramExecutable \
                    "<%InstallDir%>/$vars(WindowsAppExecutable)"
            }
        } elseif {[::InstallJammer::IsRealPlatform $pf]} {
            if {[string length $vars(UNIXAppExecutable)]} {
                $pf set ProgramExecutable \
                    "<%InstallDir%>/$vars(UNIXAppExecutable)"
            }
        }
    }

    array set info [array get newinfo]

    set info(ApplicationID) [::InstallJammer::uuid]

    set    info(InstallVersion) $info(MajorVersion).$info(MinorVersion)
    append info(InstallVersion) .$info(PatchVersion).$info(BuildVersion)

    if {$vars(ViewReadmeCheckbutton)} {
        set info(ViewReadme) Yes
    }

    if {$vars(LaunchAppCheckbutton)} {
        set info(LaunchApplication) Yes
    }

    if {$vars(DesktopShortcutCheckbutton)} {
        set info(CreateDesktopShortcut) Yes
    }

    if {$vars(QuickLaunchShortcutCheckbutton)} {
        set info(CreateQuickLaunchShortcut) Yes
    }

    Status "Initializing Trees..."

    InitComponentTrees

    ::InstallJammer::LoadMessages

    ::InstallJammer::LoadVirtualText

    ::InstallJammer::LoadCommandLineOptions

    set groupid [::FileGroupTree::New -text "Program Files"]
    $groupid platforms [concat [AllPlatforms] $conf(Archives)]

    set compid [::ComponentTree::New -text "Default Component"]
    $compid platforms  [AllPlatforms]
    $compid set FileGroups [list $groupid]
    $compid set RequiredComponent Yes
    ::InstallJammer::SetVirtualText en $compid \
        Description "<%ProgramFilesDescription%>"

    set id [::SetupTypeTree::New -text "Typical"]
    $id platforms  [AllPlatforms]
    $id set Components [list $compid]
    ::InstallJammer::SetVirtualText en $id \
        Description "<%TypicalInstallDescription%>"

    set id [::SetupTypeTree::New -text "Custom"]
    $id platforms [AllPlatforms]
    $id set Components [list $compid]
    ::InstallJammer::SetVirtualText en $id \
        Description "<%CustomInstallDescription%>"

    Status "Loading [::InstallJammer::StringToTitle $info(Theme)] Theme..."

    LoadTheme

    set info(ThemeVersion) $::InstallJammer::theme(Version)

    Status "Adding Panes and Actions..."

    ## Add the panes to all the requested install types.
    foreach setup $conf(ThemeDirs) {
        foreach pane $conf(PaneList,$setup) {
            set obj $panes($pane)
            if {[lsearch -exact [$obj installtypes] "Common"] < 0
                && ([$obj get Active value value] && !$value)} { continue }

            foreach parent [$obj installtypes] {
                set parent $parent$setup
                set id [::InstallJammer::AddPane $setup $pane -parent $parent]
                foreach action [$id children] {
                    set types([$action component]) 1
                }
            }
        }
    }

    ## Create default Install Action Groups.
    set id [::InstallJammer::AddActionGroup Install \
        -parent ActionGroupsInstall -title "Setup Actions" -edit 0 -open 1]
    $id set Alias "Setup Actions"

    set id [::InstallJammer::AddActionGroup Install \
        -parent ActionGroupsInstall -title "Startup Actions" -edit 0 -open 0]
    $id set Alias "Startup Actions"

    set id [::InstallJammer::AddActionGroup Install \
        -parent ActionGroupsInstall -title "Install Actions" -edit 0 -open 0]
    $id set Alias "Install Actions"

    set id [::InstallJammer::AddActionGroup Install \
        -parent ActionGroupsInstall -title "Finish Actions" -edit 0 -open 0]
    $id set Alias "Finish Actions"
    set installFinishActions $id

    set id [::InstallJammer::AddActionGroup Install \
        -parent ActionGroupsInstall -title "Cancel Actions" -edit 0 -open 1]
    $id set Alias "Cancel Actions"


    ## Add a popup to the Startup Actions that asks the user if
    ## they want to continue the install.
    set act [::InstallJammer::AddAction Install Exit -parent "Startup Actions"]
    $act set Comment "Ask the user if they want to proceed with the install."

    set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
    $con set String   "<%GuiMode%>"
    $con set Operator "true"

    set id [::InstallJammer::AddCondition AskYesOrNo -parent $act]
    $id set TrueValue "No"
    ::InstallJammer::SetVirtualText en $id {
        Title "<%InstallApplicationText%>" Message "<%InstallStartupText%>"
    }

    ## If the theme didn't already add a CreateInstallPanes action,
    ## add it to the Startup Actions.
    if {![info exists types(CreateInstallPanes)]} {
        ::InstallJammer::AddAction Install CreateInstallPanes \
            -parent "Startup Actions"
    }

    ## Add items to the Install Actions.
    ::InstallJammer::AddAction Install InstallSelectedFiles \
        -parent "Install Actions"

    set id [::InstallJammer::AddAction Install ExecuteAction \
        -parent SilentInstall -title "Install Everything"]
    $id set Action "Install Actions"

    set act [::InstallJammer::AddAction Install Exit -parent SilentInstall]
    $act set ExitType Finish

    ## Add default Uninstall Action Groups.
    set id [::InstallJammer::AddActionGroup Uninstall \
        -parent ActionGroupsUninstall -title "Setup Actions" -edit 0 -open 1]
    $id set Alias "Setup Actions"

    set id [::InstallJammer::AddActionGroup Uninstall \
        -parent ActionGroupsUninstall -title "Startup Actions" -edit 0 -open 0]
    $id set Alias "Startup Actions"

    set id [::InstallJammer::AddActionGroup Uninstall \
        -parent ActionGroupsUninstall -title "Uninstall Actions" \
	-edit 0 -open 0]
    $id set Alias "Uninstall Actions"

    set id [::InstallJammer::AddActionGroup Uninstall \
        -parent ActionGroupsUninstall -title "Finish Actions" -edit 0 -open 1]
    $id set Alias "Finish Actions"

    set id [::InstallJammer::AddActionGroup Uninstall \
        -parent ActionGroupsUninstall -title "Cancel Actions" -edit 0 -open 1]
    $id set Alias "Cancel Actions"

    ## Add items to the Uninstall Startup Actions.
    set act [::InstallJammer::AddAction Uninstall Exit \
        -parent "Startup Actions"]
    $act set Comment "Ask the user if they want to proceed with the uninstall."

    set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
    $con set String   "<%GuiMode%>"
    $con set Operator "true"

    set id [::InstallJammer::AddCondition AskYesOrNo -parent $act]
    $id set TrueValue "No"
    ::InstallJammer::SetVirtualText en $id {
        Title "<%UninstallApplicationText%>" Message "<%UninstallStartupText%>"
    }

    ## Add items to the Uninstall Actions.
    ::InstallJammer::AddAction Uninstall UninstallSelectedFiles \
        -parent "Uninstall Actions"

    set id [::InstallJammer::AddAction Uninstall ExecuteAction \
        -parent SilentUninstall -title "Uninstall Everything"]
    $id set Action "Uninstall Actions"

    set act [::InstallJammer::AddAction Uninstall Exit -parent SilentUninstall]
    $act set ExitType Finish

    if {[::InstallJammer::CommandExists ::InstallJammer::theme::NewProject]} {
        ::InstallJammer::theme::NewProject vars
    }

    ::NewInstall::AddConsoleInstall

    set conf(projectLoaded) 1

    if {[string length $vars(applocation)]} {
        Status "Adding Files..."

        set id [AddToFileGroup -name $vars(applocation) -group $groupid \
            -parent $groupid -type dir]
        $id directory "<%InstallDir%>"
        $id set Comment \
            "Base application directory.  Install to <%InstallDir%>."

        ::InstallJammer::RecursiveGetFiles $id
    }

    tag configure project -state normal

    destroy $base

    ::InstallJammer::Grab release $base

    BuildInstall

    if {$vars(includeUninstall)} {
        set act [::InstallJammer::AddAction Install InstallUninstaller \
            -parent "Install Actions"]

        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set Operator false
        $con set String   "<%UpgradeInstall%>"
    }

    if {$vars(uninstallRegistry)} {
        set act [::InstallJammer::AddAction Install AddWindowsUninstallEntry \
            -parent "Install Actions" -title "Windows Uninstall Registry"]

        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set Operator false
        $con set String   "<%UpgradeInstall%>"
    }

    if {$vars(programShortcut)} {
        set act [::InstallJammer::AddAction Install \
            InstallProgramFolderShortcut \
            -parent "Install Actions" -title "Program Shortcut"]
        $act set FileName         "<%ShortAppName%>-program"
        $act set ShortcutName     "<%AppName%>"
        $act set TargetFileName   "<%ProgramExecutable%>"
        $act set WorkingDirectory "<%InstallDir%>"

        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set Operator false
        $con set String   "<%UpgradeInstall%>"
    }

    if {$vars(uninstallShortcut)} {
        set act [::InstallJammer::AddAction Install \
            InstallProgramFolderShortcut \
            -parent "Install Actions" -title "Uninstall Shortcut"]
        $act set FileName         "<%ShortAppName%>-uninstall"
        $act set ShortcutName     "Uninstall <%AppName%>"
        $act set TargetFileName   "<%Uninstaller%>"
        $act set WorkingDirectory "<%InstallDir%>"

        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set Operator false
        $con set String   "<%UpgradeInstall%>"
    }

    if {$vars(DesktopShortcutCheckbutton)} {
        set act [::InstallJammer::AddAction Install InstallDesktopShortcut \
                -parent $installFinishActions]
        $act set FileName         "<%ShortAppName%>-desktop"
        $act set ShortcutName     "<%AppName%>"
        $act set TargetFileName   "<%ProgramExecutable%>"
        $act set WorkingDirectory "<%InstallDir%>"

        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set String "<%CreateDesktopShortcut%>"

        set con [::InstallJammer::AddCondition FileExistsCondition -parent $act]
        $con set Filename "<%ProgramExecutable%>"
    }

    if {$vars(QuickLaunchShortcutCheckbutton)} {
        set act [::InstallJammer::AddAction Install InstallWindowsShortcut \
                -parent $installFinishActions \
                -title "Install Quick Launch Shortcut"]
        $act set ShortcutName      "<%AppName%>"
        $act set TargetFileName    "<%ProgramExecutable%>"
        $act set WorkingDirectory  "<%InstallDir%>"
        $act set ShortcutDirectory "<%QUICK_LAUNCH%>"

        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set String "<%CreateQuickLaunchShortcut%>"

        set con [::InstallJammer::AddCondition FileExistsCondition -parent $act]
        $con set Filename "<%ProgramExecutable%>"
    }

    if {$vars(ViewReadmeCheckbutton)} {
        set act [::InstallJammer::AddAction Install TextWindow \
                -parent $installFinishActions -title "View Readme Window"]
        $act set TextFile "<%ProgramReadme%>"
        ::InstallJammer::SetVirtualText en $act \
            Message "" \
            Title   "<%ApplicationReadmeText%>" \
            Caption "<%ApplicationReadmeText%>"

        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set String   "<%GuiMode%>"
        $con set Operator "true"

        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set String "<%ViewReadme%>"

        set con [::InstallJammer::AddCondition FileExistsCondition -parent $act]
        $con set Filename "<%ProgramReadme%>"
    }

    if {$vars(LaunchAppCheckbutton)} {
        set act [::InstallJammer::AddAction Install ExecuteExternalProgram \
                -parent $installFinishActions -title "Launch Application"]
        $act set WaitForProgram No
        $act set WorkingDirectory   "<%InstallDir%>"
        $act set ProgramCommandLine "<%ProgramExecutable%>"

        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set String   "<%GuiMode%>"
        $con set Operator "true"

        set con [::InstallJammer::AddCondition StringIsCondition -parent $act]
        $con set String "<%LaunchApplication%>"

        set con [::InstallJammer::AddCondition FileExistsCondition -parent $act]
        $con set Filename "<%ProgramExecutable%>"
    }

    ::InstallJammer::RefreshComponentTitles

    unset vars
    unset platforms

    ClearTmpVars

    Save

    $widg(Product) raise applicationInformation

    $widg(ApplicationInformationPref) open standard

    Status "Done." 3000
    ::InstallJammer::StatusPrefix
}

} ;# namespace eval ::NewInstall
Added lib/packages/InstallJammer/icons.tkico.


















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
## Plus and minus images for trees.
tree-plus:common:tree:9:data:iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAKFJREFUGFdj3HDo8olrjxgwgIWWHEPFjK3/sQGgOEjuz5/ff/+CEFAzkP3nz6/v3z5D5b5//wpGX4By3759+fjh9dOHt6ByX79+RLPu/u1LULlPn959+PDm7dvnQBWvXj5+/ODm7WtnoHJPHt68c+P8jcsngXLXLh67dObA+RO7oXKXzuw/tm/doR0rDu5YDkQHti87vGsVSA7oPyCFiYDiAIWxmffzwx+EAAAAAElFTkSuQmCC
tree-minus:common:tree:9:data:iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAABGdBTUEAALGPC/xhBQAAAKJJREFUGFdj3HDo8olrjxgwgIWWHEPFjK3/sQGgOEjuz5/ff/9CEZD958+v798+Q+W+f/8KRl+A6Nu3Lx8/vH768BZU7uvXj2jW3b99CSr36dO7Dx/evH37/M3rZ69ePn784Obta2egck8e3rxz4/yNyyevXzp+7eKxS2cOnD+xGyp36cz+Y/vWHdqx4uCO5UB0YPuyw7tWgeSA/gNSmAgoDgATQqT7EP+oXAAAAABJRU5ErkJggg==

## Checkbox and radiobutton for option trees.
check-off:prefs:photo:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CJYyPacDtfZ5kEaiKb6DLar55FwgqpGiKZXJqYTaq01PNkIvnRwEAOw==
check-on:prefs:photo:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CK4yPacDtfZ5kEaiKlaXLJsoFYLV5Ynl6IehkZ2e+XfSZoWZPD6nf1w9UFAAAOw==
radio-off:prefs:photo:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CI4yPqcsGD1qANCqIcHrXHr6AjreRYpmRKcqm5vlVcDlLtl0AADs=
radio-on:prefs:photo:13:data:R0lGODlhEAAQAAAAACwAAAAAEAAQAIAAAAD///8CJoyPqcsGD1qANCqIcHrXHu54YBiC42RR5Ce2m8d2sPZWsHxL+l4AADs=

## Folder icons.
folder16:folder:filesystems:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAB/ElEQVR42mL8//8/AyUAIICYGCgEAAHEqKZt7ReXkLERm+S0ye1uTx9e3Y3PAIAAYmzpXvy/uiQGQ+Ln7/8MPROXYtXU21mh++71kysgNkAAscAEHz99w8DMxMTAxMwEpBkZmJmZGbAZDAKfv//fwsjIbv7//8+XAAEEN4CLnZGBlRmkEYSBhjAzMPz68Z3BvOgZFiOs5A0yr73glnXxBwggFmRh++p3GEpnFckxMDKzMrz7AoktJkZGho+ffvx78+H/hxkMMzcCBBDcAJe6DwwLqxQZvv38z/DnLwPDXyAGqmU4cY+J4frTfww//wD5/5kY2IA6btz8/Hf/iR+3DLQZLAACCMUF/4Eajtz9z/DtBwPD95+MYPztx38GkN3MDIxACHTBPyAbaDjD7//gJAAQQCgG/PzFANEMxD9+MTL8+s0A1gwyGawdpBGEgXIM3yF6AAIIxYDffxnBBvz4ycTwA6gZ5BWY5v9/QAqAXLSECxBAKAZoSjAyCFozA21lhFoN8jcDhA3CQOf/+/uP4eNHTpYEVw71nu0vGQACCMUAIR4QZiSQeP8y/P/LxKipwszfs52BASCAUAz4AXTm+0/AsAAG+a/fQPzrDzA2/kLcDUR///2H8v8xvP3MBtYDEECMYhJKllKBu46Rk5EuzncwAgggRkqzM0CAAQDWqbzmpJES5AAAAABJRU5ErkJggg==
folderopen16:folder:filesystems:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAACWElEQVR42mL8//8/AyUAIIAYVTTNfdMyCjahS0yb3B1w//bZjYQMAAggxq6Jy/+X5kWgCP7+859hwrSVX4BMHnQNE3ubnZ88vLoPxgcIIBYY48nTNwzMzMwMTExMDKysTAxAQ3mw2SgoIr2TW0jZ7tuHlxdAfIAAghvAyMjEwMLMyMDJzsjAzMTA8OfndwYWdjagDDPDgSs/GTrWfYCqVGOxLTh2DKYPIIDgBrCyMjJ8/snI0Lv9D8O//yADfzEwMnxj+PsX6KV/TAyN0eJgdc/f/mZ49/HH/T9/WLlmrTv1GCCA4AawsTAyzNz+l0FTmZfBQI4ZGA5AV/z9DzSEESjLxLDoCETd81c/GNbveH0W6FEp9jsTlgEEENyALz+ZGP4Ao9REiYVh15V/DF9/MILxtx8MDD9+MTCwMEHUMYFi/Sczk6bGX4XbZ69dAggguAFffwKd+pcRrPjzNwaGb0D+dyD+9RviBoZ/sCgC4m9MzEx/Pv768+3+LYAAghvwBhhpoDQF0vT1OyOY/vmHESgGNOAfRA4E/gMtYPjOwsn0/9Onf39+vQEIILgBW8/9ZoiyE2RYeeo/w0+gop+/IZqZQDYDw4PhL0TdH6DrNA0Z1W8emLvw/7//fwECiAUpTTFYqjIBMb50BzKFk6Fg6mv5KVtOgeMVIIDABvRu+sKQ4CLE8Ado28fPIH//AbriN8MfIA1x+n+Gv8C4BfEZmVgZbrzlZvj7+eoMkAxAADEqqRp4ZeSUb937wZHoDLSvz93/14cL4PwDEECMlOZGgABiYqAQAAQYAOO+6KysZFfCAAAAAElFTkSuQmCC
foldernew16:folder:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIbSURBVHjaYvz//z8DNQBAADGRrGMa438wRgMAAcREiWZkcYAAYgQR8sUPUBQ97FUQAVKfgfjX/6kM/xmypBgYjj9jYDgPFAGxwYYA+YZA2lIKzAYIIEaQIQVerCgWFVYuY2A4VaoIZD5DGBYLZOoDsRZU1TUgvgg0ZDEDYzYDI0AAgQ2y0vjBcO35N7y+uyBsBHXBGYjAcROwC0GGgLgAAcQCIn79+cvw8/dfsPz/178xDLmha8WAcNEriKBlDxBfBDp18X+gYewAAQQ16B/YILYP/xiiAuQYHrz7CTdk3ntlSLgcXwx0wWLMMALy/zM8+wkQQGCvaUl/YLj05AsDzzcmBj1DAYa/zMwoLlr7Ux1MB7PfhLMbrN8xNBwVArOBLhIBCCC412CGfPgJisA/KAa5MVyFML4BxaF2PP74i0Hj8jGGmzOsQCZ/BgggsEHfvyPC5dnb73gDXZDhCIOMkiQDw4OvMKEHILcABBDYoLfP/zGoaPIynLzziWDa/Pv/O8OTe88ZxF8ygVzjCDIEJA4QQCwwBfuO3SM6l/xhACYVQVEGaDoDA4AAAhtkJvyKoTNaD54EONhYGNjZmBkEeNgZ2FmZIWxuNjDNAeQbFZ6GueYtzCCAAALntWAPiCEgTSSAZ9BsBAYAAcTIYNZNejlyqlQdFsgwIYAAAiVvYVA6JdGo48jeAgGAAAIZxAY1jBTwFtk1IAAQYABU2rjPUTb0WgAAAABJRU5ErkJggg==

actback16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAPFSURBVHjaYmRIYYCA/0DMyMDG8IfBguEvQxIDK4MvIwsDH0j8/2+GTwzfGDYDVcxjYGE4AaR/QXUxAAQQI0MqVPN/Bjmg5magljgdPSkGS01jBgVhLgZmRiaGJ+9+MJy4epHh3IV7DP9eMSwCGl4L1PEIZABAADEyxANJZgYZht8MawQ0GMyLfWMZwtV8GVTY7Bh+/P/F8Pf/HwZWJmaG1/+vMmy5u5Ohde10hidnf50EujUEqPMJQAAxM+gysAM194toM3p3xKYyuMo4M3z9/Zth79OlDK8/3gf65hfDw5+XGT79/sygLqTCoK0qwnDi5XmZL8/+CQMt3g4QAEEAvv8DACoAOgERAJFgVDgALxYnAOX44ADP6sMAHAQnAEgedQASCCIA0PSwAOn74QDq+OQADwkOACAdDADH2d0w+/H/ugKIBej3ZHldbgY5KS6G61+uMDx9/5TBhseHwU++ChiozAynvqxkuPrjHNi3TEDy0+cvDO9YvjBwqbAxfHv1IxkggFgYuBh8BeRZGF78eMvw+M1rhgChWIZQxUaw5p2P+xk2PJnO8A+olRGo+emXNwzn/75jePYTyOEDYqBegABiZExj+KcXy8EoxMPG4MvizVCgtRiomYnh////DG+A3vn99zfQqyCH/mf4/u8Hw8GP+xiSjuczAIUYGHYy/AcIIBDF8OLXL4ZX334whIjzwDWDADMz0IEs7AzMTExgvhAjL4PET0kGZAAQQCzAWHr/+u0/IUZRBoa6Z3MYFPgNGDyFM8GSe95MYei/P5OBjZkbmmgYGK5+fA5yOgPDRyD+y/AeIICYGTQYtP7zMBgwAA3+9pWBYfPLbQzafMIM6txmDPJc+gxHPx1l2Pr0CsOjb18YHgLx939Ag0Dm3QXixwyrAAKImUGb4S3jL4ZEHlmgwZwMDL//MDAcfLuTQYtPkkGL247BVsCcYd3r6Qy/GP8zcLIyMHCyMzCwfgOqOws04AtDHkAAMTPoM7xk+MwgCxQ3kFBiYeBnZ2b4BwyDYx92MUhz8DHc+36TYd/bXQw8LMCMAZTjZmZi+HLqH8PPewwLgQE5EyCAGBmiwN6TAeaDNaKGzOaK5uwM3EJsDD9//gWmyB9AfzMycLNyMLCyMzF8e/eL4f7Jnwyvz/89CdQMTsoAAQRKyiDwCRjVu749+y/84ekffSZgPAtzszGI8fAw8P1nAzr1P8Ozyz8Y7hz5wfDh9r9FQM1Z4BAAAoAAgrkABiDZmYUhiRWYSJhZmfhAUfrvz/9Pv0HZ+Q9mdgYIMADeVDlsG0BwywAAAABJRU5ErkJggg==
actup16:act:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAOxSURBVHjaYmSIYWBgYAFiJjBmZvjDYAnE4QysDM5AvgojUPj/b4Y7DN8Z9jIwMqwEqj0OFPrLAAUAAcSIZIAYULiRgZchQ1NbjMFQTZ9BU1gYaCIDw70PXxguXL/GcP7iPYa/bxlmAA2vBwq/AhkAEEAwAySAmhdxazC4FngFM8RoBjOosdkw/AJa+e//XwYWRiaG1wxXGdbcWMPQs3Exw5Ozv3YzsDHEAXW+AAggZgY9oPa/DO2c6gwR9RFhDP6Kfgw//jAw7HuyguHl57sMv/5/Y3j25y7Du5/vGDSE1Rh0NMQZTrw4p/zl2T8uoPN2AQQAQQC+/wMAKgA5AQ4Al15UNgA8GzAA5/jiAM/jwgAbAicARx9yABkJLwABAQQA1vS9AOX43gATChEAGBgHAMfW3jX99QC6AoiJ4R9DhLgGB4OSHCfD9a9XGY7dP8ig8F+fwU+lkoGVmRPsSyk2bQZjviCGFz8fMRx4sY/hEcdjBi4VFpBUBEAAsTBwMjiLKLIyvPr+nuHpkzsM/rzRDKE6jcBAZYaGMgQoclgyuAgkM4SfDGG4/e0fw38+oCBQL0AAMTOYMPSLGDAyf2f7ymDHaMuQYTALqJmJYePdFgZBdimGP4zfGXa87GKQ59JlkOE0ZvjN+J5h59OTkGh/yCAAEEBMICve/P3FcOPrR4aPAr8Znvy5yjD5ZRFDy90Ghl//fjOwA13SdWcKQ/LFCIZH3y8zfP33CeIsJojLAAIIFAN3Xn/4r8nMxcDQfn8zw/wXmxle/2RgEPsGUsMIxixs3Awr7u1n2PNan+EtUI6BA4i/AvE/hjsAAcQESmH/HzMw/PkPTHHA9PX8M5D9A8KGAWZQcLADXQqM3v9ANiMXKAUAMVAvQACBYmEF4wMGBt4PDAwCbAwMfEAFXECah5UJmIBYGFiY2IBirAzsrEA5oLgAUDMP0BLGh2AXrAAIIGYGfYbnQOeIsDMxmEoosTDwsjEzcANT3j+WvwxqAnIMb34/Zdjyag1YtQAHCwM3MIC/nP7H8PMBwzRgEpwDEECMDFFgV0oAM9AiUUNmVwVTdgY+UXaGXz//M3z9/Q2o7T8DNysnAwc7M8MnYOA8OP2T4fX5v7uBmsFJGSCAmBl0wQZ8AYbWzm/P/vN+ePLH5P+X/wz8HMwMAkCNvP/ZGf59+M/w5MIPhrvHfjB8vPNvBlBzHlDPS5BGgACCuQAeXuDszMQQzsLN4MzEzKgCEvz39/+dP1+B2fkfZnYGCDAAkBQi8GwctlQAAAAASUVORK5CYII=
viewmulticolumn16:view:actions:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAM9SURBVHjaYtRtf7hLWIDd8c+v/wy/vv5h+PX9LxAD6W8I9u8fQPrbX4bf338z/Pn5j+Hfzz8M///8YPj//eF+gABiERfltjNQE2L58IGB4csnBoavXxkYPoPoTxD+f0YGht9/GRj+MjEw/ALS/34yAAWBmBFEb7UDCCAWIQ7G36o8DOxAtQw/2IGYF4j5GRi+/wDS34H0NygNwkDDfwEN+Ac0gAloyq2LLL8BAohFTfg/Q4Ie0LD//xn+//oClAWaxMYDlGaE2PT/L1D8K1CYGegKToa///4y/Pvzn4GdlYEhvpqJASCAmJiBaliBzmP7+pjhf5cMw/8eGQb2n08YOIAKONgYGNif7GBgaBNiYJmjz8DLzcQgyMvKwM3JwMDF9p+Bhek/A0AAMTEATQSB/0D677evDEw/vzO8f/2aYfHSFQwv3wI9xvif4d/XfwxMv78z3Lp1l2HhoiUMHz9+AboEGC5//zMABBDLX4h+BkZuSQbOpDUMTMxMDL8FZRlkZb4xsLEBnSFlycCSsgRopTADOws7g4S4JAMjIyNQMzA2/v9jAAggFqDnISawcjAwqQeAmdxA7GAvCmb//svJ8F8niuHXHwYG0d+/GMTFxYEB+ovh9+8/DP/+/WMACCCW/zAD0ABI+Pfvf5DABQfcP4Y/wMD7B2IDo4ERJA7EAAHEAuJgaAbiP0ANIMX/GVkZfrMzg9PBP2AsgZ0OtJkJagBAAAED8R9E09cXDD9nW4Pxvw/PGBiAYfGflYXh78MDDMxTdBhYV/pAlTKBA+/vn/9gVwIEECIMgKH87+4pYACBEsxHhmfv/jEIiokzcH5/zcBy7xrDf/G3DF+AyfTd23cMwsIiDMyguAfqBQggJngQsPMxMBmHMLCahzN8AOaBDevXMLx59pqBWVCZ4behBwODThDD82dPGHbv2cLw48cPcFoGaQUIIIbqVY8+A/30HwUD3Qiif3/79v/zpx//P/789//Np3//P775+P8bkP/iyev/b5+9+O+fsfEzQACx7D739s+T5x///PwGzGnAuPrz8xfDn9+gXAdMWCD6F0T8758/4NCFOZiZiZHhxr0PfwACiBFXNBILAAIMABvGsDfmxCuOAAAAAElFTkSuQmCC
mimeunknown16:mime:mimetypes:16:data:iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAABl0lEQVR42mJcsWLFfwYKAEAAsYAIbuVwhvcfGRi+/wTiX1AaiL9B6Z+/UDX9A1opLsrAoM++kgEggMAG2OswMHz5xsDwHyjx9x8U//3P8AeE//xj+AfUAcL///8DYiAbiHl5uBjOH2VgAAggsAG8HBCMCoCmATWA8L//f4EUUOPff2DN/4BibGzfGc4DVQEEEAs2f4FtAWr4+xdi4///jFD+f4Tcv79gtQABxIRdM0wjKobJ//79G64eIICY0DUjK4RhZANBmkF8ZmZmsDqAAGLB5gJs+O/fv2AMYoM0wwwACCAWfBph4iCNf/78AfNhGhkZGcE0QACBDfj16xfDz58/GZiYmHA6HyQH0wT2O1QtQADBXQBSCMLoAKQJphhmGLILAAKIBeYsmNOwAZDib9++Mezbtw9DDiCAmGAGgGzBhUHyMNeFh4czBAYGMuzfv39SREQEB0AAsaD7CRtA9v/r168Z8vLyWoGZsA7kK4AAghvAwcGBN9fx8fGB6bCwsJwDBw5MhYkDBBAjqdkZ6AVG5NgACDAA4TMV4APib38AAAAASUVORK5CYII=

## Dialog icons.
dialogquestion:act:actions:32:data:iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAYlSURBVHjaYvz//z/DQAKAAGIBEYyMjERrOMbAoACkFP4xMDgAMQPI+f8g+ACQ/cAFiIk1C+R5gABiBBMEHHCKgUEAaHgC0JJ4IG0AtRBuORp9AYgXAtkLvBgYPhByAEAAEXQA0PIGoGH5QEMFQMHFB8RcQMyhr8/Axc8PVvMNhA8dYvgIpN8C8XeIQz4A8UQ/oH58DgAIIJwOOA3x9X6Qj0EWi4JwRAQDi7c3A4uvL1YD/126xPBnyxaGx8uXM9x//BjsMFCIAM1wDMISGiC7AQIIqwOAlhtALRcQAfIlXV0Z2OvrGZhkZcHyfz99Yvh48iTDn2/fGNgVFBj+//nDwMLJycCjpQU341dfH8PN+fMZ7gDVQkPDMQzoGHQHAAQQhgOgPr8PslyKl5dBvKSEgTUgAGLos2cMn27eZGCWl2cQhIohg3e7dzNwsrMzcAoIQELkxg2Gu7W1DBdu3QKlD5AjFCORQgJkN0AAYTgAGOfnQcEuCWRLz57NwKSqConnu3cZPr9/zyBeXEw4eQMtZHj+HGLJ588MtwsKGM4B9YOiI5qBwRDZAQABxIQlwRmAgl0iJ4eBSQTIAlr698kThs/v3hFnOQioqTEwAKMEpJcRGD0qWVkMqtzcoFAwWIyWKAECCB4CJ4FBDuTfZwbSWgYGDJx5eXBFby5eZBCZMAHTl6eATv79m4EBaDiDszMDg7AwQv7LFwaG1avh3N9HjjBsmjePASj6AegQxUQQDbQbIIDgIQDN5wJiQDa7FzAHA30Mw8wqKqiWfwRmuM2bGRhevoSoAaX4adMYfn9ASug8PMB4+wY3gxWYQDUFBUH2gMsUmDKAAEJ2QDw4u+npMTCB0gQw+GCYGeRDZLBnD4o8GL96xfDhwgVUdRwcYLk/wJD6uWYNgzzQx5yQrBkPUwIQQCyw4hUoaMALEpCSgrgaCXCJiiI4IF8dA+r4/h1FzX1gaGg7OKCI/QCGyp+rVxn+//wJFwMl7ptAu2ZCivQHAAHEAvW9AqgYBfmTmYsL4iPkCuPECUhcy8kxMBw+DEwUb1Dkb//6xSANzG7I4O+BAwy/z53DSJ8gr9yA2glyAEAAgR0AqlhADmBnYWFgBCUebACYx7GB26ysDApLljCwQvM+2EPAtPAjMRGrem5E5QUKrgMAAQQLAbAgNyjroAU/PnABGFraK1diWP7N0ZHh3wPslaIgUsUFAgABBAsBiAAomIl0ADATMmgDQwWr5eiJEb0OgNoJAgABhOKAr8DEwvX2LVH1OAOwUEKxHOjjH4GBwGC5wMCER+9btBAACCBYFBwACtb/AhkMLDrxWfwHZACQFrCzQ5H7DbScEWg5MwHHf0M44ACIDxBAsBB4AHIRqD6X+PcPtXYEWvYfycUgGWYkPlgJyNcEfA4DzxHBD04kAAEE1uMK5IAqildQAUZILQXBUDFmNMz68CGiPN+4EUMeF74HcfyFIqgDAAKIBd6YADajgMFj8BSYrWSYmQn6RKiigoHh2jVgiQ4sfhctYmAElXoEwLW/fxk+AhM60AELYWIAAcSClDIXgNLBjb9/BWSgTS184DIQCwPbC/+BWERdnYH96VPCDVpgDvsHaQ8sgIkBBBBKe2ATsKoEOUId6AANQUHcKRlUtG7bxiAMrDXBANjqYbCxwZuAjwNL16PASgzo0cYyaJUMshsggDAaJOugDRJjYJ0gj8MRz75+ZZC6fx9VEFTynT6NVf1VoOXbga0pUNyXoTVIAAKIBUsh4QgMhfsnnz0T+AdsXimKiWEYyAtMJ+D6HlTlwgAoLSDzYZYDa0mo5aB2gCO6PEAAYW2UroQ2SkHtAx1go1NXWRnTW6A2QlwcxNK1axkYjh7FDHZgM+wosICCWV6OpVEKEEA4m+XLgJb/gzbLuYB1hB4woamAakMiwLVHjxiOARuvH4BV9n9os7wcR7McIIAIdkwWQRImuGPCDWyYyElLM0gAo4UX6HNhISFIkw2Yuj8Bo+QxMLjvAHPDR2Aa+Qfx9cQyAh0TgAAiqms2D6lr9g8SPQxo/ULk7hm8a1ZGRNcMIICIcgAymAFpvMA7pzDL/0M7p0Ukdk4BAohxoLvnAAEGABadteqVSIbNAAAAAElFTkSuQmCC
dialoginfo:act:actions:32:data:iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAY8SURBVHjaYvz//z/DQAKAAGJiGGAAEEAsMAYjIyNehcqxOwUY/v5P+Pfvnz3D338O//7+Ffj/9x/D/79/Gf7/+ccA5H8A8g/8//P34P9//xa8PJLwAZ95sJAHCCBGOAOHA1QT9gj8//e/H2hoAsiyvwzMDN+5BBl+cvAyMPz7DzEISLN8esfA+uY5A8OPHxBH/f274P/f/4VvzqZ9wOcAgADC6wDVxL0BQMPng3z7nVOAgUFSnsHRWJzBTpaBQZ4fokYBSD/4yMDw8ScDw6FHDAw7T75geHPyHAPLy6ewUEl8fzl7Ay4HAAQQTgeoJe0D+brgFxMbww8FbYYYKyGGdEMGBn52wvG6/BoDw8Qtzxje7drLwPjpIyg0Jny8WVCIzQEAAYTVAWrJQMv//iv4wcrNwGtowjDZi4VBhhehWQDoCDFuCPvHHwaGG89/MHBxc6A44hMwRNoO/GTYPXktA9PrlwxAz0z4fK+kEN0BAAGE4QCgzwOAYut/sHAx6DuaMNTas6AYzM7MwKAvjurjyYuPMyjoaDKIiwtghMaWaz8ZeitXMTC9es4ATMCB355UbkB2AEAAoWRD1aS9AkCJ+b+Bwc6uZ8KQYMjC8P4HAwr+9RczyIX4OBg2bj+PoRaErZXYGdwKwxj+cvOCcst8DrFmFFcCBBBqOfCfART0Ap9ltRlyzVkYfgMte/8dFd99z8Dw7geqA5ZtusDAKSCAoRaGw/XZGSQCvEDRAMq6/ch6AQIIHgVqCUDfM/x//41DgMEAGPTeyrgTGRswGvj/fGB4cu06w9zlxxlktDQZ/KI88SbMW0CHTytbyMD44B4wUf4T/PWpGZw9AQKIBSlRJABdyPBNQonBQAzoy+/4U/oLBmBIKlkyRFRbgvn41L/8BsmqrKbmDL/v3gGFRAJQeAJIDiCAEA4AlnCgQkZKSojhGzBlgzBGuSAEwTAgxcPAwMnKwLDvygeGC+84GFg5ETnh8y8GhguvGBjuvIeUEWCgqMHAwsrO8P/bV3uYAwACCNkBDt95hBmk2HH7hgWYYqxkGBi4WVHFV14+z3DqJgODppMjwyugby8CLX7+FbsZ/2TlGRiuXXaA8QECCOEAYOL7yc4LKlUZ3uJwwKZbwGx1/gNDf6AAg7IgcuL9w/DuGyPDtnsMDG8IRN1/MQkGhssX4TkBIICQHQBKCODgwltDMwow7H/AgOKA/39/MjwCxvHv74RLSVjdAQMAAYTiAJAkqAT7/Qe/Id/R5P//BebLv0TWv2ieAwgg5DQAdtlHoFlfCbQSvv3GdMD/v4wYhhMDAAIIOQQ+sHx6L/AJaDgjPsf/h5T/KOL/gA74A9T1jwgbnz0FkfAqGiCAmBAO+HuA7T2w0gAGJSgw/kPxPxj+ywCWA4lh+BSYBv7/+QlxACF8/y5IxwGYVoAAQnLAv4OMv34wcLx6Ao7P/1DMAMPIhvzHkgb+/CBs+bUrwOADp9SDML0AAYScBhaAymnuJ9cYGMVl8McbE3oU/AQWYczgmhIf+HnyECyWFsDEAAIIbtSzPVGg1ssC5jfPGLg/vWDgYWPAiQ0lUQ329/NhEBPiw6uH7cldhn8P7kIt74OnAYAAQmkPiFnPB9VW9xk4uAS4PIIYmNjYUCzSFGVg2BqD24d+1RsZLvE4MTBx8KImke/fGZ719jH8efcOZLEiyAEwewECCKNBImI6OwDoiPXMAoIMoj5+DEzsiDYYL9A98t+vMnx/cB4Y7MDC/t9vYNnxB1JyMTIxXLp6l4HNOoOBXUIVrufPt+8M9ydOY/jx5BmIGwi0HKVBAhBAWJtkQvrTwE0yNiEhBvnQIAZmDnYGcgDI8qs90xi+PQZb3gi0vAG9SQYQQDgbpQJak/qBLZgCVl5uBiVfdwZ+RVmSLH97/S7DtTkrGH68eYdhObIDAAIIb7OcT6UvANi0ng90iICAgjSDnI0Jg4SeOl6Ln56+wnB3+yGwA6AFTiIs2LE5ACCACHZMuOU6wc0oYEGVAOoBsbCzMgiryDEIyEjAi2+QGe/vP2V4de0uw6+v8BoJlNUKkVM8NgcABBBBB8AAh0iTALR3ZP/vzz+H/8hdM0jt9gFawh1Ez2r4HAAQQIwD3TsGCKAB7x0DBBgAzPMp3/mFRxcAAAAASUVORK5CYII=
dialogerror:app:apps:32:data:iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAXJSURBVHjaYvz//z/DQAKAAGIBEYyMjEQpPs7AEAB0rgEQ2/9jYBAAsYE0A5C+AKQ/APFBENuNgWEDMeaBPA8QQIxgAo8DTkEsKgDieKAFCqDwAqnmgFgMx1+A+DcQQx30AEgvBNITfIAOw+cAgADC6wCg5QFAaj7It6CgEgBifnl5Bh5bWwYmII1i2IcPDJ8OH2Z4fekSwwsg/zvEMR+Ajkj0xxEiILsBAginA04zMPSDfA6SEQFiibAwBtbISAZmGxu8wfrv0SOGP8uXM9ybNYvh3qdPDL8gDpkQzMBQiM0BAAGE1QFAy+cDLU9gA7LlNTQYeGtqGJgtLEhKXP8/fmT4UFbGcGbvXoZPEEcsCAOGBroDAAIIwwHAYO8HUgV8QELazo6Bu7GRgZGXl+xU/m3pUoYL/f0MT6AhEYkUEiC7AQIIxQHQOF8P8rmylRUDT1MTwiQ+oJM+fSLOVjS133fsYNjf08PwEeKIwBhomgDZDRBAcAdAU/t9JiCtLCrKINDdzcDIzQ0xQVGRgcHYmIEBGL8Mp07ht9zMjIFBTo6B4exZoGn34cLvpkxh2HPwIChNgLKrYjwogQLtBgggJnhwQLKaACjB8cXFMTD+Aip9/56BQUwMYjkIgAw2MICIY8MgOZAaEADpAemFygkGBjKoc3IyQMuPApi9AAGE7IB4UFYTU1JiYBYXB7oPmH3ZgJEBTAcoQEWFgQEYPWB5ZAwSA8khA5BekBlAeZCHtHx8GDgh0RAPUwIQQCywEg5UyAgB2WyGhhBXgwCIBgUlLARgQFubgQEUQqtXQ/ihoRAxdADU+x9YLvx9/Jjhz61bDH9fvmQAhc8VoF2zIeltA0AAsUB9DypeGXiArmURAUbCu3cIQ2YDlf78CfEhMgA5FCQOY6OBv2vXMvyurWX4ff06irgUEF+GhIIByAEAAQR2AJBjD4oLbgEBhO+RwcSJEMscHVHFcZQNvxcsYPiRmIhVTgAa7EDT7EF8gACChYAAqGxn4eHB7gAQaG+HBLu7O95MgM9yGOAH4hcQtzAABBAsBMC1GsOPH6jBjw6qqyEh4edHtuVQD8OigAEggGAhAMYM37/jDgEY+POH4jYA1AFgABBAsBC4AEqIYAfga6BMn87AEBSEU5o1IQFM/yIQClAPXwCxAQII5oAPX0EMUPCC4hkbmDePgSEigqDvQI4AJejfeBzxBuIAcDsBIICYoC46CLL2K9D3/7Dg/yDL4+Mxq15gnIMwOmAGOoJt/nwGZhAbDYMi+AfE0wdBagECCFwh7AQWCjuA7rgFxP/Q8fz5/7ECoDhMzX8cav4hqYHhY0DcB8S9oOYd0G6AAGKANUq3AauOfSDD2NkR2NQUu+WLF6OqA2GQGDYAMgNJ3RygHT1Au2CeBwggeF0AasOB0sE9JqAQqBYE4bt3GRhyc1HDd8UKBob8fIQaGAaJgeSQAUgvyAyomnNAsz9AonwhTAlAAMGr483AggHoiPssTEwCDsDKiIuFBWEQqKzvBQbamjUMDEVF+FNhHzCAQ0IYGIqLEXUFEHwCZt9FwLrg+79/IDcolkGrY4AAQmmQbIBUSuv52NkZ7ICNTlYmJoTBmpoMDGjlOk6Apvbnv38MKx8+ZHgJqTsCy5AaJAABhNEkWwNtjMoLCTEYAOt2VuSQIAP8BPp8P7AhcxlYwoKa6eVoTTKAAMLaKF0JbZTyA+PNFljNcnNykmX5J2DBtuHqVYaXX7+CLF9QjqVRChBAOJvly6AhwQIMAV1VVQZNULOMBHAO2Bw7dvs2w3dgCKD7HNkBAAGEt2OyGJImQKEhwMXFxaACTBdyMjIMwoKCWNW/BtYjd588YbgKjO8P376BS1igcGIZno4JQAAR7JotgLbh/iF1zViBDRchoCP+IVVkr4CW/wAW49CKBtw1AzInlBHomgEEEEEHIINZDAwOQAsc/uHonP6Hdk6LSeicAgQQ40B3zwECDADHffpXRiyNMwAAAABJRU5ErkJggg==
dialogwarning:app:apps:32:data:iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAYuSURBVHjaYvz//z/DQAKAACIbnfZhUDzmyaAEZDIBMSO55gAEEBM5mi74MjSyMzHc42FluAt0RBtQiINcswACiJkcn7MyMawT1GVg4BRnYPj3hsGGl5Vh69FXDG+A0n9JNQ8ggEh2NRsTw3xmoH8lXSAYxA6QZZgElOIlx0MAAcREYtAHAiPbHmYxzCHAqDCZZ80QAlTCSWp6AAggkhzAyMjQzwEMdkFLPQYGs9NgDGKDxHQFGWqASviAmJUUMwECiImUhAf0mryUK1CLQi0wyYlBMJANEgMmSsktzgxVQKVcpJgLEEDMxCY8FmDcCwE9K+IdzsAgHg8U/Q/BbFIMbFzPGH4/u8rA+o5Bg4uFYdfx1wyviU2QAAFElAOy1RkmsHIymMuG8TIwa09kOH7qOcOWLacZzpy5w/Dnzz8GWTUrBg7WtQwfL/xil2JjEF50l2EHUNtPqCvxAoAAIuiA874MjszAuBezY2Lgcy5lePfHlGHv3gvA9MDIwMTExPD06RsGAWEZBjE5QYb/748w/H/CoKElwHBp+1OGO0DtfwiZDxBABOOKCWg5myADg5iXCgODUCDDjx9fwOKgIvzfv39g9ocPH8ByYl7KDCC1ZiIMtdAEyULIfIAAYiKQ8BKBCU9f0gdISuQA8x0bAxvbf7DlMAeAsLAwG1iOQTKDAaSWk5lBfZkdQwI0W+K1AyCAcEpe8mMQAPq+j1sZ6BVLO2BmNwaK/mAQEWFlYGb+D4z7P3AsIwNK+N/AavjMTRlAerT4GSr9ZBlkCWVLgADC6YB//xkagJSATDTQcNE4YCHwH+wAEJaX52X49esXGAsIsDKws/8Gin8HqgEmfLEYBpkoNlDU8WZpMFQAJbjxpTWAAGLCle2ABuSL2ANzmYI7kAB55CvEEiCWkmIFpoUfDD9//gSzIXIg/JmBgV2SgU3elgGkV4qTISZXg0EHKMGOq4QECCAmnOU9MPbE/IQZGPjdkCwA4S8MsrJMDN+/f2f49u0bg4oKG8Rihk9QDGQL2jOI+fIwgMyIVGToBQry4AoFgABiwlnehwJ1SDgD0zEvwmAw/sIgKPgTiP8zfP36lUFZ+T+SPIh+D9TDCdRrzgAyg1A9ARBALFjLe1mQJySAsWcCFHmHxa3/gAnvL8Pfv6Bs+AFa6IEwKC38gmR/bi0GQbvTDG/2f2LQ/QeuJzZCC6dfyPYBBBAzenkPjHt/uQxgNCh6AH0iBI33H1D8HZLagWxFRUYGbW0WBm7uH/CogdDfIGxGoF3MTAwcwo8ZPh9j4PWWYeBYdp/hMNQB8BISIICYkbMdMIBWCNmAyns5YJViADXsJzzxQfjfwRaxsX3HYjkyGxglLOwMbAJvGH6//sHA+pxB4/E3hjW3PzF8RC4hAQKICSnbTWDhYuAXCwZGE5cqNOjfQjEy+y3Dtm0PGdzdLzJYWJxjmD37Hg61HyCYS4JBLBhYGHAz8BZpMTSjZ0uAAGJGKe/9QIWOJFC1MFrQf0PCXxmSkl4wvH37A1wOHDv2kSEg4B8DHx9CHhFaQMz0D5gbfjH8B6r9f5tBQ0eA4eK2pwx3YaEAEEAs0PK+nk2UgUHYB5in2UA55g3Ubdhy6X9g9vsCzAH/gInwL7go/v//LzRa/4ITKAQjsdmBVaQPE8P7Q/8YDH4zFAEF90HTwm+AAGIGlfegQkcmF5hPlICWMzMi+fwHUkgg0oCg4C+GzZt/gYvh4ODfDOHhP+GJExMD5Rh/MTCx/mdgE/vH8P04g5S9OMPbNQ8ZLoAcABBAjBf9GB7w6DDIK7WAfMcPVMwCza7I+D+U/gcPBQT+h8ZmgPr+Pyr+DwmRe8AM+e4Sw3PTLQxmQIFXAAHEAmpmMQOTxderQCuYYMHGCC4QoCUDSvBD62I4+z88yJHF0S1HqAfZBWq+QVvRHwACiOXHX4ZpDCcZsj6dBFrFDAwyJma45YzIDkHqwv1HdggMg9QhWcQArbJRGkVQ5v0vDKuhCYwJIIBApnOU6TAYirAzaP76x8ACzI5kd7OIAVc/MDxb+YDhIaTMZngNEECMUJewQ8tqVkr6eUSC/9AyG5SqfwIEEHJEM5LbvyMDwFMuQAAxDnT3HCDAAN6sBt/v91SLAAAAAElFTkSuQmCC
Added lib/packages/InstallJammer/lang/ca.rc.










































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
! ------------------------------------------------------------------------------
!  es.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of spanish resources
!  daniel@rawbyte.com
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:    A&vortar
*retryName:    &Reintentar
*ignoreName:   &Ignorar
*okName:       &Si
*cancelName:   &Anul·lar
*yesName:      &Si 
*noName:       &No

! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       &Negreta
*italicName:     &Cursiva
*underlineName:  &Subratllat
*overstrikeName: &Tatxat
*fontName:       &Font
*sizeName:       &Tamany
*styleName:      &Estil


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    Nom d'&usuari
*passwordName: &Contrasenya 

! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:        Selecció de font
*SelectFont.sampletext:   Text d'Exemple


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Indicació
*MessageDlg.infoTitle:      Informació
*MessageDlg.questionTitle:  Pregunta
*MessageDlg.warningTitle:   Atenció
*MessageDlg.errorTitle:     Error


! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Introdueixi el seu nom d'usuari i contrasenya

Added lib/packages/InstallJammer/lang/de.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  de.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of german resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:   &Abbrechen
*retryName:   &Wiederholen
*ignoreName:  &Ignorieren
*okName:      &OK
*cancelName:  &Abbrechen
*yesName:     &Ja
*noName:      &Nein


! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       Fett
*italicName:     Kursiv
*underlineName:  Unterstrichen
*overstrikeName: Durchgestrichen
*fontName:       &Schriftart
*sizeName:       S&chriftgrad
*styleName:      Sc&hriftschnitt

! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    &Login
*passwordName: &Password


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:	    Schrift Auswahl
*SelectFont.sampletext:	    Beispieltext


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Meldung
*MessageDlg.infoTitle:      Hinweis
*MessageDlg.questionTitle:  Frage
*MessageDlg.warningTitle:   Warnung
*MessageDlg.errorTitle:     Fehler


! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Enter login and password
Added lib/packages/InstallJammer/lang/en.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  en.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of english resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:   &Abort
*retryName:   &Retry
*ignoreName:  &Ignore
*okName:      &OK
*cancelName:  &Cancel
*yesName:     &Yes
*noName:      &No


! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       Bold
*italicName:     Italic
*underlineName:  Underline
*overstrikeName: Overstrike
*fontName:       &Font
*sizeName:       &Size
*styleName:      St&yle


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    &Login
*passwordName: &Password


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:	    Font selection
*SelectFont.sampletext:	    Sample text


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Message
*MessageDlg.infoTitle:      Information
*MessageDlg.questionTitle:  Question
*MessageDlg.warningTitle:   Warning
*MessageDlg.errorTitle:     Error

! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Enter login and password
Added lib/packages/InstallJammer/lang/es.rc.










































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
! ------------------------------------------------------------------------------
!  es.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of spanish resources
!  daniel@rawbyte.com
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:    A&bortar
*retryName:    &Reintentar
*ignoreName:   &Ignorar
*okName:       &OK
*cancelName:   &Anular
*yesName:      &Sí 
*noName:       &No

! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       &Negrita
*italicName:     &Cursiva
*underlineName:  &Subrayado
*overstrikeName: &Tachado
*fontName:       &Fuente
*sizeName:       &Tamaño
*styleName:      &Estilo


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    Nombre de &usuario
*passwordName: &Contraseña 

! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:        Selección de fuente
*SelectFont.sampletext:   Texto de Ejemplo


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Indicación
*MessageDlg.infoTitle:      Información
*MessageDlg.questionTitle:  Pregunta
*MessageDlg.warningTitle:   Atención
*MessageDlg.errorTitle:     Error


! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Introduzca su nombre de usuario y contraseña

Added lib/packages/InstallJammer/lang/fr.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  fr.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of french resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:    A&bandonner
*retryName:    &Réessayer
*ignoreName:   &Ignorer
*okName:       &OK
*cancelName:   &Annuler
*yesName:      &Oui
*noName:       &Non

! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       &Gras
*italicName:     &Italique
*underlineName:  &Souligné
*overstrikeName: &Barré
*fontName:       &Police
*sizeName:       &Taille
*styleName:      St&yle


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    Nom de l'&utilisateur
*passwordName: Mot de &passe


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:        Sélection d'une police
*SelectFont.sampletext:	  Texte d'exemple


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Message
*MessageDlg.infoTitle:      Information
*MessageDlg.questionTitle:  Question
*MessageDlg.warningTitle:   Attention
*MessageDlg.errorTitle:     Erreur


! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Entrez le login et le mot de passe
Added lib/packages/InstallJammer/lang/pl.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  en.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of english resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:   &Porzuć
*retryName:   P&onów
*ignoreName:  &Ignoruj
*okName:      &OK
*cancelName:  &Anyluj
*yesName:     &Tak
*noName:      &Nie


! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       Pogrubiona
*italicName:     Kursywa
*underlineName:  Podkreślenie
*overstrikeName: Przekreślenie
*fontName:       &Czcionka:
*sizeName:       &Rozmiar:
*styleName:      St&yl czcionki:


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    &Login
*passwordName: &Hasło


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:	    Wybór czcionki
*SelectFont.sampletext:	    Przykładowy tekst


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Wiadomość
*MessageDlg.infoTitle:      Informacja
*MessageDlg.questionTitle:  Pytanie
*MessageDlg.warningTitle:   Ostrzeżenie
*MessageDlg.errorTitle:     Błąd

! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Wpisz login i hasło
Added lib/packages/InstallJammer/lang/pt_br.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  en.rc
!  This file is part of Unifix BWidget Toolkit
!  Definition of english resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:   &Abortar
*retryName:   &Repetir
*ignoreName:  &Ignorar
*okName:      &OK
*cancelName:  &Cancelar
*yesName:     &Sim
*noName:      &Não


! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       Negrito
*italicName:     Itálico
*underlineName:  Sublinhado
*overstrikeName: Sobreposto
*fontName:       &Fonte
*sizeName:       &Tamanho
*styleName:      Est&ilo


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    &Usuário
*passwordName: &Senha


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:	    Selecionar Fonte
*SelectFont.sampletext:	    Texto de amostra


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Mensagem
*MessageDlg.infoTitle:      Informação
*MessageDlg.questionTitle:  Questão
*MessageDlg.warningTitle:   Advertência
*MessageDlg.errorTitle:     Erro

! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Informe o usuário e a senha
Added lib/packages/InstallJammer/lang/ru.rc.








































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
! ------------------------------------------------------------------------------
!  ru.rc
!  This file is (currently not) part of Unifix BWidget Toolkit
!  Definition of russian resources
! ------------------------------------------------------------------------------


! --- symbolic names of buttons ------------------------------------------------

*abortName:   &Ïðåðâàòü
*retryName:   Ïîâòî&ðèòü
*ignoreName:  &Èãíîðèðîâàòü
*okName:      &OK
*cancelName:  Î&òìåíà
*yesName:     &Äà
*noName:      &Íåò


! --- symbolic names of label of SelectFont dialog ----------------------------

*boldName:       &Æèðíûé
*italicName:     &Íàêëîííûé
*underlineName:  &Ïîä÷¸ðêíóòûé
*overstrikeName: &Çà÷¸ðêíóòûé
*fontName:       &Øðèôò:
*sizeName:       &Ðàçìåð:
*styleName:      &Ñòèëü:


! --- symbolic names of label of PasswdDlg dialog -----------------------------

*loginName:    &Èìÿ ïîëüçîâàòåëÿ
*passwordName: &Ïàðîëü


! --- resource for SelectFont dialog ------------------------------------------

*SelectFont.title:	    Âûáîð øðèôòà
*SelectFont.sampletext:	    Îáðàçåö òåêñòà


! --- resource for MessageDlg dialog ------------------------------------------

*MessageDlg.noneTitle:      Ñîîáùåíèå
*MessageDlg.infoTitle:      Èíôîðìàöèÿ
*MessageDlg.questionTitle:  Âîïðîñ
*MessageDlg.warningTitle:   Ïðîäóïðåæäåíèå
*MessageDlg.errorTitle:     Îøèáêà

! --- resource for PasswdDlg dialog -------------------------------------------

*PasswdDlg.title:  Ââåäèòå èìÿ ïîëüçîâàòåëÿ è ïàðîëü
Added lib/packages/xdg-utils/xdg-desktop-icon.






























































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
#!/bin/sh
#---------------------------------------------
#   xdg-desktop-icon
#
#   Utility script to install desktop items on a Linux desktop.
#
#   Refer to the usage() function below for usage.
#
#   Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
#   Copyright 2006, Jeremy White <jwhite@codeweavers.com>
#
#   LICENSE:
#
#   Permission is hereby granted, free of charge, to any person obtaining a
#   copy of this software and associated documentation files (the "Software"),
#   to deal in the Software without restriction, including without limitation
#   the rights to use, copy, modify, merge, publish, distribute, sublicense,
#   and/or sell copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following conditions:
#
#   The above copyright notice and this permission notice shall be included
#   in all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
#   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
#   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
#   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
#   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
#   OTHER DEALINGS IN THE SOFTWARE.
#
#---------------------------------------------

#@xdg-utils-common@

#----------------------------------------------------------------------------
#   Common utility functions included in all XDG wrapper scripts
#----------------------------------------------------------------------------

DEBUG()
{
  [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0;
  [ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0;
  shift
  echo "$@" >&2
}

#-------------------------------------------------------------
# Exit script on successfully completing the desired operation

exit_success()
{
    if [ $# -gt 0 ]; then
        echo "$@"
        echo
    fi

    exit 0
}


#-----------------------------------------
# Exit script on malformed arguments, not enough arguments
# or missing required option.
# prints usage information

exit_failure_syntax()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-icon: $@" >&2
        echo "Try 'xdg-desktop-icon --help' for more information." >&2
    else
        echo "Use 'man xdg-desktop-icon' or 'xdg-desktop-icon --manual' for additional info."
    fi

    exit 1
}

#-------------------------------------------------------------
# Exit script on missing file specified on command line

exit_failure_file_missing()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-icon: $@" >&2
    fi

    exit 2
}

#-------------------------------------------------------------
# Exit script on failure to locate necessary tool applications

exit_failure_operation_impossible()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-icon: $@" >&2
    fi

    exit 3
}

#-------------------------------------------------------------
# Exit script on failure returned by a tool application

exit_failure_operation_failed()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-icon: $@" >&2
    fi

    exit 4
}

#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file

exit_failure_file_permission_read()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-icon: $@" >&2
    fi

    exit 5
}

#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file

exit_failure_file_permission_write()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-icon: $@" >&2
    fi

    exit 6
}

check_input_file()
{
    if [ ! -e "$1" ]; then
        exit_failure_file_missing "file '$1' does not exist"
    fi
    if [ ! -r "$1" ]; then
        exit_failure_file_permission_read "no permission to read file '$1'"
    fi
}

check_vendor_prefix()
{
    file_label="$2"
    [ -n "$file_label" ] || file_label="filename"
    file=`basename "$1"`
    case "$file" in
       [a-zA-Z]*-*)
         return
         ;;
    esac

    echo "xdg-desktop-icon: $file_label '$file' does not have a proper vendor prefix" >&2
    echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2
    echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2
    echo "Use --novendor to override or 'xdg-desktop-icon --manual' for additional info." >&2
    exit 1
}

check_output_file()
{
    # if the file exists, check if it is writeable
    # if it does not exists, check if we are allowed to write on the directory
    if [ -e "$1" ]; then
        if [ ! -w "$1" ]; then
            exit_failure_file_permission_write "no permission to write to file '$1'"
        fi
    else
        DIR=`dirname "$1"`
        if [ ! -w "$DIR" -o ! -x "$DIR" ]; then
            exit_failure_file_permission_write "no permission to create file '$1'"
        fi
    fi
}

#----------------------------------------
# Checks for shared commands, e.g. --help

check_common_commands()
{
    while [ $# -gt 0 ] ; do
        parm="$1"
        shift

        case "$parm" in
            --version)
            echo "xdg-desktop-icon 1.0.1"
            exit_success
            ;;
        esac
    done
}

check_common_commands "$@"

[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL;
if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then
    # Be silent
    xdg_redirect_output=" > /dev/null 2> /dev/null"
else
    # All output to stderr
    xdg_redirect_output=" >&2"
fi

#--------------------------------------
# Checks for known desktop environments
# set variable DE to the desktop environments name, lowercase

detectDE()
{
    if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde;
    elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
    elif xprop -root _DT_SAVE_MODE | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
    fi
}

#----------------------------------------------------------------------------
# kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4
# It also always returns 1 in KDE 3.4 and earlier
# Simply return 0 in such case

kfmclient_fix_exit_code()
{
    version=`kde-config --version 2>/dev/null | grep KDE`
    major=`echo $version | sed 's/KDE: \([0-9]\).*/\1/'`
    minor=`echo $version | sed 's/KDE: [0-9]*\.\([0-9]\).*/\1/'`
    release=`echo $version | sed 's/KDE: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'`
    test "$major" -gt 3 && return $1
    test "$minor" -gt 5 && return $1
    test "$release" -gt 4 && return $1
    return 0
}

[ x"$1" != x"" ] || exit_failure_syntax 

action=
desktop_file=

case $1 in
  install)
    action=install
    ;;

  uninstall)
    action=uninstall
    ;;

  *)
    exit_failure_syntax "unknown command '$1'"
    ;;
esac

shift

vendor=true
while [ $# -gt 0 ] ; do
    parm=$1
    shift

    case $parm in
      --novendor)
        vendor=false
        ;;

      -*)
        exit_failure_syntax "unexpected option '$parm'"
        ;;

      *)
        if [ -n "$desktop_file" ] ; then
            exit_failure_syntax "unexpected argument '$parm'"
        fi
        if [ "$action" = "install" ] ; then
            check_input_file "$parm"
        fi
        desktop_file=$parm
        ;;
    esac
done

# Shouldn't happen
if [ -z "$action" ] ; then
    exit_failure_syntax "command argument missing"
fi

if [ -z "$desktop_file" ] ; then
    exit_failure_syntax "FILE argument missing"
fi

filetype=
case $desktop_file in
  *.desktop)
     filetype=desktop
     if [ "$vendor" = "true" -a "$action" = "install" ] ; then
        check_vendor_prefix "$desktop_file"
     fi
     ;;
  *)
     filetype=other
     ;;
esac

my_umask=077
my_chmod=0755
# Is xdg-user-dirs present and enabled ?
if ( [ -e ${XDG_CONFIG_HOME:-~/.config}/user-dirs.conf ] && cat ${XDG_CONFIG_HOME:-~/.config}/user-dirs.conf || ( [ -e /etc/xdg/user-dirs.conf ] && cat /etc/xdg/user-dirs.conf ) ) | grep enabled=True > /dev/null; then
    DESKTOP=Desktop
    # Try to get global defaults
    [ -f /etc/xdg/user-dirs.defaults ] && . /etc/xdg/user-dirs.defaults
    # Try to get user-defined settings
    [ -f ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs ] && . ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs
    desktop_dir=${XDG_DESKTOP_DIR:-$HOME/$DESKTOP}
else
    desktop_dir="$HOME/Desktop"
fi
desktop_dir_kde=`kde-config --userpath desktop 2> /dev/null`
desktop_dir_kde4=`kde4-config --userpath desktop 2> /dev/null`
if gconftool-2 -g /apps/nautilus/preferences/desktop_is_home_dir 2> /dev/null | grep true > /dev/null; then
    desktop_dir_gnome="$HOME"
    # Don't create $HOME/Desktop if it doesn't exist
    [ -w "$desktop_dir" ] || desktop_dir=
fi
for x in "$desktop_dir_kde" "$desktop_dir_kde4" ; do
    if [ -n "$x" ]; then
        if [ ! -d "$x" ]; then
            save_umask=`umask`
            umask $my_umask
            mkdir -p "$x"
            umask $save_umask
        fi
        # Is the KDE desktop dir != $desktop_dir ?
        if [ x"`readlink -f "$desktop_dir"`" != x"`readlink -f "$x"`" ]; then
            # If so, don't create $desktop_dir if it doesn't exist
            [ -w "$desktop_dir" ] || desktop_dir=
        else
            if [ "$x" = "$desktop_dir_kde" ]; then
                desktop_dir_kde=
            fi
            if [ "$x" = "$desktop_dir_kde4" ]; then
                desktop_dir_kde4=
            fi
        fi
    fi
done

basefile=`basename "$desktop_file"`

DEBUG 1 "$action $desktop_file in $desktop_dir $desktop_dir_kde $desktop_dir_kde4 $desktop_dir_gnome"

case $action in
    install)
        save_umask=`umask`
        umask $my_umask

        for x in "$desktop_dir" "$desktop_dir_kde" "$desktop_dir_kde4" "$desktop_dir_gnome" ; do
            if [ -n "$x" ]; then
                mkdir -p "$x"
                eval 'cp "$desktop_file" "$x/$basefile"'$xdg_redirect_output
                chmod $my_chmod "$x/$basefile"
            fi
        done

        umask $save_umask
        ;;

    uninstall)
        for x in "$desktop_dir" "$desktop_dir_kde" "$desktop_dir_kde4" "$desktop_dir_gnome" ; do
            if [ -n "$x" ]; then
                rm -f "$x/$basefile"
            fi
        done

        ;;
esac

exit_success
Added lib/packages/xdg-utils/xdg-desktop-menu.


























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
#!/bin/sh
#---------------------------------------------
#   xdg-desktop-menu
#
#   Utility script to install menu items on a Linux desktop.
#   Refer to the usage() function below for usage.
#
#   Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
#   Copyright 2006, Jeremy White <jwhite@codeweavers.com>
#
#   LICENSE:
#
#   Permission is hereby granted, free of charge, to any person obtaining a
#   copy of this software and associated documentation files (the "Software"),
#   to deal in the Software without restriction, including without limitation
#   the rights to use, copy, modify, merge, publish, distribute, sublicense,
#   and/or sell copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following conditions:
#
#   The above copyright notice and this permission notice shall be included
#   in all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
#   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
#   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
#   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
#   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
#   OTHER DEALINGS IN THE SOFTWARE.
#
#---------------------------------------------

#@xdg-utils-common@

#----------------------------------------------------------------------------
#   Common utility functions included in all XDG wrapper scripts
#----------------------------------------------------------------------------

DEBUG()
{
  [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0;
  [ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0;
  shift
  echo "$@" >&2
}

#-------------------------------------------------------------
# Exit script on successfully completing the desired operation

exit_success()
{
    if [ $# -gt 0 ]; then
        echo "$@"
        echo
    fi

    exit 0
}


#-----------------------------------------
# Exit script on malformed arguments, not enough arguments
# or missing required option.
# prints usage information

exit_failure_syntax()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-menu: $@" >&2
        echo "Try 'xdg-desktop-menu --help' for more information." >&2
    else
        echo "Use 'man xdg-desktop-menu' or 'xdg-desktop-menu --manual' for additional info."
    fi

    exit 1
}

#-------------------------------------------------------------
# Exit script on missing file specified on command line

exit_failure_file_missing()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-menu: $@" >&2
    fi

    exit 2
}

#-------------------------------------------------------------
# Exit script on failure to locate necessary tool applications

exit_failure_operation_impossible()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-menu: $@" >&2
    fi

    exit 3
}

#-------------------------------------------------------------
# Exit script on failure returned by a tool application

exit_failure_operation_failed()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-menu: $@" >&2
    fi

    exit 4
}

#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file

exit_failure_file_permission_read()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-menu: $@" >&2
    fi

    exit 5
}

#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file

exit_failure_file_permission_write()
{
    if [ $# -gt 0 ]; then
        echo "xdg-desktop-menu: $@" >&2
    fi

    exit 6
}

check_input_file()
{
    if [ ! -e "$1" ]; then
        exit_failure_file_missing "file '$1' does not exist"
    fi
    if [ ! -r "$1" ]; then
        exit_failure_file_permission_read "no permission to read file '$1'"
    fi
}

check_vendor_prefix()
{
    file_label="$2"
    [ -n "$file_label" ] || file_label="filename"
    file=`basename "$1"`
    case "$file" in
       [a-zA-Z]*-*)
         return
         ;;
    esac

    echo "xdg-desktop-menu: $file_label '$file' does not have a proper vendor prefix" >&2
    echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2
    echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2
    echo "Use --novendor to override or 'xdg-desktop-menu --manual' for additional info." >&2
    exit 1
}

check_output_file()
{
    # if the file exists, check if it is writeable
    # if it does not exists, check if we are allowed to write on the directory
    if [ -e "$1" ]; then
        if [ ! -w "$1" ]; then
            exit_failure_file_permission_write "no permission to write to file '$1'"
        fi
    else
        DIR=`dirname "$1"`
        if [ ! -w "$DIR" -o ! -x "$DIR" ]; then
            exit_failure_file_permission_write "no permission to create file '$1'"
        fi
    fi
}

#----------------------------------------
# Checks for shared commands, e.g. --help

check_common_commands()
{
    while [ $# -gt 0 ] ; do
        parm="$1"
        shift

        case "$parm" in
            --version)
            echo "xdg-desktop-menu 1.0.1"
            exit_success
            ;;
        esac
    done
}

check_common_commands "$@"

[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL;
if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then
    # Be silent
    xdg_redirect_output=" > /dev/null 2> /dev/null"
else
    # All output to stderr
    xdg_redirect_output=" >&2"
fi

#--------------------------------------
# Checks for known desktop environments
# set variable DE to the desktop environments name, lowercase

detectDE()
{
    if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde;
    elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
    elif xprop -root _DT_SAVE_MODE | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
    fi
}

#----------------------------------------------------------------------------
# kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4
# It also always returns 1 in KDE 3.4 and earlier
# Simply return 0 in such case

kfmclient_fix_exit_code()
{
    version=`kde-config --version 2>/dev/null | grep KDE`
    major=`echo $version | sed 's/KDE: \([0-9]\).*/\1/'`
    minor=`echo $version | sed 's/KDE: [0-9]*\.\([0-9]\).*/\1/'`
    release=`echo $version | sed 's/KDE: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'`
    test "$major" -gt 3 && return $1
    test "$minor" -gt 5 && return $1
    test "$release" -gt 4 && return $1
    return 0
}

update_desktop_database()
{
#    echo Update desktop database: $mode
    if [ "$mode" = "system" ] ; then
        for x in `echo $PATH | sed 's/:/ /g'` /opt/gnome/bin; do
           if [ -x $x/update-desktop-database ] ; then
              DEBUG 1 "Running $x/update-desktop-database"
              eval '$x/update-desktop-database'$xdg_redirect_output
              return
           fi
        done
    fi
}

fixup_mandriva_categories()
{
    DEBUG 1 "fixup_mandriva_categories $1"
    awk '
BEGIN {
    xlat["AudioVideo"]="X-Mandrakelinux-Multimedia;X-MandrivaLinux-Multimedia"
    xlat["Development"]="X-Mandrakelinux-MoreApplications-Development;X-MandrivaLinux-MoreApplications-Development"
    xlat["Education"]="X-Mandrakelinux-MoreApplications;X-MandrivaLinux-MoreApplications-Education"
    xlat["Game"]="X-Mandrakelinux-MoreApplications;X-MandrivaLinux-MoreApplications-Games"
    xlat["Graphics"]="X-Mandrakelinux-Multimedia-Graphics"
    xlat["Network"]="X-Mandrakelinux-Internet;X-MandrivaLinux-Internet"
    xlat["Office"]="X-Mandrakelinux-Office;X-MandrivaLinux-Office"
    xlat["System"]="X-Mandrakelinux-System;X-MandrivaLinux-System"
    xlat["Utility"]="X-Mandrakelinux-Office-Accessories;X-MandrivaLinux-Office-Accessories"
}
{
    if (match($0,/Categories=/)) {
        split(substr($0,RSTART+11),categories,";")
        result=""
        for (n in categories)
        {
               if (categories[n] in xlat)
                 categories[n]=categories[n] ";" xlat[categories[n]]
               if (categories[n])
                 result=result categories[n] ";"
        }
        print "Categories=" result
    }
    else
    {
        print $0
    }
}' $1 > $1.new
    mv $1.new $1
}

# Make application $1/$2 the default for all the mimetypes it support,
# iff such mimetype didn't had a default application already.
# $1 Install dir for desktop file
# $2 base name of desktop file
make_lazy_default()
{
    local mimetypes
    local xdg_user_dir
    local xdg_default_dirs
    
    DEBUG 1 "make_lazy_default $1/$2"
    mimetypes=`awk '
{
    if (match($0,/MimeType=/)) {
        split(substr($0,RSTART+9),mimetypes,";")
        for (n in mimetypes)
        {
               if (mimetypes[n])
                 print mimetypes[n]
        }
    }
}' "$1/$2" 2> /dev/null`
    
    for MIME in $mimetypes ; do
        xdg_default_dirs="$XDG_DATA_DIRS"
        [ -n "$xdg_default_dirs" ] || xdg_default_dirs=/usr/local/share/:/usr/share/
        if [ x"$mode" = x"user" ] ; then
            xdg_user_dir="$XDG_DATA_HOME"
            [ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share"
            xdg_default_dirs="$xdg_user_dir:$xdg_default_dirs"
        fi
        local default_app
        for x in `echo "$xdg_default_dirs" | sed 's/:/ /g'`; do
            DEBUG 2 "Checking $x/applications/defaults.list"
            default_app=`grep "$MIME=" $x/applications/defaults.list 2> /dev/null | cut -d '=' -f 2`
            if [ -n "$default_app" ] ; then
                DEBUG 2 "Found default apps for $MIME: $default_app"
                default_app="$default_app;"
                break;
            fi
        done
        DEBUG 2 "Current default apps for $MIME: $default_app"
        if echo "$default_app" | grep "$2" > /dev/null 2> /dev/null; then
            # App already listed as default
            continue;
        fi
        default_file="$1/defaults.list"
        DEBUG 1 "Updating $default_file"
        grep -v "$MIME=" $default_file > ${default_file}.new 2> /dev/null
        if ! grep "[Default Applications]" ${default_file}.new > /dev/null; then
            echo "[Default Applications]" >> ${default_file}.new
        fi
        echo $MIME="$default_app$2" >> ${default_file}.new
        mv ${default_file}.new $default_file
    done
}

update_submenu()
{
    DEBUG 1 "update_submenu $1"
    menu_file="$1"

    xdg_dir_name=menus
    xdg_user_dir="$XDG_CONFIG_HOME"
    [ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.config"
    xdg_user_dir="$xdg_user_dir/$xdg_dir_name"

    xdg_system_dirs="$XDG_CONFIG_DIRS"
    [ -n "$xdg_system_dirs" ] || xdg_system_dirs=/etc/xdg
    xdg_global_dir=
    for x in `echo $xdg_system_dirs | sed 's/:/ /g'` ; do
        if [ -w $x/$xdg_dir_name ] ; then
            xdg_global_dir="$x/$xdg_dir_name"
            break
        fi
    done
    xdg_user_dir="$xdg_user_dir/applications-merged"
    xdg_global_dir="$xdg_global_dir/applications-merged"

    DEBUG 3 "Install locations for *.menu file:" 
    DEBUG 3 "xdg_user_dir: $xdg_user_dir"
    DEBUG 3 "xdg_global_dir: $xdg_global_dir"
    DEBUG 3 "kde_user_dir: $kde_user_dir"
    DEBUG 3 "kde_global_dir: $kde_global_dir"
    DEBUG 3 "gnome_user_dir: $gnome_user_dir"
    DEBUG 3 "gnome_global_dir: $gnome_global_dir"

    if [ x"$mode" = x"user" ] ; then
        xdg_dir="$xdg_user_dir"
        kde_dir="$kde_user_dir"
        gnome_dir="$gnome_user_dir"
        my_umask=077
        my_chmod=0600
    else
        xdg_dir="$xdg_global_dir"
        kde_dir="$kde_global_dir"
        gnome_dir="$gnome_global_dir"
        my_umask=022
        my_chmod=0644
        if [ -z "${xdg_dir}${kde_dir}${gnome_dir}" ] ; then
            exit_failure_operation_impossible "No writable system menu directory found."
        fi
    fi

    if [ -z "$menu_file" ] ; then
        # Work around for SUSE/gnome 2.12 to pick up new ~/.local/share/applications
        save_umask=`umask`
        umask $my_umask

        mkdir -p $xdg_dir
        touch $xdg_dir/xdg-desktop-menu-dummy.menu

        umask $save_umask
        return
    fi

    if [ $action = "install" -a -f "/etc/xdg/menus/gnome-applications.menu" ] ; then
        # Work around for Debian Gnome
        gnome_xdg_dir=`echo "$xdg_dir" | sed -e 's^/applications-merged^/gnome-applications-merged^'`
        if [ ! -e "$gnome_xdg_dir" ] ; then
            DEBUG 1 "Debian Workaround: Link '$xdg_dir' to '$gnome_xdg_dir'"
            mkdir -p `dirname "$gnome_xdg_dir"`
            eval 'ln -s "applications-merged" "$gnome_xdg_dir"'$xdg_redirect_output
        fi
    fi
    if [ $action = "install" -a -f "/etc/mandrake-release" ] ; then
        # Work around for Mandriva 2006
        mandrake_xdg_dir=`echo "$xdg_dir" | sed -e 's^/applications-merged^/applications-mdk-merged^'`
        if [ ! -e "$mandrake_xdg_dir" ] ; then
            DEBUG 1 "Mandriva Workaround: Link '$xdg_dir' to '$mandrake_xdg_dir'"
            mkdir -p `dirname "$mandrake_xdg_dir"`
            eval 'ln -s "applications-merged" "$mandrake_xdg_dir"'$xdg_redirect_output
        fi
    fi
    if [ $action = "install" -a x"$mode" = x"user" -a -d "/etc/xdg/menus/kde-applications-merged" ] ; then
        # Work around for Fedora Core 5 + patched KDE
        kde_xdg_dir=`echo "$xdg_dir" | sed -e 's^/applications-merged^/kde-applications-merged^'`
        if [ ! -e "$kde_xdg_dir" ] ; then
            DEBUG 1 "Fedora Workaround: Link '$xdg_dir' to '$kde_xdg_dir'"
            mkdir -p `dirname "$kde_xdg_dir"`
            eval 'ln -s "applications-merged" "$kde_xdg_dir"'$xdg_redirect_output
        fi
    fi        
    if [ $action = "install" -a x"$mode" = x"system" -a -d "/etc/xdg/menus/kde-applications-merged" -a ! -d "/etc/xdg/menus/applications-merged" ] ; then
        # Work around for Kubuntu 6.06
        kde_xdg_dir=`echo "$xdg_dir" | sed -e 's^/applications-merged^/kde-applications-merged^'`
        DEBUG 1 "Kubuntu Workaround: Link '$xdg_dir' to 'kde-applications-merged'"
        eval 'ln -s "kde-applications-merged" "$xdg_dir"'$xdg_redirect_output
    fi

    orig_menu_file=$xdg_dir/$menu_file

    DEBUG 1 "Updating $orig_menu_file ($action)"

    tmpfile=`mktemp /tmp/tmp.XXXXXXXXXX`
    orig_desktop_files=
    if [ -r "$orig_menu_file" ] ; then
        awk '
# List all files within <Filename> tags
BEGIN {
  RS="<"
}
/^Filename/ {
  if (match($0,/>/)) {
     print substr($0,RSTART+1)
  }
}' $orig_menu_file > $tmpfile
    fi

    orig_desktop_files=`cat $tmpfile`
    new_desktop_files=
    if [ $action = "install" ] ; then
        for desktop_file in $desktop_files; do
            basefile=`basename $desktop_file`
            if ! grep '^'$basefile'$' $tmpfile > /dev/null 2> /dev/null ; then
            	# Append
            	echo "$basefile" >> $tmpfile
            fi
        done
        new_desktop_files=`cat $tmpfile`
    fi
    if [ $action = "uninstall" ] ; then
        echo > $tmpfile
        for desktop_file in $desktop_files; do
            echo "$desktop_file" >> $tmpfile
        done
        # Files to uninstall are listed in $tmpfile
        # Existing files are in $orig_desktop_files
        for desktop_file in $orig_desktop_files; do
            if ! grep '^'$desktop_file'$' $tmpfile > /dev/null 2> /dev/null; then
                # Keep this file, it's not in the uninstall list
                new_desktop_files="$new_desktop_files $desktop_file"
            fi
        done
    fi
    rm -f "$tmpfile"
    
    DEBUG 3 "Files to list in $menu_file: $new_desktop_files"
    
    if [ -n "$new_desktop_files" ] ; then
        # Install/update
        tmpfile=`mktemp /tmp/tmp.XXXXXXXXXX`
        (
            echo '<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"'
            echo '    "http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd">'
            echo '<!-- Do not edit manually - generated and managed by xdg-desktop-menu -->'
            echo '<Menu>'
            echo '    <Name>Applications</Name>'

            for desktop_file in $directory_files; do
                basefile=`basename $desktop_file`
                basefilename=`echo "$basefile"|cut -d '.' -f 1`
                echo "<Menu>"
                echo "    <Name>$basefilename</Name>"
                echo "    <Directory>$basefile</Directory>"
            done

            echo "    <Include>"
            for desktop_file in $new_desktop_files; do
                echo "        <Filename>$desktop_file</Filename>"
            done
            echo "    </Include>"

            for desktop_file in $directory_files; do
                echo "</Menu>"
            done

            echo '</Menu>'                        
        ) > $tmpfile
        chmod $my_chmod $tmpfile
    
        save_umask=`umask`
        umask $my_umask

        mkdir -p $xdg_dir
        eval 'cp $tmpfile $xdg_dir/$menu_file'$xdg_redirect_output

        umask $save_umask
	rm -f "$tmpfile"
    else
        # Uninstall
        rm -f $xdg_dir/$menu_file
    fi
    
    # Uninstall .directory files only if no longer referenced
    if [ $action = "uninstall" ] ; then
        tmpfile=`mktemp /tmp/tmp.XXXXXXXXXX`
        for menu_file in $xdg_dir/*; do
            if grep 'generated and managed by xdg-desktop-menu' $menu_file > /dev/null 2> /dev/null; then
                awk '
# List all files within <Directory> tags
BEGIN {
  RS="<"
}
/^Directory/ {
  if (match($0,/>/)) {
     print substr($0,RSTART+1)
  }
}' $menu_file >> $tmpfile
            fi
        done 
        orig_directory_files="$directory_files"
        directory_files=
        for desktop_file in $orig_directory_files; do
            if ! grep '^'$desktop_file'$' $tmpfile > /dev/null 2> /dev/null; then
                # No longer in use, safe to delete
               directory_files="$directory_files $desktop_file"
            fi
        done
        rm -f "$tmpfile"
    fi
}


[ x"$1" != x"" ] || exit_failure_syntax

mode=
action=
update=yes
desktop_files=
directory_files=

case $1 in
  install)
    action=install
    ;;

  uninstall)
    action=uninstall
    ;;

  forceupdate)
    action=forceupdate
    ;;

  *)
    exit_failure_syntax "unknown command '$1'"
    ;;
esac

shift

vendor=true
while [ $# -gt 0 ] ; do
    parm="$1"
    shift

    case "$parm" in
      --noupdate)
        update=no
        ;;

      --mode)
        if [ -z "$1" ] ; then
            exit_failure_syntax "mode argument missing for --mode"
        fi
        case "$1" in
          user)
            mode="user"
            ;;

          system)
            mode="system"
            ;;
            
          *)
            exit_failure_syntax "unknown mode '$1'"
            ;;
        esac
        shift
        ;;

      --novendor)
        vendor=false
        ;;

      -*)
        exit_failure_syntax "unexpected option '$parm'"
        ;;

      *)
        if [ "$action" = "install" ] ; then
            check_input_file "$parm"
        fi
        case "$parm" in
           *.directory)
              if [ -n "$desktop_files" ] ; then
                  exit_failure_syntax "'$parm' must preceed any *.desktop file"
              fi
              directory_files="$directory_files $parm"
              ;;
           *.desktop)
              desktop_files="$desktop_files $parm"
              ;;
           *)
              exit_failure_syntax "file to $action must be a *.directory or *.desktop file"
              ;;
        esac
        ;;
    esac
done

# Shouldn't happen
if [ -z "$action" ] ; then
    exit_failure_syntax "command argument missing"
fi

if [ -n "$XDG_UTILS_INSTALL_MODE" ] ; then
    if [ "$XDG_UTILS_INSTALL_MODE" = "system" ] ; then
        mode="system"
    elif [ "$XDG_UTILS_INSTALL_MODE" = "user" ] ; then
        mode="user"
    fi
fi

if [ -z "$mode" ] ; then
    if [ `whoami` = "root" ] ; then
       mode="system"
    else
       mode="user"
    fi
fi

if [ x"$action" = x"forceupdate" ] ; then
    update_desktop_database
    exit_success
fi

if [ -z "$desktop_files" ] ; then
    exit_failure_syntax "desktop-file argument missing"
fi

menu_name=
for desktop_file in $directory_files; do
    if [ "$vendor" =  "true" -a "$action" = "install" ] ; then
        check_vendor_prefix "$desktop_file"
    fi

    basefilename=`basename "$desktop_file"|cut -d '.' -f 1`
    if [ -z "$menu_name" ] ; then
        menu_name="$basefilename"
    else
        menu_name="$menu_name-$basefilename"
    fi
done

if [ -n "$menu_name" ] ; then
    if [ x"$mode" = x"user" ] ; then
        update_submenu "user-$menu_name.menu"
    else
        update_submenu "$menu_name.menu"
    fi
else
    # Work around for SUSE/gnome 2.12 to pick up new ~/.local/share/applications
    if [ x"$mode" = x"user" ] ; then
        update_submenu
    fi
fi

# Install *.directory files

xdg_dir_name=desktop-directories

xdg_user_dir="$XDG_DATA_HOME"
[ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share"
xdg_user_dir="$xdg_user_dir/$xdg_dir_name"

xdg_system_dirs="$XDG_DATA_DIRS"
[ -n "$xdg_system_dirs" ] || xdg_system_dirs=/usr/local/share/:/usr/share/
xdg_global_dir=
for x in `echo $xdg_system_dirs | sed 's/:/ /g'` ; do
    if [ -w $x/$xdg_dir_name ] ; then
        xdg_global_dir="$x/$xdg_dir_name"
        break
    fi
done

DEBUG 3 "Install locations for *.directory files:" 
DEBUG 3 "xdg_user_dir: $xdg_user_dir"
DEBUG 3 "xdg_global_dir: $xdg_global_dir"
DEBUG 3 "kde_user_dir: $kde_user_dir"
DEBUG 3 "kde_global_dir: $kde_global_dir"
DEBUG 3 "gnome_user_dir: $gnome_user_dir"
DEBUG 3 "gnome_global_dir: $gnome_global_dir"

if [ x"$mode" = x"user" ] ; then
    xdg_dir="$xdg_user_dir"
    kde_dir="$kde_user_dir"
    gnome_dir="$gnome_user_dir"
    my_umask=077
else
    xdg_dir="$xdg_global_dir"
    kde_dir="$kde_global_dir"
    gnome_dir="$gnome_global_dir"
    my_umask=022
    if [ -z "${xdg_dir}${kde_dir}${gnome_dir}" ] ; then
        exit_failure_operation_impossible "No writable system menu directory found."
    fi
fi

for desktop_file in $directory_files; do
    basefile=`basename $desktop_file`

    DEBUG 1 "$action $desktop_file in $xdg_dir $kde_dir $gnome_dir"

    case $action in
        install)
            save_umask=`umask`
            umask $my_umask

            for x in $xdg_dir $kde_dir $gnome_dir ; do
                mkdir -p $x
                eval 'cp $desktop_file $x/$basefile'$xdg_redirect_output
            done

            umask $save_umask
            ;;

        uninstall)
            for x in $xdg_dir $kde_dir $gnome_dir ; do
                rm -f $x/$basefile
            done

            ;;
    esac
done

# Install *.desktop files
xdg_dir_name=applications

xdg_user_dir="$XDG_DATA_HOME"
[ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share"
xdg_user_dir="$xdg_user_dir/$xdg_dir_name"

xdg_system_dirs="$XDG_DATA_DIRS"
[ -n "$xdg_system_dirs" ] || xdg_system_dirs=/usr/local/share/:/usr/share/
xdg_global_dir=
for x in `echo $xdg_system_dirs | sed 's/:/ /g'` ; do
    if [ -w $x/$xdg_dir_name ] ; then
        xdg_global_dir="$x/$xdg_dir_name"
        break
    fi
done

kde_user_dir="$HOME/.kde/share/applnk"
kde_global_dir="/usr/share/applnk"
[ -w $kde_global_dir ] || kde_global_dir=

gnome_user_dir="$HOME/.gnome/apps"
gnome_global_dir="/usr/share/gnome/apps"
[ -w $gnome_global_dir ] || gnome_global_dir=

[ -f /etc/mandriva-release ] && need_mandriva_fix=true
[ -n "$need_mandriva_fix" ] && DEBUG 1 "Fixing up .desktop categories (Mandriva work around)"

DEBUG 3 "Install locations for *.desktop files:" 
DEBUG 3 "xdg_user_dir: $xdg_user_dir"
DEBUG 3 "xdg_global_dir: $xdg_global_dir"
DEBUG 3 "kde_user_dir: $kde_user_dir"
DEBUG 3 "kde_global_dir: $kde_global_dir"
DEBUG 3 "gnome_user_dir: $gnome_user_dir"
DEBUG 3 "gnome_global_dir: $gnome_global_dir"

if [ x"$mode" = x"user" ] ; then
    xdg_dir="$xdg_user_dir"
    kde_dir="$kde_user_dir"
    gnome_dir="$gnome_user_dir"
    my_umask=077
else
    xdg_dir="$xdg_global_dir"
    kde_dir="$kde_global_dir"
    gnome_dir="$gnome_global_dir"
    my_umask=022
    if [ -z "${xdg_dir}${kde_dir}${gnome_dir}" ] ; then
        exit_failure_operation_impossible "No writable system menu directory found."
    fi
fi

for desktop_file in $desktop_files; do
    if [ "$vendor" =  "true" -a "$action" = "install" ] ; then
        check_vendor_prefix "$desktop_file"
    fi

    basefile=`basename $desktop_file`

    DEBUG 1 "$action $desktop_file in $xdg_dir $kde_dir $gnome_dir"

    case $action in
        install)
            save_umask=`umask`
            umask $my_umask

            for x in $xdg_dir $kde_dir $gnome_dir ; do
                mkdir -p $x
                eval 'cp $desktop_file $x/$basefile'$xdg_redirect_output
            done

            if [ -n "$need_mandriva_fix" ] ; then
            	fixup_mandriva_categories $xdg_dir/$basefile
            fi

            if [ -f $kde_dir/$basefile ] ; then
                echo "OnlyShowIn=Old;" >> $kde_dir/$basefile
            fi

            if [ -f $gnome_dir/$basefile ] ; then
                echo "OnlyShowIn=Old;" >> $gnome_dir/$basefile
            fi
            
            make_lazy_default "$xdg_dir" "$basefile"

            umask $save_umask
            ;;

        uninstall)
            for x in $xdg_dir $kde_dir $gnome_dir ; do
                rm -f $x/$basefile
            done

            ;;
    esac
done

if [ x"$update" = x"yes" ] ; then
    update_desktop_database
fi

exit_success
Added lib/packages/xdg-utils/xdg-icon-resource.










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
#!/bin/sh
#---------------------------------------------
#   xdg-icon-resource
#
#   Utility script to install icons on a Linux desktop.
#
#   Refer to the usage() function below for usage.
#
#   Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
#   Copyright 2006, Jeremy White <jwhite@codeweavers.com>
#
#   LICENSE:
#
#   Permission is hereby granted, free of charge, to any person obtaining a
#   copy of this software and associated documentation files (the "Software"),
#   to deal in the Software without restriction, including without limitation
#   the rights to use, copy, modify, merge, publish, distribute, sublicense,
#   and/or sell copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following conditions:
#
#   The above copyright notice and this permission notice shall be included
#   in all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
#   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
#   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
#   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
#   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
#   OTHER DEALINGS IN THE SOFTWARE.
#
#---------------------------------------------

manualpage()
{
cat << _MANUALPAGE
Name

xdg-icon-resource - command line tool for (un)installing icon resources

Synopsis

xdg-icon-resource install [--noupdate] [--novendor] [--theme theme] [--context
context] [--mode mode] --size size icon-file [icon-name]

xdg-icon-resource uninstall [--noupdate] [--theme theme] [--context context]
[--mode mode] --size size icon-name

xdg-icon-resource forceupdate [--theme theme] [--mode mode]

xdg-icon-resource { --help | --manual | --version }

Description

The xdg-icon-resource program can be used to install icon resources into the
desktop icon system in order to illustrate menu entries, to depict desktop
icons or to graphically represent file types.

The desktop icon system identifies icons by name. Depending on the required
size, the choice of icon theme and the context in which the icon is used, the
desktop icon system locates an appropriate icon resource to depict an icon.
Icon resources can be XPM files, PNG files or SVG files.

The desktop icon system works according to the XDG Icon Theme Specification at
http://www.freedesktop.org/Standards/icon-theme-spec

Commands

install
    Installs the icon file indicated by icon-file to the desktop icon system
    under the name icon-name. Icon names do not have an extension. If icon-name
    is not provided the name is derived from icon-file. The icon file must have
    .png or .xpm as extension. If a corresponding .icon file exists in the same
    location as icon-file it will be installed as well.
uninstall
    Removes the icon indicated by icon-name from the desktop icon system. Note
    that icon names do not have an extension.
forceupdate
    Force an update of the desktop icon system. This is only useful if the last
    call to xdg-icon-resource included the --noupdate option.

Options

--noupdate
    Postpone updating the desktop icon system. If multiple icons are added in
    sequence this flag can be used to indicate that additional changes will
    follow and that it is not necassery to update the desktop icon system right
    away.
--novendor

    Normally, xdg-icon-resource checks to ensure that an icon file to be
    installed in the apps context has a proper vendor prefix. This option can
    be used to disable that check.

    A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated
    with a dash ("-"). Companies and organizations are encouraged to use a word
    or phrase, preferably the organizations name, for which they hold a
    trademark as their vendor prefix. The purpose of the vendor prefix is to
    prevent name conflicts.

--theme theme
    Installs or removes the icon file as part of theme. If no theme is
    specified the icons will be installed as part of the default hicolor theme.
    Applications may install icons under multiple themes but should at least
    install icons for the default hicolor theme.
--context context
    Specifies the context for the icon. Icons to be used in the application
    menu and as desktop icon should use apps as context which is the default
    context. Icons to be used as file icons should use mimetypes as context.
    Other common contexts are actions, devices, emblems, filesystems and stock.
--size size
    Specifies the size of the icon. All icons must be square. Common sizes for
    icons in the apps context are: 16, 22, 32, 48, 64 and 128. Common sizes for
    icons in the mimetypes context are: 16, 22, 32, 48, 64 and 128
--mode mode

    mode can be user or system. In user mode the file is (un)installed for the
    current user only. In system mode the file is (un)installed for all users
    on the system. Usually only root is allowed to install in system mode.

    The default is to use system mode when called by root and to use user mode
    when called by a non-root user.

--help
    Show command synopsis.
--manual
    Show this manualpage.
--version
    Show the xdg-utils version information.

Environment Variables

xdg-icon-resource honours the following environment variables:

XDG_UTILS_DEBUG_LEVEL
    Setting this environment variable to a non-zero numerical value makes
    xdg-icon-resource do more verbose reporting on stderr. Setting a higher
    value increases the verbosity.
XDG_UTILS_INSTALL_MODE
    This environment variable can be used by the user or administrator to
    override the installation mode. Valid values are user and system.

Exit Codes

An exit code of 0 indicates success while a non-zero exit code indicates
failure. The following failure codes can be returned:

1
    Error in command line syntax.
2
    One of the files passed on the command line did not exist.
3
    A required tool could not be found.
4
    The action failed.
5
    No permission to read one of the files passed on the command line.

See Also

xdg-desktop-icon(1), xdg-desktop-menu(1), xdg-mime(1)

Examples

To install an icon resource to depict a launcher for the application myfoobar,
the company ShinyThings Inc. can use:

xdg-icon-resource install --size 64 shinythings-myfoobar.png

To install an icon for a new application/x-foobar file type one can use:

xdg-icon-resource install --context mimetypes --size 48 ./mime-foobar-48.png application-x-foobar
xdg-icon-resource install --context mimetypes --size 64 ./mime-foobar-64.png application-x-foobar

This will install two icons with the name application-x-foobar but with
different sizes.

_MANUALPAGE
}

usage()
{
cat << _USAGE
xdg-icon-resource - command line tool for (un)installing icon resources

Synopsis

xdg-icon-resource install [--noupdate] [--novendor] [--theme theme] [--context
context] [--mode mode] --size size icon-file [icon-name]

xdg-icon-resource uninstall [--noupdate] [--theme theme] [--context context]
[--mode mode] --size size icon-name

xdg-icon-resource forceupdate [--theme theme] [--mode mode]

xdg-icon-resource { --help | --manual | --version }

_USAGE
}

#@xdg-utils-common@

#----------------------------------------------------------------------------
#   Common utility functions included in all XDG wrapper scripts
#----------------------------------------------------------------------------

DEBUG()
{
  [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0;
  [ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0;
  shift
  echo "$@" >&2
}

#-------------------------------------------------------------
# Exit script on successfully completing the desired operation

exit_success()
{
    if [ $# -gt 0 ]; then
        echo "$@"
        echo
    fi

    exit 0
}


#-----------------------------------------
# Exit script on malformed arguments, not enough arguments
# or missing required option.
# prints usage information

exit_failure_syntax()
{
    if [ $# -gt 0 ]; then
        echo "xdg-icon-resource: $@" >&2
        echo "Try 'xdg-icon-resource --help' for more information." >&2
    else
        usage
        echo "Use 'man xdg-icon-resource' or 'xdg-icon-resource --manual' for additional info."
    fi

    exit 1
}

#-------------------------------------------------------------
# Exit script on missing file specified on command line

exit_failure_file_missing()
{
    if [ $# -gt 0 ]; then
        echo "xdg-icon-resource: $@" >&2
    fi

    exit 2
}

#-------------------------------------------------------------
# Exit script on failure to locate necessary tool applications

exit_failure_operation_impossible()
{
    if [ $# -gt 0 ]; then
        echo "xdg-icon-resource: $@" >&2
    fi

    exit 3
}

#-------------------------------------------------------------
# Exit script on failure returned by a tool application

exit_failure_operation_failed()
{
    if [ $# -gt 0 ]; then
        echo "xdg-icon-resource: $@" >&2
    fi

    exit 4
}

#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file

exit_failure_file_permission_read()
{
    if [ $# -gt 0 ]; then
        echo "xdg-icon-resource: $@" >&2
    fi

    exit 5
}

#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file

exit_failure_file_permission_write()
{
    if [ $# -gt 0 ]; then
        echo "xdg-icon-resource: $@" >&2
    fi

    exit 6
}

check_input_file()
{
    if [ ! -e "$1" ]; then
        exit_failure_file_missing "file '$1' does not exist"
    fi
    if [ ! -r "$1" ]; then
        exit_failure_file_permission_read "no permission to read file '$1'"
    fi
}

check_vendor_prefix()
{
    file_label="$2"
    [ -n "$file_label" ] || file_label="filename"
    file=`basename "$1"`
    case "$file" in
       [a-zA-Z]*-*)
         return
         ;;
    esac

    echo "xdg-icon-resource: $file_label '$file' does not have a proper vendor prefix" >&2
    echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2
    echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2
    echo "Use --novendor to override or 'xdg-icon-resource --manual' for additional info." >&2
    exit 1
}

check_output_file()
{
    # if the file exists, check if it is writeable
    # if it does not exists, check if we are allowed to write on the directory
    if [ -e "$1" ]; then
        if [ ! -w "$1" ]; then
            exit_failure_file_permission_write "no permission to write to file '$1'"
        fi
    else
        DIR=`dirname "$1"`
        if [ ! -w "$DIR" -o ! -x "$DIR" ]; then
            exit_failure_file_permission_write "no permission to create file '$1'"
        fi
    fi
}

#----------------------------------------
# Checks for shared commands, e.g. --help

check_common_commands()
{
    while [ $# -gt 0 ] ; do
        parm="$1"
        shift

        case "$parm" in
            --help)
            usage
            echo "Use 'man xdg-icon-resource' or 'xdg-icon-resource --manual' for additional info."
            exit_success
            ;;

            --manual)
            manualpage
            exit_success
            ;;

            --version)
            echo "xdg-icon-resource 1.0.1"
            exit_success
            ;;
        esac
    done
}

check_common_commands "$@"

[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL;
if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then
    # Be silent
    xdg_redirect_output=" > /dev/null 2> /dev/null"
else
    # All output to stderr
    xdg_redirect_output=" >&2"
fi

#--------------------------------------
# Checks for known desktop environments
# set variable DE to the desktop environments name, lowercase

detectDE()
{
    if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde;
    elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
    elif xprop -root _DT_SAVE_MODE | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
    fi
}

#----------------------------------------------------------------------------
# kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4
# It also always returns 1 in KDE 3.4 and earlier
# Simply return 0 in such case

kfmclient_fix_exit_code()
{
    version=`kde-config --version 2>/dev/null | grep KDE`
    major=`echo $version | sed 's/KDE: \([0-9]\).*/\1/'`
    minor=`echo $version | sed 's/KDE: [0-9]*\.\([0-9]\).*/\1/'`
    release=`echo $version | sed 's/KDE: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'`
    test "$major" -gt 3 && return $1
    test "$minor" -gt 5 && return $1
    test "$release" -gt 4 && return $1
    return 0
}

# Set GTK_UPDATE_ICON_CACHE to gtk-update-icon-cache executable path or
# to "-" if not found.
GTK_UPDATE_ICON_CACHE=
find_gtk_update_icon_cache()
{
    [ -n "$GTK_UPDATE_ICON_CACHE" ] && return;
 
    GTK_UPDATE_ICON_CACHE="-"   
    for x in `echo "$PATH:/opt/gnome/bin" | sed 's/:/ /g'`; do
        DEBUG 3 "Checking $x for gtk-update-icon-cache"
        if [ -x "$x/gtk-update-icon-cache" ] ; then
            DEBUG 1 "Found $x/gtk-update-icon-cache"
            GTK_UPDATE_ICON_CACHE="$x/gtk-update-icon-cache"
            return
        fi
    done
}

# Start GNOME legacy workaround section
need_dot_icon_path()
{
  # GTK < 2.6 uses ~/.icons but not XDG_DATA_HOME/icons
  # The availability of gtk-update-icon-cache is used as indication
  # of whether the system is using GTK 2.6 or later
  find_gtk_update_icon_cache
  [ "$GTK_UPDATE_ICON_CACHE" != "-" ] && return 1; 
  return 0;
}

update_icon_database()
{
   # Touch me, I'm dirty
   touch "$1/.xdg-icon-resource-dummy"
   rm -f "$1/.xdg-icon-resource-dummy"

   # Don't create a cache if there wan't one already
   if [ -f "$1/icon-theme.cache" ] ; then
      find_gtk_update_icon_cache
      if [ "$GTK_UPDATE_ICON_CACHE" != "-" ] ; then 
         DEBUG 1 "Running $GTK_UPDATE_ICON_CACHE -f -t \"$1\""
         eval '$GTK_UPDATE_ICON_CACHE -f -t "$1"'$xdg_redirect_output
         return
      fi
   fi
}

[ x"$1" != x"" ] || exit_failure_syntax

mode=
action=
update=yes
size=
theme=hicolor
context=apps
icon_file=
icon_name=

case $1 in
  install)
    action=install
    ;;

  uninstall)
    action=uninstall
    ;;

  forceupdate)
    action=forceupdate
    ;;

  *)
    exit_failure_syntax "unknown command '$1'"
    ;;
esac

shift

vendor=true
while [ $# -gt 0 ] ; do
    parm="$1"
    shift

    case $parm in
      --noupdate)
        update=no
        ;;

      --mode)
        if [ -z "$1" ] ; then
            exit_failure_syntax "mode argument missing for --mode"
        fi
        case "$1" in
          user)
            mode="user"
            ;;

          system)
            mode="system"
            ;;
            
          *)
            exit_failure_syntax "unknown mode '$1'"
            ;;
        esac
        shift
        ;;

      --theme)
        if [ -z "$1" ] ; then
            exit_failure_syntax "theme argument missing for --theme"
        fi
        theme="$1"
        shift
        ;;

      --size)
        if [ -z "$1" ] ; then
            exit_failure_syntax "size argument missing for --size"
        fi
        if echo "$1" | grep '[^0-9]' > /dev/null 2> /dev/null; then
            exit_failure_syntax "size argument must be numeric"
        fi
        size="$1"
        shift
        ;;

      --context)
        if [ -z "$1" ] ; then
            exit_failure_syntax "context argument missing for --context"
        fi
        context="$1"
        shift
        ;;

      --novendor)
        vendor=false
        ;;

      -*)
        exit_failure_syntax "unexpected option '$parm'"
        ;;

      *)
        if [ -n "$icon_name" ] ; then
            exit_failure_syntax "unexpected argument '$parm'"
        elif [ -n "$icon_file" ] ; then
            icon_name="$parm"
        else
            if [ "$action" = "install" ] ; then
                check_input_file "$parm"
            fi
            icon_file="$parm"
        fi
        ;;
    esac
done

# Shouldn't happen
if [ -z "$action" ] ; then
    exit_failure_syntax "command argument missing"
fi

# Shouldn't happen
if [ -z "$context" ] ; then
    exit_failure_syntax "context argument missing"
fi

if [ -n "$XDG_UTILS_INSTALL_MODE" ] ; then
    if [ "$XDG_UTILS_INSTALL_MODE" = "system" ] ; then
        mode="system"
    elif [ "$XDG_UTILS_INSTALL_MODE" = "user" ] ; then
        mode="user"
    fi
fi

if [ -z "$mode" ] ; then
    if [ `whoami` = "root" ] ; then
       mode="system"
    else
       mode="user"
    fi
fi

xdg_dir_name="icons/$theme"

xdg_user_dir="$XDG_DATA_HOME"
[ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share"
xdg_user_prefix="$xdg_user_dir/icons"
xdg_user_dir="$xdg_user_dir/$xdg_dir_name"

xdg_global_dir=
xdg_global_prefix=
xdg_system_dirs="$XDG_DATA_DIRS"
[ -n "$xdg_system_dirs" ] || xdg_system_dirs="/usr/local/share/:/usr/share/"
for x in `echo "$xdg_system_dirs" | sed 's/:/ /g'`; do
   if [ -w $x/$xdg_dir_name ] ; then
      xdg_global_prefix="$x/icons"
      xdg_global_dir="$x/$xdg_dir_name"
      break
   fi
done
[ -w $xdg_global_dir ] || xdg_global_dir=

dot_icon_dir=
dot_base_dir=
if [ x"$mode" = x"user" ] ; then
    xdg_base_dir="$xdg_user_dir"
    #Gnome 2.8 supports ~/.icons but not XDG_DATA_HOME
    if need_dot_icon_path ; then
        dot_icon_dir="$HOME/.icons"
        dot_base_dir="$dot_icon_dir/$theme"
    fi
else
    xdg_base_dir="$xdg_global_dir"
    if [ -z "$xdg_base_dir" ] ; then
        exit_failure_operation_impossible "No writable system icon directory found."
    fi
fi

if [ x"$action" = x"forceupdate" ] ; then
    if [ -n "$icon_file" ] ; then
      exit_failure_syntax "unexpected argument '$icon_file'"
    fi
    update_icon_database $xdg_base_dir
    if [ -n "$dot_icon_dir" ] ; then
        if [ -d "$dot_icon_dir/" -a ! -L "$dot_icon_dir" ] ; then
            update_icon_database $dot_base_dir
        fi
    fi
    exit_success
fi

if [ -z "$icon_file" ] ; then
    if [ x"$action" = x"install" ] ; then
      exit_failure_syntax "icon-file argument missing"
    else
      exit_failure_syntax "icon-name argument missing"
    fi
fi

xdg_size_name=
extension=

if [ -z "$size" ] ; then
    exit_failure_syntax "the icon size must be specified with --size"
fi
xdg_size_name="${size}x${size}"

if [ x"$action" = x"install" ] ; then
    case $icon_file in
      *.xpm)
        extension="xpm"
        ;;
      *.png)
        extension="png"
        ;;
      *)
        exit_failure_syntax "icon file to install must be a *.png or *.xpm file"
        ;;
    esac
fi

if [ -n "$icon_name" ] ; then
    case $icon_name in
      *.png)
         exit_failure_syntax "icon name should not include an extension"
         ;;
      *.xpm)
         exit_failure_syntax "icon name should not include an extension"
         ;;
    esac
fi

# Start KDE legacy workaround section
need_kde_icon_path()
{
  local path
  path=`readlink -f "$1" 2> /dev/null` # Normalize path
  DEBUG 2 "need_kde_icon_path $path"
  if [ -z "$path" ] ; then
     DEBUG 2 "need_kde_icon_path RETURN 1 (not needed, no xdg icon dir)"
     return 1; # Not needed
  fi

  # if kde-config not found... return 0
  kde_icon_dirs=`kde-config --path icon 2> /dev/null |sed 's/:/ /g'`
  DEBUG 3 "kde_icon_dirs: $kde_icon_dirs"
  if [ -z "$kde_icon_dirs" ] ; then
     DEBUG 3 "no result from kde-config --path icon"
     DEBUG 2 "need_kde_icon_path RETURN 1 (not needed, no kde icon path)"
     return 1; # Not needed
  fi
  needed=0 # Needed
  for y in $kde_icon_dirs ; do
    x=`readlink -f "$y"` # Normalize path
    DEBUG 3 "Normalize $y --> $x"
    if [ -n "$x" ] ; then
      if [ "$x" = "$path" ] ; then
        needed=1 # Not needed
      fi
      if [ -w "$x" ] ; then
        kde_global_prefix="$x"
        # Take last writable dir
      fi
    fi
  done
  DEBUG 2 "kde_global_prefix: $kde_global_prefix"
  [ $needed -eq "1" ] && DEBUG 2 "need_kde_icon_path RETURN $needed (not needed)"
  [ $needed -eq "0" ] && DEBUG 2 "need_kde_icon_path RETURN $needed (needed)"
  return $needed
}

kde_dir=
if [ x"$mode" = x"user" ] ; then
    xdg_dir="$xdg_base_dir/$xdg_size_name/$context"
    #KDE 3.x doesn't support XDG_DATA_HOME for icons
    #Check if xdg_dir prefix is listed by kde-config --path icon
    #If not, install additional symlink to kdedir 
    if need_kde_icon_path "$xdg_user_prefix" ; then
        kde_user_dir="$HOME/.kde/share/icons/$theme"
        kde_dir="$kde_user_dir/$xdg_size_name/$context"
    fi
    #Gnome 2.8 supports ~/.icons but not XDG_DATA_HOME
    if [ -n "$dot_icon_dir" ] ; then
        if [ -L "$dot_icon_dir" ] ; then
            # Don't do anything
            dot_icon_dir=
        elif [ ! -d "$dot_icon_dir/" ] ; then
            # Symlink if it doesn't exist
            eval 'ln -s ".local/share/icons" "$dot_icon_dir"'$xdg_redirect_output
            dot_icon_dir=
        else
            dot_icon_dir="$dot_icon_dir/$theme/$xdg_size_name/$context"
        fi
    fi
    my_umask=077
else
    xdg_dir="$xdg_base_dir/$xdg_size_name/$context"
    #KDE 3.x doesn't support XDG_DATA_DIRS for icons
    #Check if xdg_dir prefix is listed by kde-config --path icon
    #If not, install additional symlink to kdedir 
    if need_kde_icon_path "$xdg_global_prefix" ; then
        kde_global_dir="$kde_global_prefix/$theme"
        kde_dir="$kde_global_dir/$xdg_size_name/$context"
    fi
    my_umask=022
fi
# End KDE legacy workaround section

# Start GNOME legacy workaround section
need_gnome_mime=
[ $context = "mimetypes" ] && need_gnome_mime=true 
# End GNOME legacy workaround section

[ -n "$icon_name" ] || icon_name=`basename $icon_file | sed 's/\.[a-z][a-z][a-z]$//'`

if [ "$vendor" = "true" -a "$action" = "install" -a "$context" = "apps" ] ; then
    check_vendor_prefix "$icon_name" "icon name"
fi

icon_icon_file=`echo "$icon_file" | sed 's/\.[a-z][a-z][a-z]$/.icon/'`
icon_icon_name="$icon_name.icon"

DEBUG 1 "$action icon in $xdg_dir"
[ $action = "install" -a -f $icon_icon_file ] && DEBUG 1 "install $icon_icon_name meta file in $xdg_dir"
[ -n "$kde_dir" ] && DEBUG 1 "$action symlink in $kde_dir (KDE 3.x support)"
[ -n "$need_gnome_mime" ] && DEBUG 1 "$action gnome-mime-$icon_name symlink (GNOME 2.x support)"
[  $action = "install" -a -n "$dot_icon_dir" ] && DEBUG 1 "$action ~/.icons symlink (GNOME 2.8 support)"

case $action in
    install)
        save_umask=`umask`
        umask $my_umask

        for icon_dir in $xdg_dir $dot_icon_dir; do
            mkdir -p $icon_dir
            eval 'cp "$icon_file" "$icon_dir/$icon_name.$extension"'$xdg_redirect_output
            if [ -f "$icon_icon_file" ] ; then
                eval 'cp "$icon_icon_file" "$icon_dir/$icon_icon_name"'$xdg_redirect_output
            fi
            if [ -n "$need_gnome_mime" ] ; then
                eval 'ln -s "$icon_name.$extension" "$icon_dir/gnome-mime-$icon_name.$extension"'$xdg_redirect_output
            fi
        done
        if [ -n "$kde_dir" ] ; then
            mkdir -p $kde_dir
            eval 'ln -s "$xdg_dir/$icon_name.$extension" "$kde_dir/$icon_name.$extension"'$xdg_redirect_output
        fi

        umask $save_umask
        ;;

    uninstall)
        for icon_dir in $xdg_dir $dot_icon_dir; do
            rm -f "$icon_dir/$icon_name.xpm" "$icon_dir/$icon_name.png"
            rm -f "$icon_dir/$icon_icon_name"
            if [ -n "$need_gnome_mime" ] ; then
                rm -f "$icon_dir/gnome-mime-$icon_name.xpm" 
                rm -f "$icon_dir/gnome-mime-$icon_name.png" 
            fi
        done
        if [ -n "$kde_dir" ] ; then
            rm -f "$kde_dir/$icon_name.xpm" "$kde_dir/$icon_name.png"
        fi

        ;;
esac

if [ x"$update" = x"yes" ] ; then
    update_icon_database "$xdg_base_dir"
    if [ -n "$dot_icon_dir" ] ; then
        if [ -d "$dot_icon_dir/" -a ! -L "$dot_icon_dir" ] ; then
            update_icon_database $dot_base_dir
        fi
    fi
fi

exit_success
Added lib/packages/xdg-utils/xdg-mime.




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
#!/bin/sh
#---------------------------------------------
#   xdg-mime
#
#   Utility script to manipulate MIME related information
#   on XDG compliant systems.
#
#   Refer to the usage() function below for usage.
#
#   Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
#   Copyright 2006, Jeremy White <jwhite@codeweavers.com>
#
#   LICENSE:
#
#   Permission is hereby granted, free of charge, to any person obtaining a
#   copy of this software and associated documentation files (the "Software"),
#   to deal in the Software without restriction, including without limitation
#   the rights to use, copy, modify, merge, publish, distribute, sublicense,
#   and/or sell copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following conditions:
#
#   The above copyright notice and this permission notice shall be included
#   in all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
#   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
#   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
#   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
#   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
#   OTHER DEALINGS IN THE SOFTWARE.
#
#---------------------------------------------

manualpage()
{
cat << _MANUALPAGE
Name

xdg-mime - command line tool for querying information about file type handling
and adding descriptions for new file types

Synopsis

xdg-mime query { filetype | default } ...

xdg-mime default application mimetype(s)

xdg-mime install [--mode mode] [--novendor] mimetypes-file

xdg-mime uninstall [--mode mode] mimetypes-file

xdg-mime { --help | --manual | --version }

Description

The xdg-mime program can be used to query information about file types and to
add descriptions for new file types.

Commands

query

    Returns information related to file types.

    The query option is for use inside a desktop session only. It is not
    recommended to use xdg-mime query as root.

    The following queries are supported:

    query filetype FILE: Returns the file type of FILE in the form of a MIME
    type.

    query default mimetype: Returns the default application that the desktop
    environment uses for opening files of type mimetype. The default
    application is identified by its *.desktop file.

default

    Ask the desktop environment to make application the default application for
    opening files of type mimetype. An application can be made the default for
    several file types by specifying multiple mimetypes.

    application is the desktop file id of the application and has the form
    vendor-name.desktop application must already be installed in the desktop
    menu before it can be made the default handler. The aplication's desktop
    file must list support for all the MIME types that it wishes to be the
    default handler for.

    Requests to make an application a default handler may be subject to system
    policy or approval by the end-user. xdg-mime query can be used to verify
    whether an application is the actual default handler for a specific file
    type.

    The default option is for use inside a desktop session only. It is not
    recommended to use xdg-mime default as root.

install
    Adds the file type descriptions provided in mimetypes-file to the desktop
    environment. mimetypes-file must be a XML file that follows the
    freedesktop.org Shared MIME-info Database specification and that has a
    mime-info element as its document root. For each new file type one or more
    icons with name major-minor must be installed with the xdg-icon-resource
    command in the mimetypes context. For example the application/
    vnd.oasis.opendocument.text filetype requires an icon by the name of
    application-vnd.oasis.opendocument.text to be installed.
uninstall
    Removes the file type descriptions provided in mimetypes-file and
    previously added with xdg-mime install from the desktop environment.
    mimetypes-file must be a XML file that follows the freedesktop.org Shared
    MIME-info Database specification and that has a mime-info element as its
    document root.

Options

--mode mode

    mode can be user or system. In user mode the file is (un)installed for the
    current user only. In system mode the file is (un)installed for all users
    on the system. Usually only root is allowed to install in system mode.

    The default is to use system mode when called by root and to use user mode
    when called by a non-root user.

--novendor

    Normally, xdg-mime checks to ensure that the mimetypes-file to be installed
    has a proper vendor prefix. This option can be used to disable that check.

    A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated
    with a dash ("-"). Companies and organizations are encouraged to use a word
    or phrase, preferably the organizations name, for which they hold a
    trademark as their vendor prefix. The purpose of the vendor prefix is to
    prevent name conflicts.

--help
    Show command synopsis.
--manual
    Show this manualpage.
--version
    Show the xdg-utils version information.

Environment Variables

xdg-mime honours the following environment variables:

XDG_UTILS_DEBUG_LEVEL
    Setting this environment variable to a non-zero numerical value makes
    xdg-mime do more verbose reporting on stderr. Setting a higher value
    increases the verbosity.
XDG_UTILS_INSTALL_MODE
    This environment variable can be used by the user or administrator to
    override the installation mode. Valid values are user and system.

Exit Codes

An exit code of 0 indicates success while a non-zero exit code indicates
failure. The following failure codes can be returned:

1
    Error in command line syntax.
2
    One of the files passed on the command line did not exist.
3
    A required tool could not be found.
4
    The action failed.
5
    No permission to read one of the files passed on the command line.

See Also

xdg-icon-resource(1), xdg-desktop-menu(1)

Examples

xdg-mime query filetype /tmp/foobar.png

Prints the MIME type of the file /tmp/foobar.png, in this case image/png

xdg-mime query default image/png

Prints the .desktop filename of the application which is registered to open PNG
files.

xdg-mime install shinythings-shiny.xml

Adds a file type description for "shiny"-files. "shinythings-" is used as the
vendor prefix. The file type description could look as folows.

shinythings-shiny.xml:

<?xml version="1.0"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
  <mime-type type="text/x-shiny">
    <comment>Shiny new file type</comment>
    <glob pattern="*.shiny"/>
    <glob pattern="*.shi"/>
  </mime-type>
</mime-info>

An icon for this new file type must also be installed, for example with:

xdg-icon-resource install --context mimetypes --size 64 shiny-file-icon.png text-x-shiny

_MANUALPAGE
}

usage()
{
cat << _USAGE
xdg-mime - command line tool for querying information about file type handling
and adding descriptions for new file types

Synopsis

xdg-mime query { filetype | default } ...

xdg-mime default application mimetype(s)

xdg-mime install [--mode mode] [--novendor] mimetypes-file

xdg-mime uninstall [--mode mode] mimetypes-file

xdg-mime { --help | --manual | --version }

_USAGE
}

#@xdg-utils-common@

#----------------------------------------------------------------------------
#   Common utility functions included in all XDG wrapper scripts
#----------------------------------------------------------------------------

DEBUG()
{
  [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0;
  [ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0;
  shift
  echo "$@" >&2
}

#-------------------------------------------------------------
# Exit script on successfully completing the desired operation

exit_success()
{
    if [ $# -gt 0 ]; then
        echo "$@"
        echo
    fi

    exit 0
}


#-----------------------------------------
# Exit script on malformed arguments, not enough arguments
# or missing required option.
# prints usage information

exit_failure_syntax()
{
    if [ $# -gt 0 ]; then
        echo "xdg-mime: $@" >&2
        echo "Try 'xdg-mime --help' for more information." >&2
    else
        usage
        echo "Use 'man xdg-mime' or 'xdg-mime --manual' for additional info."
    fi

    exit 1
}

#-------------------------------------------------------------
# Exit script on missing file specified on command line

exit_failure_file_missing()
{
    if [ $# -gt 0 ]; then
        echo "xdg-mime: $@" >&2
    fi

    exit 2
}

#-------------------------------------------------------------
# Exit script on failure to locate necessary tool applications

exit_failure_operation_impossible()
{
    if [ $# -gt 0 ]; then
        echo "xdg-mime: $@" >&2
    fi

    exit 3
}

#-------------------------------------------------------------
# Exit script on failure returned by a tool application

exit_failure_operation_failed()
{
    if [ $# -gt 0 ]; then
        echo "xdg-mime: $@" >&2
    fi

    exit 4
}

#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file

exit_failure_file_permission_read()
{
    if [ $# -gt 0 ]; then
        echo "xdg-mime: $@" >&2
    fi

    exit 5
}

#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file

exit_failure_file_permission_write()
{
    if [ $# -gt 0 ]; then
        echo "xdg-mime: $@" >&2
    fi

    exit 6
}

check_input_file()
{
    if [ ! -e "$1" ]; then
        exit_failure_file_missing "file '$1' does not exist"
    fi
    if [ ! -r "$1" ]; then
        exit_failure_file_permission_read "no permission to read file '$1'"
    fi
}

check_vendor_prefix()
{
    file_label="$2"
    [ -n "$file_label" ] || file_label="filename"
    file=`basename "$1"`
    case "$file" in
       [a-zA-Z]*-*)
         return
         ;;
    esac

    echo "xdg-mime: $file_label '$file' does not have a proper vendor prefix" >&2
    echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2
    echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2
    echo "Use --novendor to override or 'xdg-mime --manual' for additional info." >&2
    exit 1
}

check_output_file()
{
    # if the file exists, check if it is writeable
    # if it does not exists, check if we are allowed to write on the directory
    if [ -e "$1" ]; then
        if [ ! -w "$1" ]; then
            exit_failure_file_permission_write "no permission to write to file '$1'"
        fi
    else
        DIR=`dirname "$1"`
        if [ ! -w "$DIR" -o ! -x "$DIR" ]; then
            exit_failure_file_permission_write "no permission to create file '$1'"
        fi
    fi
}

#----------------------------------------
# Checks for shared commands, e.g. --help

check_common_commands()
{
    while [ $# -gt 0 ] ; do
        parm="$1"
        shift

        case "$parm" in
            --help)
            usage
            echo "Use 'man xdg-mime' or 'xdg-mime --manual' for additional info."
            exit_success
            ;;

            --manual)
            manualpage
            exit_success
            ;;

            --version)
            echo "xdg-mime 1.0.1"
            exit_success
            ;;
        esac
    done
}

check_common_commands "$@"

[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL;
if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then
    # Be silent
    xdg_redirect_output=" > /dev/null 2> /dev/null"
else
    # All output to stderr
    xdg_redirect_output=" >&2"
fi

#--------------------------------------
# Checks for known desktop environments
# set variable DE to the desktop environments name, lowercase

detectDE()
{
    if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde;
    elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
    elif xprop -root _DT_SAVE_MODE | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
    fi
}

#----------------------------------------------------------------------------
# kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4
# It also always returns 1 in KDE 3.4 and earlier
# Simply return 0 in such case

kfmclient_fix_exit_code()
{
    version=`kde-config --version 2>/dev/null | grep KDE`
    major=`echo $version | sed 's/KDE: \([0-9]\).*/\1/'`
    minor=`echo $version | sed 's/KDE: [0-9]*\.\([0-9]\).*/\1/'`
    release=`echo $version | sed 's/KDE: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'`
    test "$major" -gt 3 && return $1
    test "$minor" -gt 5 && return $1
    test "$release" -gt 4 && return $1
    return 0
}

update_mime_database()
{
   if [ x"$mode" = x"user" -a -n "$DISPLAY" ] ; then
      detectDE
      if [ x"$DE" = x"kde" ] ; then
         DEBUG 1 "Running kbuildsycoca"
         eval 'kbuildsycoca'$xdg_redirect_output
      fi
   fi
   for x in `echo "$PATH:/opt/gnome/bin" | sed 's/:/ /g'`; do
      if [ -x $x/update-mime-database ] ; then
         DEBUG 1 "Running $x/update-mime-database $1"
         eval '$x/update-mime-database $1'$xdg_redirect_output
         return
      fi
   done
}

info_kde()
{
    DEBUG 1 "Running kfile \"$1\""
    kfile "$1" 2> /dev/null | head -n 1 | cut -d "(" -f 2 | cut -d ")" -f 1

    exit_success
}

info_gnome()
{
    file=`readlink -f "$1"` # Normalize path
    DEBUG 1 "Running gnomevfs-info \"$file\""
    gnomevfs-info "$file" 2> /dev/null | grep MIME | cut -d ":" -f 2 | sed s/"^ "//

    exit_success
}

info_generic()
{
    DEBUG 1 "Running /usr/bin/file -i \"$1\"" 
    /usr/bin/file -i "$1" 2> /dev/null | cut -d ":" -f 2 | sed s/"^ "//

    exit_success
}

make_default_kde()
{
    # $1 is vendor-name.desktop
    # $2 is mime/type 
    # Add to $KDE_HOME/share/config/profilerc:
    # [$2 - 1]
    # Application=$1
    #
    # Remove all [$2 - *] sections, or even better,
    # renumber [$2 - *] sections and remove duplicate
    
    default_file="$HOME/.kde/share/config/profilerc"
    DEBUG 2 "make_default_kde $1 $2"
    DEBUG 1 "Updating $default_file"
    mkdir -p "$HOME/.kde/share/config"
    [ -f $default_file ] || touch $default_file
    awk -v application="$1" -v mimetype="$2" '
    BEGIN {
        header_start="[" mimetype " - "
        supress=0
    }
    {  
        if (index($0, header_start) == 1 )
            supress=1
        else
            if (/^\[/) { supress=0 }

        if (!supress) {
            print $0
        }
    }
    END {
        print "" 
        print "[" mimetype " - 1]"
        print "Application=" application
        print "AllowAsDefault=true"
        print "GenericServiceType=Application"
        print "Preference=1"
        print "ServiceType=" mimetype
    }
' $default_file > ${default_file}.new && mv ${default_file}.new $default_file
}

make_default_generic()
{
    # $1 is vendor-name.desktop
    # $2 is mime/type 
    # Add $2=$1 to XDG_DATA_HOME/applications/defaults.list
    xdg_user_dir="$XDG_DATA_HOME"
    [ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share"
    default_file="$xdg_user_dir/applications/defaults.list"
    DEBUG 2 "make_default_generic $1 $2"
    DEBUG 1 "Updating $default_file"
    grep -v "$2=" $default_file > ${default_file}.new 2> /dev/null
    if ! grep "[Default Applications]" ${default_file}.new > /dev/null; then
       echo "[Default Applications]" >> ${default_file}.new
    fi
    echo $2=$1 >> ${default_file}.new
    mv ${default_file}.new $default_file
}

defapp_generic()
{
    MIME="$1"
    xdg_user_dir="$XDG_DATA_HOME"
    [ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share"
    xdg_user_dir="$xdg_user_dir/$xdg_dir_name"
    xdg_system_dirs="$XDG_DATA_DIRS"
    [ -n "$xdg_system_dirs" ] || xdg_system_dirs=/usr/local/share/:/usr/share/

    for x in `echo "$xdg_user_dir:$xdg_system_dirs" | sed 's/:/ /g'`; do
       DEBUG 2 "Checking $x/applications/defaults.list"
       trader_result=`grep "$MIME=" $x/applications/defaults.list 2> /dev/null | cut -d '=' -f 2 | cut -d ';' -f 1`
       if [ -n "$trader_result" ] ; then
          echo $trader_result
          exit_success
       fi
    done
    exit_success
}

defapp_kde()
{
    MIME="$1"
    ktradertest=`which ktradertest 2> /dev/null`
    if [ -n "$ktradertest" ] ; then
        DEBUG 1 "Running ktradertest \"$MIME\" Application"
        trader_result=`ktradertest "$MIME" Application 2>/dev/null | grep DesktopEntryPath \
            | head -n 1 | cut -d ':' -f 2 | cut -d \' -f 2`
        if [ -n "$trader_result" ] ; then
            basename "$trader_result"
            exit_success
        else
            exit_failure_operation_failed
        fi
    else
        defapp_generic "$1"
    fi
}

[ x"$1" != x"" ] || exit_failure_syntax

mode=
action=
filename=
mimetype=

case $1 in
  install)
    action=install
    ;;

  uninstall)
    action=uninstall
    ;;

  query)
    shift

    if [ -z "$1" ] ; then 
        exit_failure_syntax "query type argument missing"
    fi
    
    case $1 in
      filetype)
        action=info

        filename="$2"
        if [ -z "$filename" ] ; then 
            exit_failure_syntax "FILE argument missing"
        fi
        case $filename in
          -*)
            exit_failure_syntax "unexpected option '$filename'"
            ;;
        esac
        check_input_file "$filename"
        ;;

      default)
        action=defapp
        mimetype="$2"
        if [ -z "$mimetype" ] ; then 
            exit_failure_syntax "mimetype argument missing"
        fi
        case $mimetype in
          -*)
            exit_failure_syntax "unexpected option '$mimetype'"
            ;;

          */*)
            # Ok
            ;;

          *)
            exit_failure_syntax "mimetype '$mimetype' is not in the form 'minor/major'"
            ;;
        esac
        ;;

      *)
      exit_failure_syntax "unknown query type '$1'"
      ;;
    esac
    ;;

  default)
    action=makedefault
    shift

    if [ -z "$1" ] ; then 
        exit_failure_syntax "application argument missing"
    fi
    case $1 in
      -*)
        exit_failure_syntax "unexpected option '$1'"
        ;;

      *.desktop)
        filename="$1"
        ;;

      *)
        exit_failure_syntax "malformed argument '$1', expected *.desktop"
        ;;
    esac
    ;;

  *)
  exit_failure_syntax "unknown command '$1'"
  ;;
esac

shift


if [ "$action" = "makedefault" ]; then
    if [ -z "$1" ] ; then 
        exit_failure_syntax "mimetype argument missing"
    fi

    while [ $# -gt 0 ] ; do
        case $1 in
          -*)
            exit_failure_syntax "unexpected option '$1'"
            ;;
        esac
        mimetype="$1"
        shift
        
        make_default_kde "$filename" "$mimetype"
        make_default_generic "$filename" "$mimetype"
    done
    exit_success
fi

if [ "$action" = "info" ]; then
    detectDE

    if [ x"$DE" = x"" ]; then
        if [ -x /usr/bin/file ]; then
            DE=generic
        fi
    fi

    case "$DE" in
        kde)
        info_kde "$filename"
        ;;

        gnome)
        info_gnome "$filename"
        ;;

        generic)
        info_generic "$filename"
        ;;
    esac
    exit_failure_operation_impossible "no method available for quering MIME type of '$filename'"
fi

if [ "$action" = "defapp" ]; then
    detectDE

    case "$DE" in
        kde)
        defapp_kde "$mimetype"
        ;;

        *)
        defapp_generic "$mimetype"
        ;;
    esac
    exit_failure_operation_impossible "no method available for quering default application for '$mimetype'"
fi

vendor=true
while [ $# -gt 0 ] ; do
    parm="$1"
    shift

    case $parm in
      --mode)
        if [ -z "$1" ] ; then
            exit_failure_syntax "mode argument missing for --mode"
        fi
        case "$1" in
          user)
            mode="user"
            ;;

          system)
            mode="system"
            ;;
            
          *)
            exit_failure_syntax "unknown mode '$1'"
            ;;
        esac
        shift
        ;;

      --novendor)
        vendor=false
        ;;

      -*)
        exit_failure_syntax "unexpected option '$parm'"
        ;;

      *)
        if [ -n "$filename" ] ; then
            exit_failure_syntax "unexpected argument '$parm'"
        fi

        filename="$parm"
        check_input_file "$filename"
        ;;
    esac
done

if [ -z "$action" ] ; then
    exit_failure_syntax "command argument missing"
fi

if [ -n "$XDG_UTILS_INSTALL_MODE" ] ; then
    if [ "$XDG_UTILS_INSTALL_MODE" = "system" ] ; then
        mode="system"
    elif [ "$XDG_UTILS_INSTALL_MODE" = "user" ] ; then
        mode="user"
    fi
fi

if [ -z "$mode" ] ; then
    if [ `whoami` = "root" ] ; then
        mode="system"
    else
        mode="user"
    fi
fi

if [ -z "$filename" ] ; then
    exit_failure_syntax "mimetypes-file argument missing"
fi

if [ "$vendor" =  "true" -a "$action" = "install" ] ; then
    check_vendor_prefix "$filename"
fi

xdg_base_dir=
xdg_dir_name=mime/packages/

xdg_user_dir="$XDG_DATA_HOME"
[ -n "$xdg_user_dir" ] || xdg_user_dir="$HOME/.local/share"
[ x"$mode" = x"user" ] && xdg_base_dir="$xdg_user_dir/mime"
xdg_user_dir="$xdg_user_dir/$xdg_dir_name"

xdg_system_dirs="$XDG_DATA_DIRS"
[ -n "$xdg_system_dirs" ] || xdg_system_dirs=/usr/local/share/:/usr/share/
for x in `echo $xdg_system_dirs | sed 's/:/ /g'`; do
    if [ -w $x/$xdg_dir_name ] ; then
        [ x"$mode" = x"system" ] && xdg_base_dir="$x/mime"
        xdg_global_dir="$x/$xdg_dir_name"
        break
    fi
done
[ -w $xdg_global_dir ] || xdg_global_dir=
DEBUG 3 "xdg_user_dir: $xdg_user_dir"
DEBUG 3 "xdg_global_dir: $xdg_global_dir"

# Find KDE3 mimelnk directory
kde_user_dir=
kde_global_dir=
kde_global_dirs=`kde-config --path mime 2> /dev/null`
DEBUG 3 "kde_global_dirs: $kde_global_dirs"
first=
for x in `echo $kde_global_dirs | sed 's/:/ /g'` ; do
    if [ -z "$first" ] ; then
        first=false
        kde_user_dir="$x"
    elif [ -w $x ] ; then
        kde_global_dir="$x"
    fi
done
DEBUG 3 "kde_user_dir: $kde_user_dir"
DEBUG 3 "kde_global_dir: $kde_global_dir"

# TODO: Gnome legacy support
# See http://forums.fedoraforum.org/showthread.php?t=26875
gnome_user_dir="$HOME/.gnome/apps"
gnome_global_dir=/usr/share/gnome/apps
[ -w $gnome_global_dir ] || gnome_global_dir=
DEBUG 3 "gnome_user_dir: $gnome_user_dir"
DEBUG 3 "gnome_global_dir: $gnome_global_dir"

if [ x"$mode" = x"user" ] ; then
    xdg_dir="$xdg_user_dir"
    kde_dir="$kde_user_dir"
    gnome_dir="$gnome_user_dir"
    my_umask=077
else
    xdg_dir="$xdg_global_dir"
    kde_dir="$kde_global_dir"
    gnome_dir="$gnome_global_dir"
    my_umask=022
    if [ -z "${xdg_dir}${kde_dir}${gnome_dir}" ] ; then
        exit_failure_operation_impossible "No writable system mimetype directory found."
    fi
fi

# echo "[xdg|$xdg_user_dir|$xdg_global_dir]"
# echo "[kde|$kde_user_dir|$kde_global_dir]"
# echo "[gnome|$gnome_user_dir|$gnome_global_dir]"
# echo "[using|$xdg_dir|$kde_dir|$gnome_dir]"

basefile=`basename "$filename"`
#[ -z $vendor ] || basefile="$vendor-$basefile"

mimetypes=
if [ -n "$kde_dir" ] ; then
    DEBUG 2 "KDE3 mimelnk directory found, extracting mimetypes from XML file"

    mimetypes=`awk < "$filename" '
# Strip XML comments
BEGIN {
 supress=0
}
{
 do 
    if (supress) {
       if (match($0,/-->/)) {
           $0=substr($0,RSTART+RLENGTH)
           supress=0
       }
       else {
           break
       }
    }
    else {
       if (match($0,/<!--/)) {
           if (RSTART>1) print substr($0,0,RSTART)
           $0=substr($0,RSTART+RLENGTH)
           supress=1
       }
       else {
           if ($0) print $0
           break
       }
    }
 while(1)
}
' | awk '
# List MIME types listed in <mime-type> tags
BEGIN {
  RS="<"
}
/^mime-info/, /^\/mime-info/ {
  if (match($0,/^mime-type/)) {
    if (match($0,/type="[^"]*/) || match($0,/type='"'"'[^'"'"']*/)) {
      print substr($0,RSTART+6,RLENGTH-6)
    }
  }
}'`
fi  

DEBUG 1 "$action mimetype in $xdg_dir"

case $action in
    install)
        save_umask=`umask`
        umask $my_umask

        for x in $xdg_dir ; do
            mkdir -p $x
            eval 'cp $filename $x/$basefile'$xdg_redirect_output
        done

        if [ -n "$mimetypes" ] ; then
            # No quotes around $mimetypes
            for x in $mimetypes ; do 
                DEBUG 1 "Installing $kde_dir/$x.desktop (KDE 3.x support)"
                mkdir -p `dirname $kde_dir/$x.desktop`
                awk < "$filename" '
# Strip XML comments
BEGIN {
 supress=0
}
{
 do 
    if (supress) {
       if (match($0,/-->/)) {
           $0=substr($0,RSTART+RLENGTH)
           supress=0
       }
       else {
           break
       }
    }
    else {
       if (match($0,/<!--/)) {
           if (RSTART>1) print substr($0,0,RSTART)
           $0=substr($0,RSTART+RLENGTH)
           supress=1
       }
       else {
           if ($0) print $0
           break
       }
    }
 while(1)
}
' | awk > $kde_dir/$x.desktop '
# Extract mimetype $x from the XML file $filename
# Note that bash requires us to escape a single quote as '"'"' 
BEGIN {
  the_type=ARGV[1]
  the_source=ARGV[2]
  ARGC=1
  RS="<"
  found=0
  glob_patterns=""
}
/^mime-info/, /^\/mime-info/ {
  if (match($0,/^mime-type/)) {
    if (match($0,/type="[^"]*/) || match($0,/type='"'"'[^'"'"']*/)) {
      if (substr($0,RSTART+6,RLENGTH-6) == the_type) {
        found=1
        print "[Desktop Entry]"
        print "# Installed by xdg-mime from " the_source
        print "Type=MimeType"
        print "MimeType=" the_type
        the_icon=the_type
        sub("/", "-", the_icon)
        print "Icon=" the_icon 
      }
    }
  }
  else if (found) {
    if (match($0,/^\/mime-type/)) {
      if (glob_patterns)
         print "Patterns=" glob_patterns
      exit 0
    }

    if (match($0,/^sub-class-of/)) {
      if (match($0,/type="[^"]*/) || match($0,/type='"'"'[^'"'"']*/)) {    
        print "X-KDE-IsAlso=" substr($0,RSTART+6,RLENGTH-6)
      }
      else {
        print "Error: '"'"'type'"'"' argument missing in " RS $0
        exit 1 
      }
    }
    if (match($0,/^glob/)) {
      if (match($0,/pattern="[^"]*/) || match($0,/pattern='"'"'[^'"'"']*/)) {    
        glob_patterns = glob_patterns substr($0,RSTART+9,RLENGTH-9) ";"
      }
      else {
        print "Error: '"'"'pattern'"'"' argument missing in " RS $0
        exit 1 
      }
    }
    if (match($0,/^comment/)) {
      if (match($0,/xml:lang="[^"]*/) || match($0,/xml:lang='"'"'[^'"'"']*/)) {    
        lang=substr($0,RSTART+10,RLENGTH-10)
      }
      else {
        lang=""
      }
      if (match($0,/>/)) {
        comment=substr($0,RSTART+1)
        sub("&lt;", "<", comment)
        sub("&gt;", ">", comment)
        sub("&amp;", "\\&", comment)
        if (lang)
           print "Comment[" lang "]=" comment
        else
           print "Comment=" comment
      }
    }
  }
}
END {
  if (!found) {
    print "Error: Mimetype '"'"'" the_type "'"'"' not found"
    exit 1
  }
}
' $x $basefile
                if [ "$?" = "1" ] ; then
                    grep -A 10 "^Error:" $kde_dir/$x.desktop >&2
                    rm $kde_dir/$x.desktop
                    exit 1  
                fi
            done
        fi

        umask $save_umask
        ;;

    uninstall)
        for x in $xdg_dir ; do
            rm -f $x/$basefile
        done

        # No quotes around $mimetypes
        for x in $mimetypes ; do 
            if grep '^# Installed by xdg-mime' $kde_dir/$x.desktop &>/dev/null ; then
                DEBUG 1 "Removing $kde_dir/$x.desktop (KDE 3.x support)"
                rm -f $kde_dir/$x.desktop
            fi
        done
        ;;
esac

update_mime_database $xdg_base_dir

exit_success

Added lib/packages/xdg-utils/xdg-open.




























































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
#!/bin/sh
#---------------------------------------------
#   xdg-open
#
#   Utility script to open a URL in the registered default application.
#
#   Refer to the usage() function below for usage.
#
#   Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
#   Copyright 2006, Jeremy White <jwhite@codeweavers.com>
#
#   LICENSE:
#
#   Permission is hereby granted, free of charge, to any person obtaining a
#   copy of this software and associated documentation files (the "Software"),
#   to deal in the Software without restriction, including without limitation
#   the rights to use, copy, modify, merge, publish, distribute, sublicense,
#   and/or sell copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following conditions:
#
#   The above copyright notice and this permission notice shall be included
#   in all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
#   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
#   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
#   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
#   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
#   OTHER DEALINGS IN THE SOFTWARE.
#
#---------------------------------------------

#@xdg-utils-common@

#----------------------------------------------------------------------------
#   Common utility functions included in all XDG wrapper scripts
#----------------------------------------------------------------------------

DEBUG()
{
  [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0;
  [ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0;
  shift
  echo "$@" >&2
}

#-------------------------------------------------------------
# Exit script on successfully completing the desired operation

exit_success()
{
    if [ $# -gt 0 ]; then
        echo "$@"
        echo
    fi

    exit 0
}


#-----------------------------------------
# Exit script on malformed arguments, not enough arguments
# or missing required option.
# prints usage information

exit_failure_syntax()
{
    if [ $# -gt 0 ]; then
        echo "xdg-open: $@" >&2
        echo "Try 'xdg-open --help' for more information." >&2
    else
        echo "Use 'man xdg-open' or 'xdg-open --manual' for additional info."
    fi

    exit 1
}

#-------------------------------------------------------------
# Exit script on missing file specified on command line

exit_failure_file_missing()
{
    if [ $# -gt 0 ]; then
        echo "xdg-open: $@" >&2
    fi

    exit 2
}

#-------------------------------------------------------------
# Exit script on failure to locate necessary tool applications

exit_failure_operation_impossible()
{
    if [ $# -gt 0 ]; then
        echo "xdg-open: $@" >&2
    fi

    exit 3
}

#-------------------------------------------------------------
# Exit script on failure returned by a tool application

exit_failure_operation_failed()
{
    if [ $# -gt 0 ]; then
        echo "xdg-open: $@" >&2
    fi

    exit 4
}

#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file

exit_failure_file_permission_read()
{
    if [ $# -gt 0 ]; then
        echo "xdg-open: $@" >&2
    fi

    exit 5
}

#------------------------------------------------------------
# Exit script on insufficient permission to read a specified file

exit_failure_file_permission_write()
{
    if [ $# -gt 0 ]; then
        echo "xdg-open: $@" >&2
    fi

    exit 6
}

check_input_file()
{
    if [ ! -e "$1" ]; then
        exit_failure_file_missing "file '$1' does not exist"
    fi
    if [ ! -r "$1" ]; then
        exit_failure_file_permission_read "no permission to read file '$1'"
    fi
}

check_vendor_prefix()
{
    file_label="$2"
    [ -n "$file_label" ] || file_label="filename"
    file=`basename "$1"`
    case "$file" in
       [a-zA-Z]*-*)
         return
         ;;
    esac

    echo "xdg-open: $file_label '$file' does not have a proper vendor prefix" >&2
    echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2
    echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2
    echo "Use --novendor to override or 'xdg-open --manual' for additional info." >&2
    exit 1
}

check_output_file()
{
    # if the file exists, check if it is writeable
    # if it does not exists, check if we are allowed to write on the directory
    if [ -e "$1" ]; then
        if [ ! -w "$1" ]; then
            exit_failure_file_permission_write "no permission to write to file '$1'"
        fi
    else
        DIR=`dirname "$1"`
        if [ ! -w "$DIR" -o ! -x "$DIR" ]; then
            exit_failure_file_permission_write "no permission to create file '$1'"
        fi
    fi
}

#----------------------------------------
# Checks for shared commands, e.g. --help

check_common_commands()
{
    while [ $# -gt 0 ] ; do
        parm="$1"
        shift

        case "$parm" in
            --version)
            echo "xdg-open 1.0.1"
            exit_success
            ;;
        esac
    done
}

check_common_commands "$@"

[ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL;
if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then
    # Be silent
    xdg_redirect_output=" > /dev/null 2> /dev/null"
else
    # All output to stderr
    xdg_redirect_output=" >&2"
fi

#--------------------------------------
# Checks for known desktop environments
# set variable DE to the desktop environments name, lowercase

detectDE()
{
    if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde;
    elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
    elif xprop -root _DT_SAVE_MODE | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
    fi
}

#----------------------------------------------------------------------------
# kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4
# It also always returns 1 in KDE 3.4 and earlier
# Simply return 0 in such case

kfmclient_fix_exit_code()
{
    version=`kde-config --version 2>/dev/null | grep KDE`
    major=`echo $version | sed 's/KDE: \([0-9]\).*/\1/'`
    minor=`echo $version | sed 's/KDE: [0-9]*\.\([0-9]\).*/\1/'`
    release=`echo $version | sed 's/KDE: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'`
    test "$major" -gt 3 && return $1
    test "$minor" -gt 5 && return $1
    test "$release" -gt 4 && return $1
    return 0
}

open_kde()
{
    kfmclient exec "$1"
    kfmclient_fix_exit_code $?

    if [ $? -eq 0 ]; then
        exit_success
    else
        exit_failure_operation_failed
    fi
}

open_gnome()
{
    gnome-open "$1"

    if [ $? -eq 0 ]; then
        exit_success
    else
        exit_failure_operation_failed
    fi
}

open_xfce()
{
    exo-open "$1"

    if [ $? -eq 0 ]; then
        exit_success
    else
        exit_failure_operation_failed
    fi
}

open_generic()
{
    IFS=":"
    for browser in $BROWSER; do
        if [ x"$browser" != x"" ]; then

            browser_with_arg=`echo "$browser" | sed s#%s#"$1"#`

            if [ x"$browser_with_arg" = x"$browser" ]; then "$browser" "$1";
            else $browser_with_arg;
            fi

            if [ $? -eq 0 ]; then exit_success;
            fi
        fi
    done

    exit_failure_operation_impossible "no method available for opening '$1'"
}

[ x"$1" != x"" ] || exit_failure_syntax

url=
while [ $# -gt 0 ] ; do
    parm="$1"
    shift

    case "$parm" in
      -*)
        exit_failure_syntax "unexpected option '$parm'"
        ;;

      *)
        if [ -n "$url" ] ; then
            exit_failure_syntax "unexpected argument '$parm'"
        fi
        url="$parm"
        ;;
    esac
done

if [ -z "${url}" ] ; then
    exit_failure_syntax "file or URL argument missing"
fi

detectDE

if [ x"$DE" = x"" ]; then
    # if BROWSER variable is not set, check some well known browsers instead
    if [ x"$BROWSER" = x"" ]; then
        BROWSER=firefox:mozilla:netscape:opera:konqueror:galeon
    fi
    DE=generic
fi

case "$DE" in
    kde)
    open_kde "$url"
    ;;

    gnome)
    open_gnome "$url"
    ;;

    xfce)
    open_xfce "$url"
    ;;

    generic)
    open_generic "$url"
    ;;

    *)
    exit_failure_operation_impossible "no method available for opening '$url'"
    ;;
esac
Added lib/preview.tcl.


































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

namespace eval ::InstallJammer {}
namespace eval ::InstallJammer::preview {}

proc ::InstallJammer::PreviewWindow { id } {
    global conf
    global info
    global widg

    ::InstallJammer::SaveActiveComponent

    if {[$id is action]} { set id [$id parent] }

    set setup [$id setup]

    if {![info exists conf(PreviewInterp)]} {
        ::InstallJammer::preview::Initialize
    }

    set interp $conf(PreviewInterp)

    ## Do some cleanup from the last preview.  Destroy the wizard
    ## so that it can be recreated and then destroy any install
    ## components we may have created last time.
    $interp eval {
        if {[info exists info(Wizard)]} {
            destroy $info(Wizard)
        }

        foreach obj [::itcl::find objects -class InstallComponent] {
            itcl::delete object $obj
        }
    }

    foreach file [ThemeFiles $setup] {
        $interp eval [list source [::InstallJammer::ThemeFile $setup $file]]
    }

    ## Source in the init for the install.  We'll use this to
    ## create the wizard.
    set installdir [::InstallJammer::ThemeDir $setup]
    $interp eval [list source [file join $installdir init.tcl]]

    $interp eval [list set ::id $id]
    set opts [$id serialize]
    lappend opts -parent [list]
    $interp eval [list eval InstallComponent $id $opts]

    ## Add any actions that are AddWidget components.  We
    ## want to preview the window with the widgets the user
    ## has added.
    foreach child [$id children] {
        if {[$child component] eq "AddWidget"} {
            set opts [$child serialize]
            lappend opts -parent $id
            $interp eval [list eval InstallComponent $child $opts]
        }
    }

    $interp eval [list array set info [array get info]]

    set platform [::InstallJammer::Platform]
    foreach var $conf(PlatformVars) {
        if {[$platform get $var value]} {
            $interp eval [list set info($var) $value]
        }
    }

    set prop ::InstallJammer::Properties
    $interp eval [list array set $prop [array get $prop]]

    $interp eval [::InstallJammer::GetTextData -build 1 -setups $setup]
    $interp eval ::InstallJammer::InitText

    set pane [$id component]
    variable ::InstallJammer::panes
    foreach img [$panes($pane) images] {
        set file [::InstallJammer::SubstText [$id get $img]]

        if {[file pathtype $file] eq "relative"} {
            ## The image file's path is relative.  Look for it
            ## first in our project directory and then in the
            ## InstallJammer Images/ directory.
            if {[file exists [file join $info(ProjectDir) $file]]} {
                set file [file join $info(ProjectDir) $file]
            } elseif {[file exists [file join $conf(pwd) Images $file]]} {
                set file [file join $conf(pwd) Images $file]
            }
        }

        if {$conf(windows)} { set file [string tolower $file] }

        $interp eval [list set images($id,$img) $file]

	if {![file exists $file]} {
	    $interp eval [list image create photo $file]
	} else {
	    $interp eval [list image create photo $file -file $file]
	}
    }

    $interp eval [read_file [::InstallJammer::GetPaneSourceFile $id]]

    foreach include [$panes($pane) includes] {
        if {[info exists panes($include)]} {
            set setup [$panes($include) setup]
            set file [::InstallJammer::ThemeFile $setup $include.tcl]
            $interp eval [read_file $file]
        }
    }

    $interp eval {
        ## Setup some default information for previews.
        array set info {
            Language                    "en"

            InstallType                 "Custom"

            Errors                      "Error messages go here."

            GuiMode                     1

            SpaceRequired               0

            FileBeingInstalled          "some file.txt"
            FileBeingInstalledText      "Installing some file.txt"

            GroupBeingInstalled         "Program Files"
            GroupBeingInstalledText     "Installing Program Files..."

            FileBeingUninstalled        "some file.txt"
            FileBeingUninstalledText    "Removing some file.txt"

            GroupBeingUninstalled       "files"
            GroupBeingUninstalledText   "Removing files..."
        }

        if {[$id setup] eq "Install"} {
            set info(Status) <%FileBeingInstalledText%>
        } else {
            set info(Status) <%FileBeingUninstalledText%>
        }

        ThemeInit

        $info(Wizard) configure -autobuttons 0
        ::InstallJammer::CenterWindow $info(Wizard)

        bind $info(Wizard) <<WizardCancel>> ::InstallJammer::preview::Done
        bind $info(Wizard) <<WizardFinish>> ::InstallJammer::preview::Done

        if {[$id is window]} {
            set top .[$id name]
            if {[winfo exists $top]} { destroy $top }
        }

        if {[$info(Wizard) exists $id]} {
            $info(Wizard) delete $id
        }

        if {[catch { ::InstallJammer::CreateWindow $info(Wizard) $id 1 } win]} {
            ::InstallJammer::MessageBox -title "Error creating preview" \
                -message "Error creating preview window: $::errorInfo"
        }

        ## Execute any AddWidget actions.
        ::InstallJammer::ExecuteActions $id -conditions 0 -type AddWidget

        if {[$id is window]} {
            set top $win

            if {[winfo exists $top]} {
                wm protocol $top WM_DELETE_WINDOW {
                    ::InstallJammer::preview::Done
                }
                bind $top <1> "::InstallJammer::preview::Done; break"
            }

            wm deiconify $top

            ::InstallJammer::UpdateWidgets -step $id -buttons 0
        } else {
            $info(Wizard) raise $id
            $info(Wizard) show
            set top $info(Wizard)
            ::InstallJammer::UpdateWidgets -step $id
        }

        if {[winfo exists $top]} {
            foreach c [Children $top] {
                ## Animate any progress bars in the pane.
                switch -glob -- [string tolower [winfo class $c]] {
                    "*progress*" {
                        ::InstallJammer::preview::AnimateProgressBar $c 0
                    }

                    "*scrollbar*" { continue }
                }

                catch { $c configure -command ::InstallJammer::preview::Done }
            }
        }

        if {[winfo exists $top]} {
            raise $top
            tkwait variable ::InstallJammer::preview::Done
        }

        $id destroy
    } ;## $interp eval
}

proc ::InstallJammer::preview::AnimateProgressBar { path {percent 0} } {
    if {$percent > 100} { set percent 0 }

    if {[winfo exists $path]} {
        $path configure -value $percent
        after 10 [lreplace [info level 0] end end [incr percent]]
    }
}

proc ::InstallJammer::preview::Initialize {} {
    global conf
    global info

    set conf(PreviewInterp) [interp create]
    set interp $conf(PreviewInterp)

    interp alias $interp puts {} puts

    $interp eval [list set ::InstallJammer 1]
    $interp eval [list set ::auto_path $::auto_path]

    $interp eval [list source [file join [info library] init.tcl]]

    $interp eval {
        package require installkit
        package require Tk
        package require tile
	package require Itcl
        package require BWidget

        if {$::tcl_platform(platform) eq "unix"} { tile::setTheme jammer }

        BWidget::use png
        BWidget::use ttk
    }

    foreach file {common.tcl installapi.tcl utils.tcl preview.tcl install.tcl} {
        $interp eval [list source [file join $conf(lib) $file]]
    }

    ## Source in action procs.
    $interp eval [BuildActionsData Install 0]
    $interp eval [BuildActionsData Uninstall 0]
    
    ## Source in all the Common files.
    foreach file [ThemeFiles Common] {
        $interp eval [list source [::InstallJammer::ThemeFile Common $file]]
    }

    $interp eval [list array set info [array get info]]

    $interp eval [list set conf(lib) $conf(lib)]

    set platform [::InstallJammer::Platform]
    foreach var $conf(PlatformVars) {
        if {[$platform get $var value]} {
            $interp eval [list set info($var) $value]
        }
    }

    $interp eval {
        set ::BWidget::iconLibrary InstallJammerIcons
        SetIconTheme

        wm withdraw .

        ThemeSetup

        set ::info(InstallID) "InstallID"

        proc ::InstallJammer::InitText {} {}

        unset ::InstallJammer
        ::InstallJammer::CommonInit
        set ::InstallJammer 1

        set info(Wizard) .wizard
    }
}

proc ::InstallJammer::preview::Done { args } {
    if {[$::id is window]} { destroy $::win }
    destroy $::info(Wizard)

    if {[::InstallJammer::CommandExists ::CreateWindow.$::id]} {
        rename ::CreateWindow.$::id ""
    }

    if {[::InstallJammer::CommandExists ::CreateWindow.[$::id component]]} {
        rename ::CreateWindow.[$::id component] ""
    }

    set ::InstallJammer::preview::Done 1
}

proc ::InstallJammer::preview::Cleanup {} {
    global conf

    if {[info exists conf(PreviewInterp)]} {
        interp delete $conf(PreviewInterp)
        unset conf(PreviewInterp)
    }
}
Added lib/splash.tcl.


















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc Window.splash {} {
    global widg
    global conf

    set top .splash

    if {[winfo exists $top]} { wm deiconify $top; return }

    image create photo ::icon::splash -data R0lGODlh9AEvAfcAAAAAAP///+JaGKNnaJdARLZ4fdGwuDMVIIFAY5NihE0hSW9EfKGKtycRPYRuqysUYD4kixQKgBMKdhEJbRoPlz40r05EtmNbvRULjQ8JYg4IWSEXny0jp3dxx4mEz5qY27a26NDQ0sLCw7a2t6qqq8nM8pGSk97f4PDx8NNVENRLB+VUCslJCpk4COpaDc5ODNdQDu5eEONXEdpUEc5REI43C3gvCd5YEtJREcVOELlHD9ZWEspREcpOEapDDttWE9dUFL1LEYU0DOZbFuNaFttXFdlXFdRUFNBTFL9MErhJEp4/EN5ZF81TFclRFaZCEaNBEdlXF9dXF9VXF9NVF8VPFbFHE6FBEeFbGd9bGd1bGc1TF79NFapFE6NDEps/EdtZGblLFeNdG91bG+VfHeNfHeNhH9lbHeNhIeViIuNjI+BiI+VlJeNlJedtMeVtMedvM+dxN+d1PeV1Ped3P+l7Q+d5Q+l7Rel9SOl/S39SPOybc++jfeuxk3poX/TazfXi2OFPCdxOCrhDCuFTDqM8CmwoB9xSD8JJDl0jB9xVFdlVFd1XFs9RFbVHEttXF81RFdlVF9dVF9VTF9VVF8dPFcJNFbxJFK9FE5U7EONbGeFZGd9ZGd1ZGdJTF89TF8xRF71LFbtLFbZJFKlDE9xXGblJFadDE6RBE+NbG+FbG7BHFaFBE+NdHeFbHeFdHdtYHcRPGuNfH99aHtdYHaxFF+FdH91dH7RJGeJfIeNhI+VjJdpcJNRaI+VlJ+JjJuRnKqhKIOVpLeVrMOdtM99oMeVtM+JsNOdvNtlqNedxOedzO+NyO+dzPed1P6VULel3Qed3Qel5RchnPOh7R+qDUuuJW+uOYe2RZW1KOfGnhfGtjeqqi/OzlPO4nO+9ptq0o/bQvkweCqhEGdNaKK9OJNtrPNVxRtp8VNiGZVc6LrlLIMpTJZ5AHYA1GMZWLqVgRsh4WZQ8ILtPKsFmTdqWg6ySi6FCLLVONGwwIdWjmYeCgcuIe4M3LVUkIp+fnywAAAAA9AEvAQAI/wADePtGsGBBbwi7ddvGUJvDhxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTnuTDkuWel9iuWatGTc6wXViYREE40CDBhAu3QWxJtKjRo0iTKl3KtKnTp1CjSp1KtarVq1izat3KtatXly/3YMNmzRqeaHGAydr0SBJPhN8G8gzqsGXYu3jz6t3Lt6/fv4ADCx5MuLDhw4gTK17MuLHjx5Aj4x1LduadZcPQYGnrSWG3t94UNgQrlrLp06hTq17NurXr17Bjy55Nu7bt27hz697Nu7fv37qvxbxGvHjxstXy1HTjSxMTKZ5AMfTseTSf0sOJl93Ovbv37+DDi/8fT768+fPo06tfz769+/fw48ufT7++/Wr4k1OjgwyYGbZUNOGENgwVKJQ215UmU355NOjggxBGKOGEFFZo4YUYZqjhhhx26OGHIIYo4ogklmjiiShyiMeKLLboIh7U3AHNMsgIo9kjlAhoyURgEYefcnXYQceQdMhh5JFIJqnkkkw26eSTUEYp5ZRUVmnllVhmqeWWXHbp5ZdghhnmMsrE8YYwaTgHnROWcHEUTNfgh4eQy8SBzJ1wEGPMG3z26eefgAYq6KCEFmrooYgmquiijDbq6KOQRirppJRWaumlmAoDjBpicBJFgFVwEYZeMc00J41uCKMpMMD44uqrsMb/KuustNZq66245qrrrrz26uuvwAYr7LDEFmvsscgmq+yrapghBltTNMJmGKNMVmpydChDjKa+tKGGGmiEK+645JZr7rnopqvuuuy26+678MYr77z01mvvvfjmq+++/PY7rixiCMBEJFQ4EaoSVqC2YB5ouQEMG+DKIksZFFds8cUYZ6zxxhx37PHHIIcs8sgkl2zyySinrPLKLLfs8sswWywGFgJw0tYnbIriCCbGLVjNWcoMs6kZZYgxMxZIJ6300kw37fTTUEct9dRUV2311VhnrfXWXHft9ddghy322GQvLcAmOoHKBcJdeJecHXLAIQwbaBSttAB456333nz3/+3334AHLvjghBdu+OGIJ6744ow37vjjkEcu+eSTJ523zdCBEuoomLSN3I81xTGML2oAjDTlqKeu+uqst+7667DHLvvseuf0SOaWhML5Kfn9eKoxwuxS9+m0F2/88cgnr/zyzCuPNmc5W9HFE8n9mMcddMThcOlHN+/99+CHL/745E/+vCTSWhKG9E9ASA3cyAiti+k0l2///fjnr//+qG/SCY7SEpUVSAGFB8EoGsswxujmNzP+OfCBEIygBMXnPxzhTIAEdBGdgOeLujVwgiAMoQhHSELFoS0KlLjg+ghIjRa2UEjKSFUH7VbCGtrwhjh84AkpEcAwYIKFLrwD3P+UcaYZfjCHSEyiEpc4ux0G0BQ/hMIdggg3M83Ng/Vjoha3yMUuHs6JTuACFAl4hzLeoQ7RkIMV6UZDL7rxjXDcIhi5wDkymhGNajwTG48Yxz768Y8TnGMdoVCHO6ZxjVgEpCIXycjyzXGMhDRkHq/YxkZa8pKYbKJOeBhGSBayjHhEZCUzScpSmvJxj4ziJ894SD0m8pSwjKUsA5dKAq4ylK4c5Sx3yUtT1jKSoGwlJfnYy2Iac5G/vKUw95jFYzrzmW9MpiRFSUxoWvOaSJRmMCfJTGx685s21CYruflKcJrznBAUJy6H2Ux0uvOd5FPnMssJz3rak3nyJKcu78n/z37GLp/UbKc/B0rQ/m3yiaqcZi6rWdCGOnRxAF2oQB9K0YoKLqLstKhGN/o3jHaToyAFqUfpGdKSPnSk+zSpSv2JUoau9KX1bOlEYUpTdMq0pjiF501zylNz7rSnQL3mT4NK1GMOtahI3eVRk8rUUy61qVDF5FOjSlVkHrSTCd1mQKvKVUtOtatgdeNXw0pWLY61rGjN5lXFmNVxbjWtcDXrWj2p0IzG9a5JPCte9ypBvfL1r/zzK2AHez/BEvawFJxrW9f5UcQ6Vn+GfaxkkxfZyVqWdpW9rGZfl9nNelZ1nf2saCUX2tGatnGlPa1qEZfa1bp2cK19rWz9FtvZ/9o2b7W9rW1zq1vZ8ra3rpWpDAJB3OIaNxAy0ARw/UYEF7hgBdAlBCGg69wYDEGzLZVBHhKkFz4w4wbL5RsRYEGPAcQjHehFbzzKSwB8XNeyLSUENgJA3/ra9wTTeAEnwqs3IoxhARfwAAhKQGAQdMACG4hAP34w08HKtAfxsG99URACPbQgCZ3g795eQIALfGDAIPBABSggAXcUogpMgK9ibVlXZh5hHICQ8AlEsA9DZMISKdYw3jYBCVQ44MMf6EAFMBCBBtjYCZtQMQoRymKtSpQRsYhxfWf8Dz8YQgdSsKEMZDC5LRvzBrH48Qc8cAEST6ABQnBEFHI6BCJwdv/FwHSrRIlACynTNwQkMIEfhOCE8RFBBtINNCFk4GbBEWEYwuAy5GQADGMYkwhUYMAHgswBDEwgAw2oQSXYTA5YFJp1MqWznVEggn/oWQiQqN1wj3tcQgwOC6tmNXEV/TciSLcVw6gGd6ghDDEEghCf7lsg+hAOHAhC1shONnHFAIhvwCDHfFP2rBu8NywQQtmuTpy1sQ07OkuazAnOgAYakIk+E24Iz4WuuqkbgxgczrnpXvcKqhsDauetufJWN71rh+5867vdwQacc/09bxdYV2/ojjfBF55vF/ACAvgAL96aq3CGL3zQAW+pAEQ94VKfuhF6k4EcgmKgAnVjD9D//pt2SW4ghTCD1v2VLhqs8Q07SxgQ3riGLmbdN0FwIwDf4EbJh050omsjHAHQxyCMIF4xaIPlJe8GNWAOOEJYwxtF7wYfVBHwwcngGlgnuta57joiUELSH7hAuMdd7nO/YwAF4Ec95l4PfvBjAAhAgKcHR4RSwD3udJ87PwqAdwK8F3BDIAfc5R74weNd74WWQXkB3/i7533vgCPCJhbPeMHfHe/zeO8Q3pGAAdg98KhPvernXgAHbEAePEgxERQf986v/vbpQEcybLHlQmuc4/RFwQhMvWeQ5+0GzPiDhCVcjx4UIXCEoIbNJwyOacyAb1u2wzamv/z6AqIP2BiG/3QnvnGfd//86F/+CezRgkmIFwt9SD9+cZDyv1md+3fmxyfqPzhCXAP/AYAC9QAKTNc63jZmahcB4kZu5iY4oxdgH0BgJQACaVcBG6AAlvB8hrYJACZgEjiB4IYB/XAD+5V55JAAHhCBEkiBFsABFICBjIA3Q4APF9ABA/aBQTZiCoBigdN3A9ABH7aCObgBD3APGjh6HXiDBQYCTNiETviETUhpEeAOaqYJQ8AOSfiBULiFUDgCBUAPvHBdoVZnHUd8QgAKtQMDQaB83ScCQuADVBA4WAADuMCGwXcCfmADheAJSZY3hIAGSJd+6IcC3sAMgkAIZaBc5ieIjChhpP/mBzXgCX3DBCwADt1Hav3QAqGwZoOjAu+AAo5IAjZQA0HAiYajCTgwCJZoXxSWh5iABGVHC9+WgAvYdoRzA7XwYyCWdhuAAQ9QA6iAhoNDiQjgYTdoYCMWAfmwBFVQCoJzA+sAhDeYgxiAAf7QApggiQKABTNwD8ZYYGlXaQpQA5ggCYLDBCoAD0E4gbzoi29YCX2oCCywANJIgR7QAReQj/q4j/yojwhmaf7gA1GgXEzwAvT4YfaIj/24kDXoASk4Zg7ADjIwhnZGZR+3N4+gipcYAs9QCJKgXIBTBBoZfCEwAtlgCD5ACVnEZd+wfChwAjAZkzCJAqDoiELxDbf/wASLGHw02ZM16ZI+6ZMzRgKQqI17Q4n14JKlZmOW4IyDAwSiYHMztg+JUANc8AiJAwSDwA+sWGr5kGaUEIuzuHYMWDiM4Ai6SIEdUGkS0AA28ASfUDgc1gECxoRpRwERMAH+UANOwH98cwPvUJcgaAEklgH+IARWkGV48wNW4AB1yYQiRmQHYANdYIodpQIDEIQUqHaW5pao0AR5Q4xAiIAVwAEbcJqomZqqeZoUgJcSkAGJQAoDKTAqgAAPSWaluZq6uQEcwAEVkI8dcGAQsA5EAGfKpE8BA3wBOHwXqTdMAAOr6IgBcALxoALn+ALReQIk8A/ZoGl9KAAyIAx2/xiAMzYCI0AC6JmeJGCeIjCTrMgPg3AEKvBzJxACInCfIjAC+BkCJzBh9omfAGqe21llkdg3RAADgeif26kHg6CYw0gFo3aeViabikMELJAO/mlq+VAIVPCdq0MEkjCWCsh2DSg4MjANQEZplnZmNWAJGcZ3hwAPDzlpHsCWZ7YElvk3KxAPTvgBhDmiieADxjdxoCBmkFlmeakB7mAJXkcOI+CENWppmFYDVfCieHMDKHiPCBYBEtClXvqlYPqlE3BpGhCQs0kENzAADnlgCRambvqlGEABvlmaFPAA68AEAIRVTSZnw7RxZBh8Hld8e0MEh9CS6ZcOgtCDMGCoAf8QAqaWDYVACSApAITgDfclAgO6D/vgB5zqB5pqAv/wDyRwn/xZnv1QCE4wn426naAKqqGqnycAihQ2oKZWq65qArhalH0jA78wfSdwnv+wD46AlYRDBGdgZ3imZzagBB56OIKwB1M2AiawD/ngCCVogLKIgGRpi/1XDwmZjJeWAe7AA81aa5I3oyoqAZc2goZmCwZQAiEAmUM2ARqgAfmgBMQ6cdk6aWNGmOqqlzzQrUt4lyPaAEsQh3pDCAXQr3gZrhnwsBAbsRIbsfVqpiC5AgtLZg07sRwbsRMgAXFKAUSmYDuwZHoaZ4yFRcopfGYojHpTqIIICOQgCF13bzD/S18eB6mSOnFYYIektp1+kA3+IA5EW7TioA6eCqrrKaA1tgRN4HN4mA3qILVUmw3Z8A/RSnzqMLVcS7V+cGo4IGzQOmHliZ72UAtHUDhEMAvISnzuoATXijjPWl/JSq064Jeoc4DgVrDc2oNYYACb6YJcemkToABBkK8mSg/8ygD42KZjqgBhGzgrwA8TaI8XwAFJqgGGcAlg0F/7OmZCtrEZ0A41G3LmsIQM4AEWgAGvOW5LkLYht7AHVpjjdgC2e7u4m7u32wANoAFBOpsCgLH9SmQLqLu5y7u9+7EREKesW7g5cAToc7LHGVArG6ioxjc3O2E96X3pAAO1tqiA//qokQqShGAHZbgP6kC0hmADQlADmdACmVADNmAIiZAP2bAPrboP4iAEQVAKgsAP9qC+hjDA9Eu/BRCt05q+BLzAiZAInFqge0MIzPCTZZueIzAAh1ust9C2ygq3iyMIGHpneUatHiyW2sq3JVp16bCZrjmmLjwB+YAEkxo4kjdmWiq4/zq6Gug3MoAO8RpkF9CCZlav+aADnXtv2eqQF2CBg/u4kctcufCuCGgBpcm6C/i6eyMDsjtkrXsAibDAYBzGBJwIDWCxeCO8kdnFXyzGDEzG1diaSdoAX+AEKSS9LeZBfhqhZjikeQO+U2af/PmTAYCoNXugjOpxejC+eP8zt/T1q/+QvjaQCVZQBZDgCZasI47wBDVAv37wqIngBWFJBO8gD5HcBVZwyo6QyoWQlMEnrSaQDULwBKc8y1bgCD4gD+7wBUbph4wqfNu5tAL6DC8wwyq3wSRJfMsat846tqs6rdWqzKoDoiJaiynMw7kgAgaGuQ7rwhLwALVQunxDCIobZP/YxBlQuDzQYISgDyUQjiJbja1rr0FwxBM3BbM4ZBGQly7szTu8N5uwAugwgUK2Aa3pmleMsHmjxdQoARVbA12QyhAd0RI9CqNgBajgDu6ACcCLxlxcsbEs0RFtBZjwBEuQD7wpuGTKv1RwQXTlZH1avXuMvb2MqaL/OgKx6n3n4L3i5ccBkLOKLACCEH8BWJL/IA6GQApNEAWc4KGb4CmUUAmOsAQ2gL/iYANcsF9YQAOOYAVOEAVe/dVFoKqtHKzZ0AKQ8Ahf7dU4ogNPMAoOijcygAz25ahKq5/nSQL2EAYxaGjGfGfIXMKJAwPMXLfP/Dp6S4sk6nWUG5lkes5eOqbqsAOEU8NkZqPnfM5jumA8PAyb2Yv5nM/xnA/z7LmpO7v6/MLoPFFEwAn6gIwju7x5edARvMWsW7E+8Alonda6XQRfbQSfogQ+EApOGbwZ29FlegWgkNu6HQVFYASUgAS1QI//KG4aYAOO4AksvVjzZDcry5x7/+ayeZO9yYqr/zACISDI3RtwhGqopCa+OwvUQj2dIhACA1ADL9BmNasJ+r0JUaADz6AHhsAKVACSnQAERpAFxCwAgfBzjezKkBoJCa4JnUAJkqDMgcAHWZsNfqCf93nXA/ACfMe2dOu2gC23gz3C94q3lHPY21rN2FcM8YrYDeDYj/0AjtDPKqe4s/ua4obZ6voAuNB1REAEgLuW+iwB+UymmpvBSJy6lxvbD/ux/9oPM5DghOCtImZmIEtkZNoAhQC7CU3bresPmGAECZ43Q5DmIKnfj0AFUZBFwitkVlymUHAEZy4A+m2FkRaOI6q5pPAJ2b2nKcvdfxqA1ptqe/8j3qaGv6Bq3j+JAudAs/3F0z793ov4krGKAvqQDGbQChsXaMWFcXgeBaOQCZlgCiq+NzspfNOayO/tda8gZbOqv9nA4flptjqw15nX1xT219BcOCBMtyhe4h+axDLet34D0CxoxQ0gDg/QpebcDzTgdTo+rz1O4+rKrnuzAulQAqqr5cvL5URsxKS9t9cu5WP6ADkQcDIA4yCQgGMa7lx6xWAO12L+sGQ+A0O+7/wuA7yAAOxweMle3FZsmE9wBOA85CtwDp1dsEcN6Hbs0nuUxxPm3ULAx3jD03QtteTt6Nyr0xNH6abm6sp1oOgQgC8pyIAACOEQDj/RDdqwB9X/gAxicG0gaglV8NaBs5Mzhqs6e+d9QwjbMGXbqQ6JIAT/EKDoCQ89YKJ93ai+/sEn7szWatghesLU3IOvUORrZ9T5gORcmsPtoOv2V+1SyrvK26UT8ACj0M8yYA7YjKSv+QC8mWD0Ks/07Kepu6ULKOVqPwFUHsGtvZbN2wByypayHbtjloxITua0sDGtkAAbcA8/ILkZ668TEAH+UAg4sGWe//lclgvpALg+Oudu2QUQz1aCvt3JWejt3Zwvy9507QeJkA0df972Rcghz96VDpI3wA78GciNWF9/4A3YsAaCcAi//jerLq378POEQwhw8JOlpr96CA/z3eHmaQ9W/6AIQL9xvD77ybw4gi3sVL/8K27sLS653V76l9YAiZAJg6AAXNrEhTvtNGz27y8OUg4QESQMzJdCwEEBK/SB8MBBoIQDDyxc4IBBggYNhoKAQSiACC0GHi5siJBBwwENA1VKUJCEEUIZv0R8uGBRQgNxFS5UsGiywRIqHQXIKPDBg4UNGCJggOCAgQGoUaGSYFBRHg9OQoWuKHqUQgSwEBIU0FfWrFlwBkKUAEGT5ASMB4Q48vTJCRdTmEhBqXPHb51ocuK8EcYGTRkxWD4CCtAYxYh/JvwIAaX10LfGAUJE9mNDiB4TJkiMCIEiM6Bzgg4SuZxZRORshShpQkjDnv+IESJKZ+bd2zcgbdQOEdFa/KAgbplPiAgde7ZxrTIwNz4B2U8iKE503NaNe8SIATygr57FuPFmye6UZB0/XtCezCFImNiXTwmT9vn1rwZpdGRJDRrIxInxYhIBhA4cgkscGxxBQh4JHpJgAgrbwa9Aej7ogKcJMmggEQVWGmiCdoo4SAZgZhppQpwWuGDDnjTIJ4hHOvoopP8yyMCfRCYQcYJ8joCpHgQVzECcRCzowIIYGyhEyI6I8o8DCjCgoIIOPPhgSy63XJICCfLRgT3juJqyyis7+AAENtss4c032zrKSIzEqYELKuzCSy++/LoDMMEIMwwxxWgxLwAUXpP/TAhILJsOBfT0aCGJTPTYx4R/SDMts3RU8AiGRxV1jraDfijnH1RHC+EEFDb17dXG9oCBOP2Qy+yx5mQjtT1C7Lh1s338uZMJGsrpLgQRcCOhnB/GI+KWQ9HrbL39ihMknfjmq4/aarvV6kb/SPJpwAL1KeEDDj005IsmBKBBAbDAmnACBVK40DgZMoSxwwZsqOGBgSR8oBKPZFgowQg6FMeQBTxY0iKMxOQIoRuPElcDfwoJ8cd2iCMknRI84HCCD91x4GEJfFoCSpi6oqhKKzngoIKZa6Z5AzB3HHM8Mx2ugAKgObBgoguKflHLLUVCSqkO4zKkiyYoaeSuvPbq/+uvwAYr7DAxPDL0VsgWbUQrUOPjrBAkLKkBNEw15S0dQYgouzFF9dAVIU0GYRvT0XRb9QRWW3X11Xpg2M9Wx0agz+7n8gsEPuqsS+QJTwRgRAl9QtAc2RFIgIcF6DYhojzHpLWBW2+Pg1wzbfNxhMzUvSVCEgbCBVBAAo0jgpcQikw4gwNsGCUKTYzoR6l4J3yAlCJ2FYqIfH3GgF8hfNj4IR/luYGQcxiyIOcPa0jAA5EhlnEjG0ES6WJ/fHAn4BFZmmF0A0DI8Ugh2smSyZQDBEooKYmkIgJZylIwcEAEygsu/kBdccxEk58hEGgTpMAGNlABJV1gaQJp2knsZP8JSUhianuymp8ApbVBdW0xt1LUZMYmlNYgSlqF8MQjLJEJP4QmU6w6zTlgMLcAiOpuCAFCISwVGkylajTfSVay/jY4RJ3jELVKTuJy1bgCqeEP8VGcP2xgiU4chAX8ABzgQtA5e+ACCM6zEbTMJpnTwc5bMFidfOjjOjnGbj9EkELt1nc7chmHEOg4V00mpIFELAEUmzhIKB6AQKVMSAHigU6+NJSuBgghCPLIgIgioIAXlIIECHrLSWwwiPGV7yIZQR/F1IcUAIlJBwBbSQQegItDdA9d0wMedrjQAZSpLChR6gosO0QhZCYTmTpC5M6g0zOKWMRHIorQUijAgaT/cBAuATpAIhpEiShIjWp8utqfsiYorhXqUI/hDGUc9UY/tEBIm3DC2i6Vqd1wSgWhgs0QD7KJI/jAEPnwwz4uhUSEokqJyQrcCUJgD0TUqD2IC0B1/rGPUeWHEN1goQj8II4WwEAGhBjpIAzgmOV0bgCIgM7oosUZ9eSxWu/J1h3vo8fUgcsrgMzdtwRQP1VOgEGIuIEMjHqIdkDAglWaUAb6cYNK6guTNQgCDfIBvwhhoB8ZEplAgGcIH+AgAZeM0Ywkyh8csU8HSFjCNFWCAQX0oHYXAJ84hNADdpCPfz55EgCLAqP+BagBgiVsAwaLEX8EQaYI6dn3SmISZkI2/wMUitCI4NKAA4hjYS1QgiSYEM4RVq1PWAvU1gi1Qse0kFHvlGFk7FY5AZQiCWvTodscM40+uKafWDwIExrxBCEkQhzqyEY2/FBQgyYXianSjUMh8wwa5IeiuDJBRgs0DFclyqPymMYc6PBdOiSDHyzs3D+YpTs3thaODfTWtWq6rcXqhwhDqJZOv9c/3JUJZL6zpT/68Q5zBDgZ05jHAixQgaTMSwHRxZdUeZnJJBhBCbQECwY2sICxrohkdq3CDbrCk1VKLH1pjaUjJNGDfBCwwhBAgM8SdhJDPOEHr2zSyvxK1lVmVrM75rFmB+sPZ5apmE06QJGNjBJlUggnif8whBCuUIUpMOGz4iThaM1Z2hR6bZ1hcyHZpqOZs8E2tk74Atvw6SpAvNQEjGOjADYhhUp0IRNCMEQi7Gxnf/hDHXsu7j7+QYLudE4yg7iXcSi6nMX5U5AcLZ1uoIgoSCMqpaMpQA8K/U+XwjOOOKXpeVr3Oj3ujhy0yg8f/XjfcfU0SsU4kMi+shShZYl8Disagr/S1Ay0wwjFgR49pHdZIViCEzPoR8AOyIELCPB3B4hxEYgwVlVGrJVotRiAgByFSDjiAQS0EpY2BL5EZKIKROiFXms8zJbhOC7+ykQN2v1ud2fCBl5k71Y+bL5u2kDf+/aHjpA5IgXUwBFOkAL/Izcx5dCS04TnNK0Kv5badr6wIzGEVJg7goUe1CAbOnT0q4TI26EQgjhRaEQVwmCFU3yh3TUQgr7rLFw/+O2MnGkByIUyXcVVV9HfwsKhUiqCR/MGBSntHGRWAQRep7fi641vfuj4Xjzq0QUDWABU5QuLpIEYIw1ogaoRQoh6FJIkA4lZBcx+dplVSZsUUkAOGBkdB1OPC4qZcFavVLSKpOxDmagEETxsFK2zcmLUzhHGdBAFAaSg2FndgJIcaxK7OiIK5A7JXv2H7hP9NfAZqwISPP/5zzdBFEvIhLB5du9VCgsTSmA967/QgGNOIHlPFQCpDg7acZaQtChMJ2oR/8Vld8Lwy9KSp1A6UYUWmJk0Ht+t82QgBz5Y3c2lCKcnmuCEKuQgCUFwhA+gUAMbiEDSXM5EI9rckUMzB6M7FwohsMFCEvTtb2U0I+eK/h3wIOLSHiHdeWBa75mqo/kwAfvYP/kaggSwgFAwHI3SpfLZpp9ol+f5KYZwiJTxkQorIKVAnnlRpn74AVKDibjzkBpIAkbagX6QPVijmRgJHiuYPCkBLJMwqxH7oxk8PE1gglXYtqW4IARbNuz4BNEpt6Nokr4iJhwzCX+wAikYjyhwAksQMyFLQoxZgiZgglLIwkfgAXl4gMlSwaV4gHUgtdujMtEqpxNCp9N6OERRrf9GEb7ScS0a0opN2IJKuaflEzrm0DneIoRvQAFy8BS80QRCLESEwEJPGARwgDg48jqtwLkrOr8TEYZNSZQBTCKFykQS0MTc+I5/gC42ehY124dN2w8sIARCwILjwBZPa45BaLroIIShMAdaK4cVCMHoYAIDYIuGeLGTeAIk0IpBagvL0wAd8bdj7JBj/EKVmIBbwsWhGEEI24QcRIQQqTCm0ZFuuoKg8DvUixgdGDyvqTy1ah5NAIIUxMZsxAkhcIKsoLwixC8bQ0LAQiwfIJ7x2AROUMWOcAH6YqxvxBgf8IRd0QROeAEhYMZ4gasdeLsyTDjduzLeQwwtA5uI8zL/eJpDreCEHKAtTBGBExA6xdkHNkOIG3iDxvgDdBCEQBA5ZyGCQCiGSqwbG3DEm6uiilK/kjQ0bVAO69gzoAxKofSDvvEOEtgHHRAK0ek/SNlEUtQBJiACqZxKqqxKQsCDapAB1eEiVOkHQqtKsKRKQniDaiCCFeAHo+gAB6CHW1iBFTAqqhwphXgTDbkYgcS8gqkfhIGLI+tLv9QAt5oX2rOR6NkXDxECLni7HWAFDOQgHcEJGwgF/CCCUgjIGRHHiik810E8AbgBHbhGBTIJZnsCziQ3c5NHvIxBENMRf3CERQhL2JzKIYAHdvjHhAjI9pHCg4iCIFAAyqompRjM/4fMPStLw4arSOpQLYlDCIqbId1EiEfIARzCw5CMnEhEiEDoycz4hmugBl24gZY0KvEcKUIwA2vYIuoYQHWgDEk8DpykLuuKDkp8o2xAEkO4T/zMzzrLh39wImXxHAakmPSqqNGwByGASmgsDhkYBkDwBhXAj6eLnNzQAx9ghAT9FiLwhm+AgV6oHaPQEgbgh3g4h2L4hVzIhV84BnTogxI4Ae/hJYxIBEzgzK8DGZqggKaxT/3cUUM4gIDRpra7NEsyzExKzIPgyI2hEJOAsS+gAtogAkKwB8AzH43AzFdiH8lDiBSQh2nqIJyoAUugmA6NR2G6MVebEAlon9f0CP/YXA2pFIAhoAcOIACtPIie2byBLI4jyATAbMwCCgbiGM4qQ0OGSyF18smLmozKgEP/k4ziMw56aoFsoM5WOaPr9AgBQM/eAIRw4INqmANfaINfAAY6wIZvOBT1uo5MOIL2FIBDy7n4FIpAeL/I+YePEoLVGwVd3VVddQRHUIJCGIBV0RwRiD+IegmK6b+cXBUDCAdnfVZojVZnNQ1+0IFd67SK0hxI+QZp7dZnZQxwGIQBIB+jAaYtYZPNWYsTYAsEWc2tM4RQCCOKWYPeQRhtNIRMUAJT2Fd+7VdT0AEIKSDH7AcGE0ENqYjLKsG3EwAmaIdl2jpxKL23gx7NMx//GnQlcrQ2HTCR3nqXpsIIUxoeMT1NvmKZzCMrgWCKBCABqWhZlzUAfWAAJiHYCzGTesSYK3jOg+CBGujTrArDeUI44iRULOs9NqyO0OgyRk2UswlG6GCCHEg+vmmuYg2NnVzQoOsNwYEVSMk5dQArGjU0nERakmQ/jyCEcCid+fhaK6CCUgADuI1buX2EF3gGVgGcYt3EcihYjxhQh6pOWAncirKHvnIv6liVrBXcxtCHFnARC8CmDRCaZNOSNqlckeAJX9QAu3KChU0IdCDGGLETLoiCt5Vb091CBUggZHoARyi06Ikm6jHBjugB32QmU7ICSqAYD3MYhAVHKw2J/5/pH9fh2FJJwQ7qJnZZWMozTP8x2aH4qwFaCgug3MqtXuutywgQk1Kw0wLg3elBLMoxDt70hx9dyKeSMtwb1IUrWopEreWIDLHByIriMo2EjlKAhFPQg6IUNKsdIkLwhmzVHB5S3FtpStgItyrgR+hAHEvsX5sTgMfxSRL4qBr4hFLDAhZYxK7dRBKwh1FQBFIhgjEwD4fqOALujeXwgznsNEgx4RO+lROwBxtQqkiqsMjViaIBpqJ53LFbUhiDgrCFU3v4I34xhBcsNSaoBaDJRh1RAKctGF97vABBzM79gUF4gKbppiVAAuUFgwL4kkM6H8yEBQf4j226NqHgAf9/6CAGSYJCIzcwhsD/6QhC+GLHyirJNRo93mM9/sEJaM3tvU0wXtLchI5HqAUelJdqOt/0PcP1nciukYEoYIzlGMCLEoLl9AhBwIymxJR40lmhwAInaIEBSJZNhN81a4FJoA0ZOAYUiD9YJg3ETdyhm7mLUgcGUYIg/pZASI5O7t9VFkZgIGHI+IdsSIQukNf2IAIWwJZKTpURKAAWoBUZGOGcLLpZFhxt3uZWqQ4SGIAnIQJBqAcZwubA4WZ0HrpksQd/OCBcoywDqiCcUTvHBNluQkwFJgIXOIdv+x384Vz5mgEF+Apl/MJxkAFacQF6GAleIkG364hN2FJmYpD/UIAdfU4AP17SfEAEcRyCG4imlLnBsC0eK/DCr+JGoXCBM/geGPWQI1wNF0jAsaOQeMYZC7ppnL7pJf4dQD6IqTMmyGofvBQKxYukf1uKcnABRhChoX1kNRQDImCDnqzkhIIHJ3hjZ6jUTcQUewiGJx4PqH0GU06ofQiGYSKCX4gHIcgHS/Gz+MsNvymjzTHlrfYDXDYETKAEBYaONkhbi9IhPzBrrcCCYUjbro2Mi5IHLtijNfjDmdOh0TiHM0AIa2jDU/4zuG4izd5sZUEVFUYCMWCGPzhsaM5szuZsWPYDBXgAwzIsjPjCwFwJ2+WmyMvd1XAFfHhcgj5GAZEE//kSAHyAAGmSLHpZB1jQBCJgBwRIMMiSEVzYawF4hN5UF6BwHk14BxruoAxQAEwgXiLQBALIu6bZblbAR4TgBKtakGHpCE3gheWOEWPUAHn4ak0ghwWokoL+TWra75VomvbZXk3ohfuGbw+Zb0nUhEc4Hn+erAh5gHtgB0rQE0fevafOzsMOjYP6M3owiIMghDxQ50vkG3qQvkqiBmQZQIMKjfibBqjShEVAhCVoOTtTh4LCRA7+s8umj2zwByQRuCZsDxlQBkCgavpQcRJgcTq+hlouZiSKv3iYgVJDgyGv2oQCNAM4g8e58CJHKC7v8i5X4RfgA3WOjIPycjPncv9bNQSXqzNxKDKQXcZjBFnaTgSq8u3VGIL3/p03d0YLzo8YIACm8mGMwMB+GAJYEG49H3R6kQJcXIR+CB9L6Nw/T7AOMsYMeIBYQIg/vzVBd8YxVEpcgEyRRYghIAcI2G05n6x7oJUhwIds2iY5t/TIivU3F3SMsYJHGALszsY9n4BVN44/5/U9B4sHKAckqAT1pfCGY4JkoAc9yAah5LN2sIQLQet4gAdoD8ps0INgwIH8YIJfOIdnj/ZtDwakY1gkwL4ggAI6Ey7iOq7kSq7j2vEds4FM4ALbbg8mWAN0gAc9IHc9KIdzP5FiuPZxF8pseAYcgEUBGIN+//doVwf/PYAHLpiBZIiHg494jY94P7DVQsABc7j2bN94kgfKSfUDQ2iBJXiCJ1gC8KuzInPtWMcsHbP3MAhiIsCHfsgHf/DLA8gHUdi19hgCdtj5nvd5/zoCReiHfjj6I/OHfKiCS2MCR3AHXM33g2h1o/f5fFgFztT6fED6cSBehHACebD3RbIRSSCApkf6dnDaIQAFAuB5n697uzcyxHKEUoj7uXf6p/8C5yX1og/7uof6cagEZJ9wiXxqLKCBQqAz/GSy+7T3eEUIK64B/WQyG1gCgG6PF8f8/JR8G6Ach+SETSgFT6gCTPgC8LMzJNEsHucxzV+CgQtk/WAERGgBGwj9/8knfYTAghkYhJe/T8lXc863/afN/d2vM+bHzxpgQhwYBMgnfuYvfh7N/EQ4rkKgAhgYhBbA/usPfzszLiEwhSagggivglHwApZj8x5DEs2vAUxwgl0GKEwY/vz0F7rQj0UAiCCZbBgqaNCQDSFQnEShUUgIwYM2MoV6JOAiRk+OMIFighHjjRwDDxa0UYMUFYw/HNWIaNAkppQfBTwK0qXiTAFMXvgQQrKgkCtVNl1k1KOFy59KlxpMpMGflVICGNFYkrSkEFagsOS8WETHyJ82EpKyVIWLKUykoNS547ZONDlx3ghjg6aMGCxRqihR4uhv31GjlFj6xAkjEyRBgv/0BdzXEiWuXT8y8ZREiY6/jvoquVQlSk5NoplEaWJJSZcrXzLVaF0j0xcoVrg4kcRJ0+TJnKhw8et3c98glYzM7NQoSGbHg5UkoXQ490UsVE5z5rw8iJNSpSAh/129sebw4h0F8cE6ZqkmjMErQT7+vWa/S4RkaiL6/qZSVJyIwgTli2s1tBCbFVV40kluRlRxiSkNOthgKAxBh1EpToTyoBIPmmIJFZVZEsYoGoZxyScezaRXFM/NlN4lIYah4SWVgHbRI05g6GAYVViUUylR7JgTFXyZEkZfDYYRBoeIecLFkS9m2OB3T2oI5ZNKnCKEEI48osluSTRZpJGWSJL/WymgoDWkhqM4MkqMlaClFltu3QGXXHTZhRdXnZQCBp999vmIihdlUcojfvL5CCOSTSjAoIUaCsYjCC7KySNReNKEE5VUUUUlTjRxhBSlELVoV40+CqmkM3FC6KmPlJIFqQKsemqfpZjIxJ606vpoKZIkgQkXoOm5K7F+PlIJJo7IlNMmj0zhCSSZburpEVGYmBsWw7Z67aK46uoqV/k5auyrsc7kLa2pXoSuoaWoa+4mnejayaiCslosvqV8gloVJpr6aKSKdsWun1FEIQUVlzrx5lptvRXXXHXdlZe5FVt8McYZa7wxxx0L0GuKHn/ECSWScCsyyimrvDLLKEdB/8mMLV+0CaWUNLJwWg3LSWfEd1IsM9BBCz000UUbfTTSSSs94Sak2YwznA7PCbGdEwu8NNZZa7011117/bXKTb98M8NxPlynxHiCvTbbbbv9Ntxxxyr202VLzXPVasu9N999+/034BfTTXbOZk+Nts9XB7444407/rjRg0Ot89k9Ww055plrvjnnuUlu985Up/1z56WbfjrqbX9e+N2iJ5467LHLPjvQq0cdOuKX07477737PpntlB9uud6/G3888qUHbzjeoyuePPTRSy/38q3nXvz02Wu//dbV40486dyLPz75Mntfed7hl78+++1XfP7w6T/vPv31uw9/86/bv/8//+vj77ru+ifAAUrvf9dTHwETqEDaGRB881sgBCO4uQbKT4IWvKDmKOg8DHKwg4HToP48KMIRug2EASQhClOoNRNiT4UufCHRWIhAGNKwhiiT4QNtqMMdwstphLsd+jbIwyEScW4+nBzzANjCIjKxiQLAoROj2EQoSrGKPKSiFbNIQyxqsYsp5KIXw+hBMIqxjBYkoxnTqEA0qrGN/WOjG+NIPzjKsY7lo6Md87g9POqxj9Hjox8DaTxACrKQuyOkIRMJO0QqspHKOyLoghhCR1JydoysJCYdd8lMchJwm+wkKPf2yVCSsoSQZN33KljKVTZulKx8ZfdOCcT4CRH/lrYUpSyFl78T3rKXqstlEg+YQ18SM2uuLCYyW3bMZDLzhsC0ngObKc2lLXOa1hTcM1NZy2tys3bZlCQvuynOlFVznOacSTnPqc50qtOc7GynON8JT27Kc57WrKc9pYnPfDJzn/xEpj//ScyACrSXBC2oLQ+K0FcqdKGrbKhDSQnRiIJyohTlpEUvismMapSSHO1oIz8K0kSKdKSFLKlJA4nSlPZxpSzNo0tfWseYyjSONK1pG2+K0zTqdKdl7KlPwwjUoHZxqETNolGPWsWkKjWKTG3qFL9Jy0lCFaBS3eUSq+rLp2p1iFzt6g6/ClYbinWsW7yqEmdoVlaWda0u/2yrW7+IVmHG9ZZwresI74rXMc41mntla19V+ddS6nWwFyysYSWI2MRCcLGMXWNgt/nYjUaWqpP1aGXDedmQZjarmyVpZ9X62ZOGdpijbWlpT4vZsSERmoJVLWhZG8mpaha2fnSsbe+X2twaEre89d9uf6vS4AoXtbJFJTg9W1ybEne5dvStc/fY3Ogy97izxKpoqWtG6Gq3gNPtLk+/C96fine8Qi2veYuK3vQidb3sXap73+vU+Mo3qtbVZVpNW1/71g25tFXufud732D6NcDqHbBrJWtg+CJYm5ZdsID7e938QliL3K3wIumL4RpeeMOn67CHH9ng5GY3xGTVsP+JVQjiFGdQqnagMIuLuDw7tKUOL6ZrjIk44xrfeC7AeHCOaciJTgyYxnWwMR3q9OPaBvmFQx6bm9LyhCvYocpVpsMy4jCMJQO4ySl8MhUwxYVRYGLKVr5ylrcMZC+rEMxNcBOZpxyNaFQ5LstAhpqZzGYUuhnOZb4CHegw5yQrA88/NkOX9yxCN1chFBuZshzkEGhCG3oXiC6xoj1IqSiEudGO6MKUlbGMSC8jy8QQBjDUIItEZ5qDm/aEE6ogik9DYQnIiIMych0HOAxDGL5QdSuwoN9WX5BSUoD1h6ywliW8wQ1weLYb6MJlTBP7sKSRwieccBpl1xoYwvg2uH//rAszULvail0Vp5twlkerZhds8AW84b0LNMii3OaGIBY4wYRHSMIToLCEKKzQhVp/QQxlOPiq8ZIXLGyi4Zx4eMMbLuyJU7ziFr84xjOu8Y1zvOMe/zjIQy7ykZO85CY/OcpTrvKVs7zlKY/4w/VN5GOre8xwWk3Ec04zfTOhE53ouc+ZIHSfE73oRj860pOu9KUzvelOfzrUoy71qVO96la/OtazrvWtc73rXs+60IG+b4NJIszaDoOyn7CE1Tyi7W53u8HiLve5073udr873vOu973zve9+/zvgAy/4wRO+8IY/POITr/jFM37vCFOYp8v8n9VIgRKWpwLmM++J/81vPvOe/zzoQy/60ZO+9KY/PepTr/rVs771rn897GMv+9nTvva2vz3uQ++JT3wCU1WwRCjIvOzVZMITjWhEE5IPimg5ofnOdwIkoh/95FO/+ta/Pvazr/3tc7/73v8++MMv/vGTv/zmPz/606/+9bO//e5Pv/SZLy1L9GYjpPDC2jOhf1A0X1Ob+r0lBKAAmsX/FaABHiACJqACLiADNqADPiAERqAETiAFVqAFXiAGZqAGbiAHdqAHfuD/CSAXcEEogIgVqAUqqAbxZQIAkmAoiEKTmIJghMiQxGANNgkO5qAO7iAP9qAP/iAQBqEQDiERFqERHiESJqESLiETNv+hEz4hFEYhEuLIkcigmjjCCXYBKTwBwemfF7ogiKiJFYwhGZahGZ4hGqahGq4hG7ahG74hHMahHM4hHdahHd4hHuahHu4hH/ahH/5hG2ICJnSBFj6BF1xB/nmh/l2CX4zhIGohKZDCKTzBE5yCJV4iJmaiJm4iJ3aiJ34iKIaiKI4iKZaiKZ4iKqaiKq4iK7aiK74iLMaiLF4iJXIhFEABIn6BLiqiF+pAFkYiKtziFQzjEhRjMQ4jMiajMi4jMzajMz4jNEajNE4jNVajNV4jNmajNm4jN3ajN34jOIajOIqjMZajLq4gL+ofPAziKQQjIq7dOcajPM4jPdajPd4lIz7moz7uIz/2oz/+I0AGpEAOJEEWpEEeJEImpEIuJD+mo0MGBAA7

    toplevel     $top
    wm withdraw  $top
    wm title     $top "InstallJammer Multi-Platform Installer"
    wm override  $top 1
    wm resizable $top 0 0
    CenterWindow $top 500 303
    
    set c [canvas $top.c -width 500 -height 303 -highlightthickness 0]
    pack $c

    $c create image 0 0 -anchor nw -image ::icon::splash

    set text "Version $conf(Version)\n(Build $conf(BuildVersion))"
    $c create text 490 125 -text $text -fill #FFFFFF -font TkTextFont -anchor ne
    set widg(SplashText) [$c create text 12 278 -anchor nw -fill #FFFFFF \
        -font TkTextFont]

    ::InstallJammer::FadeWindowIn $top
}

proc CenterWindow { target {w 473} {h 335} {lower 0} } {
    update
    if {$w == 0} { set w [winfo reqwidth $target] }
    if {$h == 0} { set h [winfo reqheight $target] }
    set sw [winfo screenwidth $target]
    set sh [winfo screenheight $target]
    set x0 [expr ([winfo screenwidth $target] - $w)/2 - [winfo vrootx $target]]
    set y0 [expr ([winfo screenheight $target] - $h)/2 - [winfo vrooty $target]]
    set x "+$x0"
    set y "+$y0"
    if { $x0+$w > $sw } {set x "-0"; set x0 [expr {$sw-$w}]}
    if { $x0 < 0 }      {set x "+0"}
    if { $y0+$h > $sh } {set y "-0"; set y0 [expr {$sh-$h}]}
    if { $y0 < 0 }      {set y "+0"}

    if {$lower} { set y +[expr [lindex [wm maxsize .] 1] - 200] }

    wm geometry $target $x$y
    update
}
Added lib/themes.tcl.




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::InstallJammer::ThemeDir { {file ""} } {
    global conf
    global info

    variable ::InstallJammer::themes

    ## See if the ThemeDir stored in the install is good.
    set dir $info(ThemeDir)
    if {[file pathtype $info(ThemeDir)] eq "relative"} {
        set dir [file join $conf(pwd) Themes $info(ThemeDir)]
    }

    if {![file exists $dir] && [info exists themes($info(Theme))]} {
        ## Grab the default directory for this theme.
        set dir $themes($info(Theme))
    }

    if {![file exists $dir]} {
        set name [join [split $info(Theme) _] " "]
        return -code error "Cannot find theme directory for $name theme"
    }

    if {[string length $file]} { set dir [file join $dir $file] }

    if {$conf(windows) && [file exists $dir]} {
        set dir [file attributes $dir -longname]
    }

    return $dir
}

proc ::InstallJammer::LoadThemeConfig { arrayName } {
    upvar 1 $arrayName array
    set themefile [::InstallJammer::ThemeDir theme.cfg]
    if {![file exists $themefile]} { return 0 }

    array set array [read_file $themefile]
    return 1
}

proc LoadTheme { args } {
    global conf
    global info
    global widg

    variable ::InstallJammer::theme
    variable ::InstallJammer::panes

    if {![::InstallJammer::LoadThemeConfig theme]} {
        ::InstallJammer::Error -message "Cannot find theme directory"
        return 0
    }

    if {[info exists theme(Width)]} {
        SafeSet info(WizardWidth) $theme(Width)
    }
    if {[info exists theme(Height)]} {
        SafeSet info(WizardHeight) $theme(Height)
    }

    set themedir [::InstallJammer::ThemeDir]

    set conf(ThemeDir) $themedir

    unset -nocomplain panes
    unset -nocomplain conf(PaneList,Install)
    unset -nocomplain conf(PaneList,Uninstall)

    ::InstallJammer::DeletePaneObjects

    ::InstallJammer::DeleteWindowProcs

    foreach setup $conf(ThemeDirs) {
        set directory [file join $themedir $setup]
        set ::InstallJammer::loadtheme::setup    $setup
        set ::InstallJammer::loadtheme::setupdir $setup
        
        foreach file [glob -nocomplain -directory $directory *.pane] {
            set ::InstallJammer::loadtheme::deffile $file
            set ::InstallJammer::loadtheme::tclfile [file root $file].tcl
            namespace eval ::InstallJammer::loadtheme [read_file $file]
        }

        set common [file join $themedir Common]
        foreach file [glob -nocomplain -directory $common *.pane] {
            set ::InstallJammer::loadtheme::setupdir Common
            set ::InstallJammer::loadtheme::deffile $file
            set ::InstallJammer::loadtheme::tclfile [file root $file].tcl
            namespace eval ::InstallJammer::loadtheme [read_file $file]
        }

        unset -nocomplain sort
        unset -nocomplain order
        foreach pane $conf(PaneList,$setup) {
            set obj $panes($pane)
            lappend sort([$obj order]) $pane
        }

        foreach i [lsort -real [array names sort]] {
            eval lappend order $sort($i)
        }

        set conf(PaneList,$setup) $order

        if {[info exists widg(${setup}PanesMenu)]} {
            $widg(${setup}PanesMenu) delete 0 end

            foreach pane $conf(PaneList,$setup) {
                set id    $panes($pane)
                set types [$id installtypes]
                if {[lsearch -exact $types "Common"] > -1} { continue }
                $widg(${setup}PanesMenu) add command -label [$id title] \
                    -command [list ::InstallJammer::AddPane $setup $pane]
            }
        }
    }

    set projectdir [file dirname $info(ProjectFile)]

    foreach dir [list $themedir $projectdir] {
        ::InstallJammer::LoadMessages -dir $dir

        set file [file join $dir theme.tcl]
        if {[file exists $file]} { uplevel #0 source [list $file] }

        foreach subdir $conf(ThemeSourceDirs) {
            set directory [file join $dir $subdir]

            set file [file join $directory defaults.tcl]
            if {[file exists $file]} { uplevel #0 source [list $file] }
        }
    }

    return 1
}

proc ::InstallJammer::loadtheme::Pane { name title {preview 1} } {
    global conf

    variable pane
    variable active
    variable tclfile
    variable deffile
    variable setup
    variable setupdir
    variable actioncount 0

    lappend conf(PaneList,$setup) $name

    set pane [::InstallJammer::Pane ::#auto \
        -title $title -name $name -parent Standard -preview $preview]

    $pane setup   $setupdir
    $pane deffile $deffile
    $pane tclfile $tclfile

    set active pane

    return $pane
}

proc ::InstallJammer::loadtheme::Window { name title {preview 1} } {
    set obj [::InstallJammer::loadtheme::Pane $name $title $preview]
    $obj property Toplevel hidden Toplevel Yes
}

proc ::InstallJammer::loadtheme::Property { name type pretty 
                                          {value ""} {choices ""} } {
    variable pane
    $pane property $name $type $pretty $value $choices
}

proc ::InstallJammer::loadtheme::Text { name {pretty ""} {subst 1} } {
    variable pane
    if {[lempty $pretty]} { set pretty $name }
    $pane text $name $pretty $subst
}

proc ::InstallJammer::loadtheme::Condition { name args } {
    variable pane
    variable active
    $pane condition $active $name $args
}

proc ::InstallJammer::loadtheme::File { filename } {
    variable pane
    $pane file $filename
}

proc ::InstallJammer::loadtheme::Help { property text } {
    variable pane
    $pane help $property $text
}

proc ::InstallJammer::loadtheme::InstallTypes { args } {
    variable pane
    $pane configure -installtypes $args
}

proc ::InstallJammer::loadtheme::Action { name args } {
    variable pane
    variable actioncount
    variable active action[incr0 actioncount]
    $pane action $name $args
}

proc ::InstallJammer::loadtheme::Order { order } {
    variable pane
    $pane configure -order $order
}

proc ::InstallJammer::loadtheme::Include { args } {
    variable pane
    eval $pane includes $args
}

proc ::InstallJammer::loadtheme::proc { name arguments body } {
    if {![string match "::*" $name]} { set name ::$name }
    ::proc $name $arguments $body
}

proc ThemeFiles { setup } {
    global conf
    set dir [file join $conf(ThemeDir) $setup]

    set files [list setup.tcl init.tcl main.tcl utils.tcl]

    set list [list]
    foreach file $files {
        set filename [file join $dir $file]
        if {[file exists $filename]} { lappend list $file }
    }

    return $list
}

proc ::InstallJammer::ThemeFile { setup filename } {
    set file [InstallDir Theme/$setup/$filename]
    if {[file exists $file]} { return $file }

    return [::InstallJammer::ThemeDir [file join $setup $filename]]
}

proc RestoreThemeWindows {} {
    global conf
    global info
    global widg

    Status "Restoring theme windows..."
    update idletasks

    set theme [file join $conf(pwd) Themes $info(Theme)]
    foreach setup $conf(ThemeDirs) {
	set windows [file join $theme $setup windows.tcl]
	if {![file exists $windows]} { return }
	file copy -force $windows $info(ProjectDir)
	namespace eval ::InstallJammer::preview [read_file $windows]
    }
    set item [$widg(DialogTree) selection get]
    if {![lempty $item]} { ::Dialogs::raise $item }
    Modified

    Status "Done restoring theme windows." 3000
    update idletasks
}

proc RestoreTheme { {option ""} } {
    global conf
    global info
    global widg

    if {$option != "-new"} {
	Status "Restoring original theme..."
	update idletasks
    }

    set ans no
    if {[string equal $option "-save"]} { set ans yes }
    if {[string equal $option "-prompt"]} {
	set parent $widg(InstallJammer)
	set ans [tk_messageBox -type yesnocancel \
	    -title "Restore Theme" -parent $parent -message \
	    "Do you want to keep your current settings for this install?"]
	if {[string equal $ans "cancel"]} { return }
    }
    set save [string equal $ans "yes"]

    set theme [file join $conf(pwd) Themes $info(Theme)]
    set info(ThemeDir) $theme

    foreach dir $conf(ThemeSourceDirs) {
	set projectdir [file join $info(ProjectDir) $dir]
	if {![file exists $projectdir]} { file mkdir $projectdir }

	foreach file [glob -nocomplain -types f [file join $theme $dir *]] {
	    file copy -force $file [file join $info(ProjectDir) $dir]
	}
    }

    if {!$save} {
        foreach dir $conf(ThemeDirs) {
            set dir [file join $info(ProjectDir) $dir]
            file delete -force [file join $dir windows.tcl]
            file delete -force [file join $dir defaults.tcl]
            foreach file [glob -nocomplain -dir $dir *.msg] {
                file delete -force $file
            }
        }
    }

    Modified

    if {![string equal $option "-noload"] && ![string equal $option "-new"]} {
	LoadTheme $info(ProjectDir)
    }

    if {![string equal $option "-new"]} {
	Status "Done restoring original theme." 3000
	update idletasks
    }
}

proc SaveTheme {} {
    global conf
    global info
    
    Status "Saving new theme..."
    update idletasks

    ClearTmpVars

    set top [::InstallJammer::TopName .__save_theme]

    toplevel     $top
    wm withdraw  $top
    update idletasks
    wm geometry  $top 240x100
    wm title     $top "Save New Theme"
    wm protocol  $top WM_DELETE_WINDOW "set ::TMP 0"
    wm resizable $top 0 0
    ::InstallJammer::CenterWindow $top 240 100

    set b [Buttons $top \
    	-okcmd "set ::TMP 1" \
    	-cancelcmd "set ::TMP 0" \
    	-helpcmd "Help SaveTheme"]

    pack [frame $top.sp1 -height 5]

    label $top.l -text "New Theme Name:"
    pack  $top.l -anchor w

    ENTRY $top.e -width 40 -textvariable ::TMPARRAY(theme)
    pack  $top.e -anchor w
    focus $top.e
    $top.e icursor end

    pack [frame $top.sp2 -height 20]

    bind $top <Key-Return> "$b.ok invoke"

    if {![::InstallComponents::Dialog $top]} { return }

    set theme [join $::TMPARRAY(theme) _]

    if {[lempty $theme]} { return }

    set themedir [file join $conf(pwd) Themes $theme]

    if {[file exists $themedir]} {
	tk_messageBox -title "Theme Exists" -message \
	    "That theme already exists."
	return
    }

    foreach setup $conf(ThemeDirs) {
	set dir [file join $themedir $setup]
	file mkdir $dir

	foreach file [ThemeFiles $setup] {
	    file copy [file join $info(ProjectDir) $setup $file] $dir	
	}
    }

    Status "Done saving new theme." 3000
    update idletasks
}

proc ::InstallJammer::ThemeList {} {
    global conf
    global preferences

    variable ::InstallJammer::themes

    if {![array exists themes]} {
        if {[string length $preferences(CustomThemeDir)]} {
            lappend dirs $preferences(CustomThemeDir)
        }
        lappend dirs [file join $conf(pwd) Themes]

        foreach dir $dirs {
            foreach themedir [glob -nocomplain -type d -dir $dir *] {
                set name [file tail $themedir]
                set file [file join $themedir theme.cfg]
                if {[file exists $file] && ![info exists themes($name)]} {
                    set themes($name) $themedir
                }
            }
        }

        if {![array exists themes]} {
            ::InstallJammer::MessageBox -title "No Themes" \
                -message "Could not locate any install themes!"
            ::exit
        }
    }

    return [lsort [array names themes]]
}

proc ::InstallJammer::DeletePaneObjects {} {
    eval ::itcl::delete object \
        [::itcl::find object -class ::InstallJammer::Pane]
}

proc ::InstallJammer::DeleteWindowProcs {} {
    foreach proc [info commands CreateWindow.*] {
        rename $proc ""
    }
}

proc ::InstallJammer::GetPaneSourceFile { id {ext .tcl} } {
    set setup [$id setup]

    set file [InstallDir Theme/$setup/$id$ext]
    if {[file exists $file]} { return $file }

    return [[$id object] tclfile]
}
Added lib/trees-component.tcl.




























































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

namespace eval ::ComponentTree {
    variable tree ""
    variable popup ""
}

proc ::ComponentTree::setup { tree } {
    $tree bindText  <Button-1>		"::ComponentTree::select 1"
    $tree bindImage <Button-1>		"::ComponentTree::select 1"
    $tree bindText  <ButtonRelease-1>	"::ComponentTree::dorename"
    $tree bindImage <ButtonRelease-1>	"::ComponentTree::dorename"
    $tree bindText  <Double-Button-1>	"::ComponentTree::select 2"
    $tree bindImage <Double-Button-1>	"::ComponentTree::select 2"
    $tree bindText  <Shift-Button-1>	"::ComponentTree::select 3"
    $tree bindImage <Shift-Button-1>	"::ComponentTree::select 3"
    $tree bindText  <Control-Button-1>	"::ComponentTree::select 4"
    $tree bindImage <Control-Button-1>	"::ComponentTree::select 4"

    $tree bindText  <Button-3>          "::ComponentTree::popup %X %Y"
    $tree bindImage <Button-3>          "::ComponentTree::popup %X %Y"

    ::FileTree::Setup $tree
}

proc ::ComponentTree::init {} {
    global widg
    variable tree $widg(ComponentTree)
    variable pref $widg(ComponentPref)

    ::ComponentTree::Clear

    $pref insert end root Components -text "My Product" -haspage 0 -open 1 \
        -data component -image [GetImage component16]
    
    foreach id [::ComponentTree::List] {
	set node [::ComponentTree::New -id $id]
    }
}

proc ::ComponentTree::Clear {} {
    global widg
    variable pref
    variable FileGroupIncludes

    if {![string length $pref]} { return }

    $pref selection clear

    eval [list $pref delete] [$pref nodes root]

    set tree $widg(ComponentFileGroupTree)
    eval $tree delete [$tree nodes root]
    unset -nocomplain FileGroupIncludes
}

proc ::ComponentTree::New { args } {
    global info
    global widg

    variable pref

    array set data {
        -id     ""
        -text   ""
    }
    array set data $args

    set id  $data(-id)
    set new 0
    if {![string length $id]} {
        set parent [$pref selection get]
        if {![string length $parent]} { set parent Components }

        set id   [::InstallJammer::uuid]
        set text $data(-text)

        Component ::$id -name $text -parent $parent

        if {![string length $text]} {
            set new 1
            set text "New Component"
            ::InstallJammer::EditNewNode $pref end $parent $id \
                -text $text -image [GetImage component16] -fill blue \
                -data component -pagewindow $widg(ComponentDetails) -open 1
            set text [$pref itemcget $id -text]
            $id configure -name $text
            focus [$pref gettree]
        }

        $id platforms [AllPlatforms]
    }

    set text   [$id name]
    set parent [$id parent]

    ::ComponentObject initialize $id Name $text

    if {!$new} {
        $pref insert end $parent $id -text $text \
            -image [GetImage component16] -data component \
            -pagewindow $widg(ComponentDetails) -open 1
    } else {
        ::ComponentTree::select 1 $id
    }

    if {[string equal $parent "Components"]} { set parent root }

    if {[$id is component]} {
        set tree $widg(SetupTypeComponentTree)
        $tree insert end $parent $id \
            -type checkbutton -open 1 -text $text \
            -variable ::SetupTypeTree::ComponentIncludes($id) \
            -command [list ::SetupTypeTree::SetComponentInclude $tree $id]
    }

    Modified

    return $id
}

proc ::ComponentTree::List { args } {
    return [Components children recursive]
}

proc ::ComponentTree::select {mode node} {
    global conf
    global info
    global widg

    variable tree

    after cancel $conf(renameAfterId)

    variable old [$tree selection get]

    if {$mode == 1} {
	$tree selection set $node

        ::ComponentTree::RaiseNode $node

        variable last $old
    }

    if {$mode == 2} {
	## It's a double-click.
	## If there is no data associated with the node, it's a platform
	## or component, so we need to open or close it.

        variable double 1
        after idle [list unset -nocomplain [namespace current]::double]

	$tree selection set $node

        $tree toggle $node

        ::ComponentTree::RaiseNode $node
    }

    if {$mode == 3 && [$tree parent $node] != "root"} {
	## They executed a shift-click.
	## If both nodes are not in the same parent node, ignore it.
	if {[lempty $old]} { return }
	set old [lindex $old 0]
	if {[$tree parent $node] != [$tree parent $old]} { return }
	set p [$tree parent $old]
	set first [$tree index $old]
	set last  [$tree index $node]	
	if {$last < $first} {
	    set items [$tree nodes $p $last $first]
	} else {
	    set items [$tree nodes $p $first $last]
	}

	eval $tree selection set $items
    }

    if {$mode == 4 && [$tree parent $node] != "root"} {
	## They executed a ctrl-click.
	if {[lsearch $old $node] > -1} {
	    $tree selection remove $node
	} else {
	    $tree selection add $node
	}
    }

    if {$mode == 5} {
	$tree selection set $node
    }
}

proc ::ComponentTree::dorename { node } {
    global conf

    variable old
    variable tree
    variable double

    after cancel $conf(renameAfterId)

    ## They're renaming the node.
    if {![info exists double] && $node eq $old && $node ne "Components"} {
        set text [$tree itemcget $node -text]
        set cmd  [list ::InstallJammer::Tree::DoRename $tree $node]
        set conf(renameAfterId) [after 800 [list $tree edit $node $text $cmd]]
        return
    }
}

proc ::ComponentTree::rename { id newtext } {
    global widg
    variable pref

    variable ::InstallJammer::active

    $id name $newtext
    $id set Name $newtext

    $widg(SetupTypeComponentTree) itemconfigure $id -text $newtext

    set active(Name) $newtext
}

proc ::ComponentTree::delete {} {
    global widg

    variable pref

    set ans [::InstallJammer::MessageBox -type yesno \
        -message "Are you sure you want to delete the selected components?"]
    if {$ans eq "no"} { return }

    set idlist [list]
    foreach id [$pref selection get] {
        if {![$pref exists $id]} { continue }

        if {$id eq "Components"} { continue }

        $pref delete $id
        $widg(SetupTypeComponentTree) delete $id
        $id destroy

        lappend idlist $id
    }

    if {[llength $idlist]} {
        foreach id [SetupTypes children] {
            set components [$id get Components]
            set components [eval [list lremove $components] $idlist]
            $id set Components $components
        }
        Modified
    }
}

proc ::ComponentTree::popup { X Y item } {
    variable tree
    variable popup

    focus $tree

    $popup post $X $Y
    if {$::tcl_platform(platform) == "unix"} { tkwait window $popup }
}

proc ::ComponentTree::RaiseNode { node } {
    global widg

    variable pref
    variable FileGroupIncludes

    if {[string equal $node "Components"]} { return }

    ## If this is the same node already raised, don't do anything
    if {[string equal [$pref raise] $node]} { return }

    $pref raise $node
    set id $node

    set tree $widg(ComponentFileGroupTree)

    set include [$id get FileGroups]
    foreach node [::InstallJammer::Tree::AllNodes $tree] {
        if {[lsearch -exact $include $node] > -1} {
            set FileGroupIncludes($node) 1
        } else {
            set FileGroupIncludes($node) 0
        }
    }

    ::InstallJammer::SetActiveComponent $id

    ::InstallJammer::SetupPlatformProperties $id $widg(ComponentDetailsProp)
}

proc ::ComponentTree::SetFileGroupInclude { tree node } {
    variable pref
    variable FileGroupIncludes

    set component [$pref raise]
    if {![string length $component]} { return }

    set include [list]
    foreach node [::InstallJammer::Tree::AllNodes $tree] {
        if {$FileGroupIncludes($node)} { lappend include $node }
    }

    $component set FileGroups $include

    if {$component eq $::InstallJammer::ActiveComponent} {
        set ::InstallJammer::active(FileGroups) $include
    }
}
Added lib/trees-filegroup.tcl.










































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

namespace eval ::FileGroupTree {
    variable old   ""
    variable tree  ""
    variable popup ""
}

proc ::FileGroupTree::setup { tree } {
    $tree configure \
        -opencmd  "::FileGroupTree::open  $tree" \
        -closecmd "::FileGroupTree::close $tree" \
        -selectcommand "::FileGroupTree::UpdateSelection"

    $tree bindText  <Button-1>		"::FileGroupTree::select 1"
    $tree bindImage <Button-1>		"::FileGroupTree::select 1"
    $tree bindText  <ButtonRelease-1>   "::FileGroupTree::dorename"
    $tree bindImage <ButtonRelease-1>   "::FileGroupTree::dorename"
    $tree bindText  <Double-Button-1>	"::FileGroupTree::select 2"
    $tree bindImage <Double-Button-1>	"::FileGroupTree::select 2"
    $tree bindText  <Shift-Button-1>	"::FileGroupTree::select 3"
    $tree bindImage <Shift-Button-1>	"::FileGroupTree::select 3"
    $tree bindText  <Control-Button-1>	"::FileGroupTree::select 4"
    $tree bindImage <Control-Button-1>	"::FileGroupTree::select 4"

    $tree bindText  <Button-3>          "::FileGroupTree::popup %X %Y"
    $tree bindImage <Button-3>          "::FileGroupTree::popup %X %Y"

    ::FileTree::Setup $tree
}

proc ::FileGroupTree::init {} {
    global widg

    variable tree $widg(FileGroupTree)
    variable pref $widg(FileGroupPref)

    ::FileGroupTree::Clear
}

proc ::FileGroupTree::Clear {} {
    global widg

    variable pref
    variable done

    if {![string length $pref]} { return }

    $pref selection clear

    eval [list $pref delete] [$pref nodes root]

    unset -nocomplain done
}

proc ::FileGroupTree::New { args } {
    global conf
    global info
    global widg

    variable pref

    array set data {
        -id        ""
        -text      ""
        -directory "<%InstallDir%>"
    }
    array set data $args

    set text $data(-text)
    set dest $data(-directory)

    set id  $data(-id)
    set new 0
    if {![string length $data(-id)]} {
        set id [::InstallJammer::uuid]

        FileGroup ::$id -name $text -parent FileGroups
        set node [::InstallJammer::NodeName $id]

        if {![string length $text]} {
            set new 1
            set text "New File Group"
            ::InstallJammer::EditNewNode $pref end root $node \
                -text $text -image [GetImage filegroup16] \
                -data $id -pagewindow $widg(FileGroupDetails)
            set text [$pref itemcget $node -text]
            $id configure -name $text
            focus [$pref gettree]
        }

        $id platforms [concat [AllPlatforms] $conf(Archives)]
    }

    set text [$id name]
    set node [::InstallJammer::NodeName $id]

    ::FileGroupObject initialize $id Name $text Destination $dest

    if {!$new} {
        $pref insert end root $node \
            -text $text -image [GetImage filegroup16] \
            -data $id -pagewindow $widg(FileGroupDetails)
    } else {
        ::FileGroupTree::select 1 $node
    }

    set tree $widg(ComponentFileGroupTree)
    $tree insert end root $id \
        -type checkbutton -text $text \
        -variable ::ComponentTree::FileGroupIncludes($id) \
        -command [list ::ComponentTree::SetFileGroupInclude $tree $id]

    Modified
    ::InstallJammer::FilesModified

    return $id
}

proc ::FileGroupTree::select { mode node } {
    global conf
    global info
    global widg

    variable old
    variable tree
    variable pref

    after cancel $conf(renameAfterId)

    ## Tree specific configurations.
    set p    [$tree parent $node]
    set id   [$tree itemcget $node -data]
    set text [$tree itemcget $node -text]
    set type [$id type]

    $widg(DeleteButton) configure -state normal

    if {[$id is filegroup]} {
        $widg(AddDirButton)   configure -state normal
        $widg(AddFilesButton) configure -state normal
    } else {
        $widg(AddDirButton)   configure -state disabled
        $widg(AddFilesButton) configure -state disabled
    }

    if {$mode == 1} {
	::FileGroupTree::selection set $node

        ::FileGroupTree::RaiseNode $node
    }

    if {$mode == 2} {
	## It's a double-click.  Open or close the node depending.

        variable double 1
        after idle [list unset -nocomplain [namespace current]::double]

	::FileGroupTree::selection set $node
        ::FileGroupTree::RaiseNode $node

        if {[$id is dir] || [$id is file]} {
            if {[$id active]} {
		Uncheck $node
	    } else {
		Check $node
	    }
	} else {
            $pref toggle $node
	}
    }

    if {$mode == 3} {
	## They executed a shift-click.

        set nodes [::InstallJammer::Tree::AllNodes $tree]

        set idx1 0
        if {[string length $old]} { set idx1 [lsearch -exact $nodes $old] }
        if {$idx1 < 0} { set idx1 0 }

        set idx2 [lsearch -exact $nodes $node]

        if {$idx2 < $idx1} {
            set x $idx1
            set idx1 $idx2
            set idx2 $x
        }

        set items [list]
        foreach n [lrange $nodes $idx1 $idx2] {
            if {[$tree visible $n]} { lappend items $n }
	}

	::FileGroupTree::selection set $items
    }

    if {$mode == 4} {
	## They executed a ctrl-click.
	if {[lsearch -exact [$tree selection get] $node] > -1} {
	    ::FileGroupTree::selection remove $node
	} else {
	    ::FileGroupTree::selection add $node
	}
    }
}

proc ::FileGroupTree::open { tree node } {
    global conf
    global info
    variable LinkDirs

    set id [$tree itemcget $node -data]

    ## Check to see if this node has already been opened.
    if {[$tree itemcget $node -drawcross] eq "auto"} { return }

    set found 0
    foreach child [$id children] {
        set found 1
        AddToFileGroup -id $child
    }

    set dir [::InstallJammer::GetFileSource $id]
    if {[file exists $dir]} {
        set topdir   [::FileGroupTree::GetTopDirectory $node]
        set platform [::FileTree::GetPlatform $tree $node]

        if {[file type $dir] eq "link"} {
            ## If we find a recursive link we only open the topmost
            ## directory link.  Going any deeper will just put us
            ## into an infinite loop, so we stop at one level deep.
            if {![info exists LinkDirs($topdir)]} { set LinkDirs($topdir) "" }
            set link [file tail $dir],[file normalize [file readlink $dir]]
            if {[lsearch -exact $LinkDirs($topdir) $link] > -1} {
                $tree itemconfigure $node -drawcross auto
                return
            }
            lappend LinkDirs($topdir) $link
        }

        set group [::FileGroupTree::GetFileGroup $node]
        set group [$tree itemcget $group -data]

        set filelist [glob -nocomplain -directory $dir *]
        eval lappend filelist [glob -nocomplain -type hidden -directory $dir *]

        foreach file $filelist {
            set found 1
            set type file
            set tail [file tail $file]
            if {[file isdir $file]} {
                if {$tail eq "." || $tail eq ".."} { continue }
                if {[::InstallJammer::IgnoreDir $file]} { continue }
                set type dir
            } else {
                if {[::InstallJammer::IgnoreFile $tail]} { continue }
            }

            AddToFileGroup -type $type -platform $platform -group $group \
                -name $file -text $tail -parent $id -modify 0
        }
    }

    if {$found} { ::FileGroupTree::SortNodes $node }
    $tree itemconfigure $node -drawcross auto
}

proc ::FileGroupTree::close { tree node } {
    #set id [$tree itemcget $node -data]
    #if {[$id type] eq "filegroup"} {
        #$tree itemconfigure $node -image [GetImage folder16]
    #}
}

proc ::FileGroupTree::dorename { node } {
    global conf

    variable old
    variable tree
    variable double

    after cancel $conf(renameAfterId)

    set type [[$tree itemcget $node -data] type]
    if {![info exists double] && $node eq $old && $type eq "filegroup"} {
        ## They clicked the same node again.  After a 1 second delay,
        ## edit the name of the node to rename it.
        set text [$tree itemcget $node -text]
        set cmd  [list ::InstallJammer::Tree::DoRename $tree $node]
        set conf(renameAfterId) [after 800 [list $tree edit $node $text $cmd]]
        return
    }

    set old $node
}

proc ::FileGroupTree::rename { node newtext } {
    global widg

    variable pref

    variable ::InstallJammer::active

    set id [$pref itemcget $node -data]

    $id name $newtext
    $id set Name $newtext

    $widg(ComponentFileGroupTree) itemconfigure $id -text $newtext

    set active(Name) $newtext
}

proc ::InstallJammer::DeleteFilesFromTree {objects} {
    global widg

    if {![info exists widg(FileGroupTree)]} { return }
    set tree $widg(FileGroupTree)

    set items {}
    foreach id $objects {
        set node [::InstallJammer::NodeName $id]
	if {[$tree exists $node]} { lappend items $node }
        if {[::InstallJammer::ObjExists $id]} { $id destroy }
    }

    if {[llength $items]} {
        eval $tree selection remove $items
        eval $tree delete $items
        ::InstallJammer::RebuildFileMap
        Modified
        ::InstallJammer::FilesModified
    }
}

proc ::FileGroupTree::delete { {selection ""} } {
    global widg

    variable tree

    if {![llength $selection]} { set selection [$tree selection get] }

    if {![llength $selection]} { return }

    set ans [::InstallJammer::MessageBox -type yesno -title "Delete Items" \
        -message "Are you sure you want to delete the selected items?"]

    if {$ans eq "no"} { return }

    set items  [list]
    set idlist [list]
    foreach i $selection {
	if {![$tree exists $i]} { continue }

	set id [$tree itemcget $i -data]

        switch -- [$id type] {
            "dir" - "file" {
                ## We only delete files and directories who are
                ## direct children of a file group.
                set file [::InstallJammer::GetFileSource $id]
                if {[[$id parent] is filegroup] || ![file exists $file]} {
                    lappend items $i
                    $id destroy
                }
            }

            "filegroup" {
                lappend items  $i
                lappend idlist $id
                $id destroy

                $widg(ComponentFileGroupTree) delete $id
            }
        }
    }

    if {[llength $items]} {
        eval $tree selection remove $items
        eval $tree delete $items
        ::InstallJammer::RebuildFileMap
        Modified
        ::InstallJammer::FilesModified
    }

    if {[llength $idlist]} { 
        foreach id [Components children recursive] {
            set filegroups [$id get FileGroups]
            set filegroups [eval [list lremove $filegroups] $idlist]
            $id set FileGroups $filegroups
        }
        Modified
        ::InstallJammer::FilesModified
    }
}

proc ::FileGroupTree::popup { args } {
    variable tree

    focus $tree

    if {![lempty $args]} { lassign $args X Y item }

    set sel [$tree selection get]

    if {[lsearch -exact $sel $item] < 0} {
	::FileGroupTree::select 1 $item
	set sel $item
    }

    if {[llength $sel] > 1} {
        set menu $::FileGroupTree::MultiPopup
    } elseif {[llength $sel] == 1} {
	set id [$tree itemcget $sel -data]

        if {[$id is filegroup]} {
	    set menu $::FileGroupTree::FileGroupPopup
        } else {
            if {[$id isfile]} {
                set menu $::FileGroupTree::FilePopup
            } else {
	        set menu $::FileGroupTree::DirectoryPopup
            }
	}
    }

    if {[info exists X]} {
	$menu post $X $Y

        if {[string equal $::tcl_platform(platform) "unix"]} {
            tkwait window $menu
        }
    }
}

proc ::FileGroupTree::selection { cmd items } {
    global conf
    global info
    global widg

    variable tree

    eval $tree selection $cmd $items
}

proc ::FileGroupTree::GetTopDirectory {node} {
    variable tree
    set id [$tree itemcget $node -data]
    foreach parent [$id parent recursive] {
        if {[$parent type] eq "dir"} { break }
    }
    return $parent
}

proc ::FileGroupTree::GetFileGroup {node} {
    variable tree

    set type [[$tree itemcget $node -data] type]
    while {![string equal $type "filegroup"]} {
        set node [$tree parent $node]
        set type [[$tree itemcget $node -data] type]
    }

    return $node
}

proc ::FileGroupTree::AddToProgramFolder {} {
    variable tree

    set items [$tree selection get]

    foreach i $items {
        set id [$tree itemcget $i -data]
        if {![$id is file]} { continue }
	set filename [$tree itemcget $i -text]
	set parent [$tree parent $i]
        set group  [$tree itemcget $parent -data]

	set file     [file tail $filename]
	set linkName [file root $file]
	set objPath  [::InstallJammer::GetFileDestination $id]

        set parent [::BuilderAPI::GetActionGroup -alias "Install Actions"]

        set act [::InstallJammer::AddAction Install \
            InstallProgramFolderShortcut \
            -parent $parent -title "$linkName Shortcut"]

        $act set FileName       "<%ShortAppName%>-program-[join $linkName {}]"
        $act set ShortcutName   $linkName
        $act set TargetFileName $objPath

        if {[string match "*.html" $file]} {
            $act set ShortcutType   "Link"
            $act set TargetFileName "file://$objPath"
        }
    }
}

proc ::FileGroupTree::AddToDesktop {} {
    variable tree

    set items [$tree selection get]

    foreach i $items {
        set id [$tree itemcget $i -data]
        if {![$id is file]} { continue }

	set parent   [$tree parent $i]
        set group    [$tree itemcget $parent -data]
	set filename [$tree itemcget $i -text]

	set file     [file tail $filename]
	set linkName [file root $file]
	set objPath  [::InstallJammer::GetFileDestination $id]

        set parent [::BuilderAPI::GetActionGroup -alias "Install Actions"]

        set act [::InstallJammer::AddAction Install InstallDesktopShortcut \
                -parent $parent -title "$linkName Shortcut"]

        $act set FileName       "<%ShortAppName%>-desktop-[join $linkName {}]"
        $act set ShortcutName   $linkName
        $act set TargetFileName $objPath

        if {[string match "*.html" $file]} {
            $act set ShortcutType   "Link"
            $act set TargetFileName "file://$objPath"
        }
    }
}

proc ::FileGroupTree::Check { {items ""} } {
    variable tree
    if {[lempty $items]} { set items [$tree selection get] }

    foreach i $items {
        if {![$tree exists $i]} { continue }
        set id [$tree itemcget $i -data]
        if {![$id is file] && ![$id is dir]} { continue }
        $id active 1
	set image folder16
        if {[$id is file]} { set image filedocument16 }
	$tree itemconfigure $i -image [GetImage check$image]
	Modified
        ::InstallJammer::FilesModified
    }

    ::FileGroupTree::UpdateDetails
}

proc ::FileGroupTree::Uncheck { {items ""} } {
    variable tree
    if {[lempty $items]} { set items [$tree selection get] }

    foreach i $items {
        if {![$tree exists $i]} { continue }
        set id [$tree itemcget $i -data]
        if {![$id is dir] && ![$id is file]} { continue }
        $id active 0
	set image folder16
        if {[$id is file]} { set image filedocument16 }
	$tree itemconfigure $i -image [GetImage $image]
	Modified
        ::InstallJammer::FilesModified
    }

    ::FileGroupTree::UpdateDetails
}

proc ::FileGroupTree::Explore {} {
    variable tree

    set initdir ""

    set i [$tree selection get]
    if {[llength $i] == 1} {
	set id [$tree itemcget $i -data]

	switch -- [$id type] {
	    "dir" {
		set initdir [::InstallJammer::GetFileSource $id]

	    }
	    "file" {
		set initdir [file dirname [::InstallJammer::GetFileSource $id]]
	    }
	}
    }

    if {$initdir ne "" && ![file exists $initdir]} {
        ::InstallJammer::Error -message "Could not locate directory '$initdir'"
        return
    }

    ::InstallJammer::Explore $initdir
}

proc ::FileGroupTree::SetupPermissionsArray { id } {
    variable permissions

    if {[$id is filegroup]} {
        set attrs [$id get Attributes]
        set perms [$id get Permissions]
    } else {
        set attrs [$id attributes]
        set perms [$id permissions]
    }

    set defaultw [expr ![string length $attrs]]
    set defaultu [expr ![string length $perms]]

    if {![$id is filegroup]} {
        set file [::InstallJammer::GetFileSource $id]

        if {$::conf(windows)} {
            if {![string length $attrs] && [file exists $file]} {
                array set tmp [file attributes $file]
                append attrs $tmp(-archive)  $tmp(-hidden)
                append attrs $tmp(-readonly) $tmp(-system)
            }
        } else {
            if {![string length $perms] && [file exists $file]} {
                set perms [file attributes $file -permissions]
            }
        }
    }

    set permissions(UseWindowsDefaultPermissions) $defaultw
    tag configure WindowsDetailsPermissions -state \
        [expr {$defaultw ? "disabled" : "normal"}]

    set permissions(UseUNIXDefaultPermissions) $defaultu
    tag configure UNIXDetailsPermissions -state \
        [expr {$defaultu ? "disabled" : "normal"}]

    ## Windows permissions are stored as XXXX for
    ## archive,hidden,readonly,system
    if {$attrs eq ""} { set attrs 0000 }
    lassign_array [split $attrs ""] permissions \
        PermArchive PermHidden PermReadonly PermSystem

    ## UNIX permissions.
    if {$perms eq ""} { set perms 000 }
    set Other [string index $perms end]
    set Group [string index $perms end-1]
    set User  [string index $perms end-2]

    foreach x [list User Group Other] {
        upvar 0 $x which
        set permissions(Perm${x}Execute) 0
        if {[expr $which & 1] == 1} {
            set permissions(Perm${x}Execute) 1
        }
        set permissions(Perm${x}Write) 0
        if {[expr $which & 2] == 2} {
            set permissions(Perm${x}Write) 1
        }
        set permissions(Perm${x}Read) 0
        if {[expr $which & 4] == 4} {
            set permissions(Perm${x}Read) 1
        }
    }
}

proc ::FileGroupTree::SetPermissions { arrayName {idlist ""} } {
    variable tree

    if {![string length $tree]} { return }

    if {![llength $idlist]} {
        set sel [$tree selection get]
        if {![llength $sel]} { return }
        foreach node $sel {
            lappend idlist [$tree itemcget $node -data]
        }
    }

    upvar #0 $arrayName array

    set attributes  ""
    set permissions ""
    if {!$array(UseWindowsDefaultPermissions)} {
        set    attributes $array(PermArchive)
        append attributes $array(PermHidden)
        append attributes $array(PermReadonly)
        append attributes $array(PermSystem)
    }

    if {!$array(UseUNIXDefaultPermissions)} {
        foreach x {User Group Other} {
            set tmp($x) 0

            if {$array(Perm${x}Execute)} {
                set tmp($x) [expr $tmp($x) | 1]
            }
            if {$array(Perm${x}Write)} {
                set tmp($x) [expr $tmp($x) | 2]
            }
            if {$array(Perm${x}Read)} {
                set tmp($x) [expr $tmp($x) | 4]
            }
        }

        set permissions 00$tmp(User)$tmp(Group)$tmp(Other)
    }

    foreach id $idlist {
        if {$id eq [::InstallJammer::GetActiveComponent]} {
            set ::InstallJammer::active(Attributes)  $attributes
            set ::InstallJammer::active(Permissions) $permissions
        }

        if {[$id is filegroup]} {
            $id set Permissions $permissions Attributes $attributes
        } else {
            $id configure -permissions $permissions -attributes $attributes
        }
    }

    if {[llength $idlist]} {
        Modified
        ::InstallJammer::FilesModified
    }
}

proc ::FileGroupTree::GetSelectedItems {} {
    variable tree
    set ids [list]
    foreach node [$tree selection get] {
        lappend ids [$tree itemcget $node -data]
    }
    return $ids
}

proc ::FileGroupTree::UpdateSelectedItems { args } {
    variable tree

    foreach id [::FileGroupTree::GetSelectedItems] {
        foreach {property value} $args {
            if {[$id is filegroup]} {
                $id set $property $value
            } else {
                switch -- $property {
                    "Active" {
                        if {$value} {
                            lappend check [::InstallJammer::NodeName $id]
                        } else {
                            lappend uncheck [::InstallJammer::NodeName $id]
                        }
                        continue
                    }

                    "Destination" {
                        set property directory
                    }

                    "FileUpdateMethod" {
                        set property filemethod
                    }

                    "Location" {
                        ## Location is set in a popup dialog.
                        ## Since Location is only set on single objects,
                        ## we can just return instead of continuing on
                        ## to the next object.
                        return
                    }

                    default {
                        set property [string tolower $property]
                    }
                }

                $id $property $value
            }
        }

        Modified
        ::InstallJammer::FilesModified
    }

    if {[info exists check]} { ::FileGroupTree::Check $check }
    if {[info exists uncheck]} { ::FileGroupTree::Uncheck $uncheck }

    ::FileGroupTree::UpdateDetails
}

proc ::FileGroupTree::UpdateSelection { tree nodes } {
    if {[llength $nodes] > 1} {
        global widg

        variable details

        ## Clear the active component.
        ::InstallJammer::SetActiveComponent

        set prop $widg(FileGroupDetailsProp)

        foreach node [$prop nodes root] {
            $prop itemconfigure $node -state hidden
        }

        $prop itemconfigure permissions -state normal
        $prop itemconfigure multiplefiles -state normal

        set details(Active)            ""
        set details(Destination)       ""
        set details(CompressionMethod) ""
        set details(FileUpdateMethod)  ""
        set details(Location)          ""
        set details(Version)           ""
        set details(SaveFiles)         ""
    }
}

proc ::FileGroupTree::UpdateDetails {} {
    global info

    variable tree
    variable details

    set sel [$tree selection get]

    if {[llength $sel] == 1} {
        set id [$tree itemcget [lindex $sel 0] -data]

        set details(Active)  [expr {[$id active] ? "Yes" : "No"}]
        set details(Comment) [$id comment]

        if {[$id is dir file]} {
            array set details {
                name              ""
                location          ""
                fileSize          ""
                fileGroup         ""
                installLocation   ""
                fileMethod        ""
                fileVersion       ""
                created           ""
                modified          ""
                accessed          ""
                compressionMethod ""
            }

            set file  [::InstallJammer::GetFileSource $id]

            set details(name)      [file tail $file]
            set details(location)  [file dirname $file]
            set details(fileGroup) [[$id group] name]

            if {[::InstallJammer::GetFileActive $id]} {
                set details(installLocation) \
                    [::InstallJammer::GetFileDestination $id]
            } else {
                set details(installLocation) "Inactive (will not be installed)"
            }

            set details(fileMethod)  [::InstallJammer::GetFileMethod $id]
            set details(fileVersion) [::InstallJammer::GetFileVersion $id]
            if {![string length $details(fileVersion)]} {
                set details(fileVersion) $info(InstallVersion)
            }

            set details(compressionMethod) \
                [::InstallJammer::GetFileCompressionMethod $id]

            set details(Location) [$id location]
            if {[info exists ::InstallJammer::Locations($id)]} {
                set details(Location) $::InstallJammer::Locations($id)
            }

            if {![file exists $file]} {
                set details(fileSize) "(file not found)"
                set details(created)  "(file not found)"
                set details(modified) "(file not found)"
                set details(accessed) "(file not found)"
            } else {
                file stat $file stats
                set fsize [::InstallJammer::FormatDiskSpace $stats(size)]

                ## Setup file details
                set fmt "%A, %B %d, %Y %H:%M:%S %p"
                set details(fileSize) "$fsize ($stats(size) bytes)"
                set details(created)  [clock format $stats(ctime) -format $fmt]
                set details(modified) [clock format $stats(mtime) -format $fmt]
                set details(accessed) [clock format $stats(atime) -format $fmt]
            }
        }
    }
}

proc ::FileGroupTree::RaiseNode { node } {
    global widg

    variable tree
    variable pref
    variable details
    variable ActiveFile

    set prop $widg(FileGroupDetailsProp)

    set id [$tree itemcget $node -data]

    set ActiveFile $id

    foreach n [list dir file] {
        if {[$id is $n]} {
            $prop itemconfigure $n -state normal
        } else {
            $prop itemconfigure $n -state hidden
        }
    }
    $prop itemconfigure multiplefiles -state hidden

    if {[$id is filegroup]} {
        ::InstallJammer::SetHelp GroupsAndFiles

        $prop itemconfigure standard  -state normal
        $prop itemconfigure platforms -state normal

        $prop itemconfigure filestandard -state hidden

        ::InstallJammer::SetActiveComponent $id

        ::InstallJammer::SetupPlatformProperties $id $prop
    } else {
        ## Hide the File Group tables.
        $prop itemconfigure standard  -state hidden
        $prop itemconfigure platforms -state hidden

        ## Show the file standard properties.
        $prop itemconfigure filestandard -state normal

        ## Walk the properties and disable the Target Filename
        ## property if the given id is a directory.  Directories
        ## use Destination Directory as their install location.
        set type [$id type]
        foreach subnode [$prop nodes filestandard] {
            set data   [$prop itemcget $subnode -data]
            set parent [$id parent]

            if {$data eq "TargetFilename" && $type eq "dir"} {
                $prop itemconfigure $subnode -state hidden
                continue
            }

            if {$data eq "SaveFiles" && $type eq "file"} {
                $prop itemconfigure $subnode -state hidden
                continue
            }

            $prop itemconfigure $subnode -state normal
        }

        ## Setup Standard Properties
        set details(ID)                $id
        set details(Active)            [expr {[$id active] ? "Yes" : "No"}]
        set details(Alias)             [$id alias]
        set details(Comment)           [$id get Comment]
        set details(Destination)       [$id directory]
        set details(DisplayName)       [$id get DisplayName]
        set details(TargetFilename)    [$id targetfilename]
        set details(FileUpdateMethod)  [$id filemethod]
        set details(CompressionMethod) [$id compressionmethod]
        set details(Version)           [$id version]
        set details(SaveFiles)         [$id savefiles]

        ::FileGroupTree::UpdateDetails
        ::InstallJammer::SetHelp FilesAndDirectories
    }

    ::FileGroupTree::SetupPermissionsArray $id

    $pref raise $node
}

proc ::FileGroupTree::SortNodes { groupNode } {
    variable tree

    set dirs  [list]
    set files [list]
    foreach node [$tree nodes $groupNode] {
        set id   [$tree itemcget $node -data]
        set text [$tree itemcget $node -text]
        if {[$id is dir]} {
            lappend dirs [list $text $node]
        } else {
            lappend files [list $text $node]
        }
    }

    set nodes [list]
    foreach list [lsort -dict -index 0 $dirs] {
        lappend nodes [lindex $list 1]
    }

    foreach list [lsort -dict -index 0 $files] {
        lappend nodes [lindex $list 1]
    }

    $tree reorder $groupNode $nodes
}

proc ::InstallJammer::FilterFile { file args } {
    array set opts {
	-include	""
	-exclude	""
	-defaultaction	1
	-regexp		0
    }

    array set opts $args

    set matchInclude 0
    set matchExclude 0
    foreach pattern $opts(-include) {
	if {$opts(-regexp)} {
	    set res [regexp $pattern $file]
	} else {
	    set res [string match $pattern $file]
	}

	if {$res} {
	    set matchInclude 1
	    if {$opts(-defaultaction)} { return 1 }
	}
    }

    foreach pattern $opts(-exclude) {
	if {$opts(-regexp)} {
	    set res [regexp $pattern $file]
	} else {
	    set res [string match $pattern $file]
	}
	if {$res} {
	    set matchExclude 1
	    if {!$opts(-defaultaction)} { return 0 }
	}
    }

    if {$matchInclude} { return 1 }
    if {$matchExclude} { return 0 }
    return -1
}

proc ::InstallJammer::FilterFileGroups { args } {
    global info
    global widg

    set tree $widg(FileGroupTree)

    array set opts {
	-nodes		"all"
	-regexp		0
	-include	""
	-exclude	""
	-recursive      1
	-defaultaction	"include"
    }

    array set opts $args

    set act [string equal $opts(-defaultaction) "include"]
    lappend filterArgs -regexp  $opts(-regexp)
    lappend filterArgs -include $opts(-include)
    lappend filterArgs -exclude $opts(-exclude)
    lappend filterArgs -defaultaction $act

    if {[string equal $opts(-nodes) "all"]} {
        set opts(-nodes) [$tree nodes root]
    }

    ::InstallJammer::RefreshFileGroups

    Status "Filtering file groups..."

    set ids [list]
    foreach node $opts(-nodes) {
        set id [$tree itemcget $node -data]

        if {$opts(-recursive)} {
            eval lappend ids $id [$id children recursive]
        }
    }

    foreach id $ids {
        if {[$id is filegroup]} { continue }

        set file [::InstallJammer::GetFileSource $id]
        set res  [eval [list FilterFile $file] $filterArgs]

        if {$res < 0} { continue }

        set node [::InstallJammer::NodeName $id]

        $id active $res
        Modified
        ::InstallJammer::FilesModified

        if {$res == 0} {
            ::FileGroupTree::Uncheck $node
        } elseif {$res == 1} {
            ::FileGroupTree::Check   $node
        }
    }

    ClearStatus
}

proc ::InstallJammer::GetFileSource { id {subst 1} } {
    global info

    variable Locations

    set name     [$id srcfilename]
    set parent   [$id parent]
    set location [$id location]

    if {[info exists Locations($id)]} {
        set location $Locations($id)
    }

    if {$location ne ""} {
        if {[$id is dir]} {
            set dir $location
        } else {
            set dir [file join $location $name]
        }
    } elseif {[$parent is filegroup]} {
        ## If we reach the file group before we've found
        ## a working directory, just return the original
        ## filename.
        if {$info(DefaultDirectoryLocation) eq ""} {
            set dir [$id name]
        } else {
            set dir $info(DefaultDirectoryLocation)
        }
    } else {
        set dir [file join [::InstallJammer::GetFileSource $parent] $name]
    }

    if {$subst} { set dir [::InstallJammer::SubstText $dir] }

    if {[file pathtype $dir] eq "relative"} {
        set dir [file join $info(ProjectDir) $dir]
    }

    return [file normalize $dir]
}

proc ::InstallJammer::GetFileDestination { id } {
    set dir    [$id destdirname]
    set name   [$id destfilename]
    set parent [$id parent]

    if {$dir ne ""} {
        set dest $dir
        if {[$id isfile]} { set dest [file join $dir $name] }
    } elseif {[$parent is filegroup]} {
        set dir [$parent destdirname]
        if {$dir eq ""} { set dir "<%InstallDir%>" }
        set dest [file join $dir $name]
    } else {
        set dest [file join [::InstallJammer::GetFileDestination $parent] $name]
    }

    return $dest
}

proc ::InstallJammer::GetFileActive { id } {
    if {![$id active]} { return 0 }
    foreach parent [lreverse [lrange [$id parent recursive] 1 end]] {
        if {![$parent active]} { return 0 }
    }
    return 1
}

proc ::InstallJammer::GetFileVersion { id } {
    if {[string length [$id version]]} { return [$id version] }
    foreach parent [lreverse [lrange [$id parent recursive] 1 end]] {
        if {[string length [$parent version]]} { return [$parent version] }
    }
}

proc ::InstallJammer::GetFileMethod { id {map 0} } {
    set method [$id filemethod]
    if {$method eq ""} {
        foreach parent [lreverse [lrange [$id parent recursive] 1 end]] {
            set method [$parent filemethod]
            if {$method ne ""} { break }
        }
    }
    if {$map} {
        variable ::InstallJammer::PropertyMap
        set method [lsearch -exact $PropertyMap(FileUpdateMethod) $method]
    }
    return $method
}

proc ::InstallJammer::GetFileCompressionMethod { id } {
    global info

    if {[$id compressionmethod] ne ""} { return [$id compressionmethod] }

    foreach parent [lreverse [lrange [$id parent recursive] 1 end]] {
        set method [$parent compressionmethod]
        if {$method ne ""} { return $method }
    }

    return $info(CompressionMethod)
}

proc ::InstallJammer::EditLocation { id } {
    global widg

    if {![::InstallJammer::ObjExists $id]} {
        set id $::FileGroupTree::ActiveFile
    }

    ClearTmpVars

    set ::TMP(projectLocation) [$id location]

    set ::TMP(preferenceLocation) ""
    if {[info exists ::InstallJammer::Locations($id)]} {
        set ::TMP(preferenceLocation) $::InstallJammer::Locations($id)
    }

    set top [::InstallJammer::TopName .__setLocation]
    Dialog .__setLocation -title "Set Location" -geometry "400x150" \
        -applybutton 0

    set frame [$top getframe]

    grid rowconfigure    $frame 4 -weight 1
    grid columnconfigure $frame 0 -weight 1

    ttk::label $frame.projectL -text "Location in Project File"
    grid $frame.projectL -row 0 -column 0 -sticky nw -padx 2

    ttk::entry $frame.project -textvariable ::TMP(projectLocation)
    grid $frame.project -row 1 -column 0 -sticky new -padx {2 0}

    focus $frame.project

    ttk::button $frame.projectB -style Toolbutton -text "..." \
        -takefocus 0 -command [list GetDir ::TMP(projectLocation)]
    grid $frame.projectB -row 1 -column 1

    ttk::label $frame.preferenceL -text "Location in Local Preferences"
    grid $frame.preferenceL -row 2 -column 0 -sticky nw -padx 2 -pady {5 0}

    ttk::entry $frame.preference -textvariable ::TMP(preferenceLocation)
    grid $frame.preference -row 3 -column 0 -sticky new -padx {2 0}

    ttk::button $frame.preferenceB -style Toolbutton -text "..." \
        -takefocus 0 -command [list GetDir ::TMP(preferenceLocation)]
    grid $frame.preferenceB -row 3 -column 1

    set res [$top draw]

    if {$res eq "ok"} {
        ::InstallJammer::SetLocation $id \
            $::TMP(projectLocation) $::TMP(preferenceLocation)
    }

    destroy $top
}

proc ::InstallJammer::SetLocation { id projectLocation preferenceLocation } {
    global widg

    if {![::InstallJammer::ObjExists $id]} {
        set id $::FileGroupTree::ActiveFile
    }

    $id location $projectLocation

    if {$preferenceLocation eq ""} {
        unset -nocomplain ::InstallJammer::Locations($id)
    } else {
        set ::InstallJammer::Locations($id) $preferenceLocation
    }

    ::FileGroupTree::UpdateDetails

    set node [::InstallJammer::NodeName $id]

    if {[$widg(FileGroupTree) exists $node]} {
        set file [::InstallJammer::GetFileSource $id]
        set fill SystemWindowText
        if {![file exists $file]} { set fill SystemDisabledText }
        $widg(FileGroupTree) itemconfigure $node -fill $fill

        if {![$id isfile]} {
            eval $widg(FileGroupTree) delete [$widg(FileGroupTree) nodes $node]
            $widg(FileGroupTree) itemconfigure $node -drawcross allways
            ::FileGroupTree::open $widg(FileGroupTree) $node
        }
    }

    ::InstallJammer::RebuildLocations
}

proc ::InstallJammer::GetFileNodeColor { id } {
    set file [::InstallJammer::GetFileSource $id]
    set tail [file tail $file]

    if {$::conf(windows)} { set tail [string tolower $tail] }

    set fill SystemWindowText

    if {[info exists ::InstallJammer::NewFiles([$id parent],$tail)]} {
        set fill blue
    }

    if {![file exists $file]} {
        set fill SystemDisabledText
    }

    return $fill
}

proc ::InstallJammer::RedrawFileTreeNodes { {node root} } {
    global conf
    global widg

    set tree $widg(FileGroupTree)

    foreach node [$tree nodes $node] {
        set id [$tree itemcget $node -data]

        if {![$id is filegroup]} {
            $tree itemconfigure $node \
                -fill [::InstallJammer::GetFileNodeColor $id]
        }

        if {![$id is file]} {
            ::InstallJammer::RedrawFileTreeNodes $node
        }
    }
}
Added lib/trees-setuptype.tcl.




































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

namespace eval ::SetupTypeTree {
    variable tree  ""
    variable popup ""
}

proc ::SetupTypeTree::setup { tree } {
    $tree bindText  <Button-1>        "::SetupTypeTree::select 1"
    $tree bindImage <Button-1>        "::SetupTypeTree::select 1"
    $tree bindText  <ButtonRelease-1> "::SetupTypeTree::dorename"
    $tree bindImage <ButtonRelease-1> "::SetupTypeTree::dorename"
    $tree bindText  <Button-3>        "::SetupTypeTree::popup %X %Y"
    $tree bindImage <Button-3>        "::SetupTypeTree::popup %X %Y"

    ::FileTree::Setup $tree
}

proc ::SetupTypeTree::init {} {
    global widg

    variable tree $widg(SetupTypeTree)
    variable pref $widg(SetupTypePref)

    ::SetupTypeTree::Clear

    foreach id [SetupTypes children] {
	set node [::SetupTypeTree::New -id $id]
    }
}

proc ::SetupTypeTree::Clear {} {
    global widg

    variable pref
    variable ComponentIncludes

    if {![string length $pref]} { return }

    $pref selection clear

    eval $pref delete [$pref nodes root]

    set tree $widg(SetupTypeComponentTree)
    eval [list $tree delete] [$tree nodes root]
    unset -nocomplain ComponentIncludes
}

proc ::SetupTypeTree::New { args } {
    global info
    global widg

    variable pref

    array set data {
        -id     ""
        -text   ""
    }
    array set data $args

    set id  $data(-id)
    set new 0
    if {![string length $id]} {
        set id   [::InstallJammer::uuid]
        set text $data(-text)

        SetupType ::$id -name $text -parent SetupTypes

        if {![string length $text]} {
            set new  1
            set text "New Setup Type"
            ::InstallJammer::EditNewNode $pref end root $id \
                -text $text -image [GetImage setuptype16] -fill blue \
                -data setuptype -pagewindow $widg(SetupTypeDetails)
            set text [$pref itemcget $id -text]
            $id configure -name $text
            focus [$pref gettree]
        }

        $id platforms [AllPlatforms]
    } else {
        set text [$id name]
    }

    ::SetupTypeObject initialize $id Name $text

    if {!$new} {
        $pref insert end root $id -text $text -image [GetImage setuptype16] \
            -data setuptype -pagewindow $widg(SetupTypeDetails)
    } else {
        ::SetupTypeTree::select 1 $id
    }

    Modified

    return $id
}

proc ::SetupTypeTree::select { mode node } {
    global conf
    global info
    global widg

    variable tree
    variable pref

    after cancel $conf(renameAfterId)

    variable old [$tree selection get]

    $tree selection set $node
    ::SetupTypeTree::RaiseNode $node
}

proc ::SetupTypeTree::dorename { node } {
    variable old
    variable tree

    if {$node eq $old} {
        ## They're renaming the node.
        set text [$tree itemcget $node -text]
        set cmd  [list ::InstallJammer::Tree::DoRename $tree $node]
        set conf(renameAfterId) [after 800 [list $tree edit $node $text $cmd]]
        return
    }
}

proc ::SetupTypeTree::rename { id newtext } {
    variable tree
    variable ::InstallJammer::active

    $id name $newtext
    $id set Name $newtext

    set active(Name) $newtext
}

proc ::SetupTypeTree::delete {} {
    variable pref

    set ans [::InstallJammer::MessageBox -type yesno \
        -message "Are you sure you want to delete the selected setup types?"]
    if {$ans eq "no"} { return }

    foreach id [$pref selection get] {
        if {[$pref exists $id]} {
            $pref delete $id
            $id destroy
        }
    }
}

proc ::SetupTypeTree::popup { X Y item } {
    variable tree
    variable popup

    focus $tree

    $popup post $X $Y
    if {$::tcl_platform(platform) eq "unix"} { tkwait window $popup }
}

proc ::SetupTypeTree::RaiseNode { node } {
    global widg

    variable pref
    variable ComponentIncludes

    $pref raise $node
    set id $node

    set tree $widg(SetupTypeComponentTree)

    set include [$id get Components]
    foreach node [::InstallJammer::Tree::AllNodes $tree] {
        if {[lsearch -exact $include $node] > -1} {
            set ComponentIncludes($node) 1
        } else {
            set ComponentIncludes($node) 0
        }
    }

    ::InstallJammer::SetActiveComponent $id

    ::InstallJammer::SetupPlatformProperties $id $widg(SetupTypeDetailsProp)
}

proc ::SetupTypeTree::SetComponentInclude { tree node } {
    variable pref
    variable ComponentIncludes

    set setuptype [$pref raise]
    if {![string length $setuptype]} { return }

    set include [list]
    foreach node [::InstallJammer::Tree::AllNodes $tree] {
        if {$ComponentIncludes($node)} { lappend include $node }
    }

    $setuptype set Components $include

    if {$setuptype eq $::InstallJammer::ActiveComponent} {
        set ::InstallJammer::active(Components) $include
    }
}
Added lib/trees.tcl.






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

namespace eval ::Tree {}
namespace eval ::FileTree {}
namespace eval ::InstallJammer::Tree {}

proc InitComponentTrees {} {
    ::SetupTypeTree::init
    ::ComponentTree::init
    ::FileGroupTree::init
}

proc ClearComponentTrees {} {
    ::SetupTypeTree::Clear
    ::ComponentTree::Clear
    ::FileGroupTree::Clear

    unset -nocomplain ::InstallJammer::Tree::select
}

proc ::FileTree::Setup { tree } {
    set canvas [$tree getcanvas]
    bind $canvas <F2>     [list ::InstallJammer::Tree::Rename $tree]
    bind $canvas <Delete> [list ::InstallJammer::Tree::Delete $tree]
}

proc ::FileTree::GetPlatform {tree node} {
    set a $node
    set p [$tree parent $node]
    while { $p != "root" } {
	set a $p
	set p [$tree parent $p]
    }
    return $a
}

proc ::FileTree::SelectAll {tree} {
    foreach platform [$tree nodes root] {
	SelectAllPlatform $tree $platform
    }
}

proc ::FileTree::SelectAllPlatform {tree {platform ""}} {
    if {[lempty $platform]} {
    	set platform [$tree selection get]
    }
    foreach item [$tree nodes $platform] {
	SelectAllBeneath $tree $item
    }
}

proc ::FileTree::SelectAllBeneath {tree {node ""}} {
    if {[lempty $node]} { set node [$tree selection get] }
    $tree selection add $node
    foreach item [$tree nodes $node] {
	$tree selection add $item
    }
}

proc ::FileTree::Check { tree {types ""} } {
    set sel [$tree selection get]

    foreach i $sel {
	set data [$tree itemcget $i -data]
	set type [lindex $data 0]
	if {$type == "platform"} { continue }
	if {[lsearch $types $type] > -1} { continue }
	upvar #0 $data var
	if {![info exists var]} { continue }
	set var 1
	$tree itemconfigure $i -image [GetImage checkfolder16]
	Modified
    }
}

proc ::FileTree::Uncheck {tree {types ""}} {
    set sel [$tree selection get]

    foreach i $sel {
	set data [$tree itemcget $i -data]
	set type [lindex $data 0]
	if {$type == "platform"} { continue }
	if {[lsearch $types $type] > -1} { continue }
	upvar #0 $data var
	if {![info exists var]} { continue }
	set var 0
	$tree itemconfigure $i -image [GetImage folder16]
	Modified
    }
}

proc ::Tree::DropFiles { tree files } {
    set node [lindex [$tree selection get] 0]
    if {$node eq ""} { return }

    set id [$tree itemcget $node -data]
    if {[$id type] eq "filegroup"} {
        AddFiles -files [lsort $files]
    }
}

proc ::Tree::DragFiles { tree x y } {
    variable drag

    set node [$tree find @$x,$y]

    if {[info exists drag(node)] && ![string equal $drag(node) $node]} {
        after cancel $drag($drag(node))
    }

    if {[string length $node] && 
        (![info exists drag(node)] || ![string equal $drag(node) $node])} {
        set drag(node)  $node
        set drag($node) [after 500 [list $tree opentree $drag(node) 0]]
        set id [$tree itemcget $drag(node) -data]
        if {[$id type] eq "filegroup"} {
	    $tree selection set $drag(node)
	}
    }
    return default
}

proc ::InstallJammer::EditNewNode { widget args } {
    set node [eval $widget insert $args]
    $widget edit $node [$widget itemcget $node -text] \
        [list ::InstallJammer::FinishEditNewNode $widget $node]
    return $node
}

proc ::InstallJammer::FinishEditNewNode { widget node newtext } {
    if {[string equal [$widget itemcget $node -data] "actiongroup"]} {
        set n [::InstallJammer::FindActionGroup $widget $newtext]
        if {![lempty $n] && $n != $node} {
            ::InstallJammer::Error \
                -message "An Action Group with that name already exists."
            return 0
        }
    }

    $widget itemconfigure $node -text $newtext
    return 1
}

proc ::InstallJammer::Tree::AllNodes { tree {parent root} } {
    set nodes [list]
    foreach node [$tree nodes $parent] {
        lappend nodes $node
        eval lappend nodes [AllNodes $tree $node]
    }
    return $nodes
}

proc ::InstallJammer::Tree::Setup { setup tree } {
    global conf

    set canv [$tree getcanvas]

    $tree bindText  <ButtonRelease-1> \
        [list ::InstallJammer::Tree::SelectItem $tree]
    $tree bindImage <ButtonRelease-1> ::InstallJammer::SetActiveComponent

    $tree bindText  <Shift-1>   [list ::InstallJammer::Tree::SelectItem $tree 3]
    $tree bindImage <Shift-1>   [list ::InstallJammer::Tree::SelectItem $tree 3]
    $tree bindText  <Control-1> [list ::InstallJammer::Tree::SelectItem $tree 4]
    $tree bindImage <Control-1> [list ::InstallJammer::Tree::SelectItem $tree 4]

    $tree bindText  <Double-1>  [list ::InstallJammer::Tree::Toggle $tree]
    $tree bindImage <Double-1>  [list ::InstallJammer::Tree::Toggle $tree]

    set command [list ::InstallJammer::Tree::Popup $setup $tree %X %Y]
    $tree bindText  <Button-3> $command
    $tree bindImage <Button-3> $command

    bind $canv <F2>     [list ::InstallJammer::Tree::Rename $tree]
    bind $canv <Delete> [list ::InstallJammer::Tree::Delete $tree]

    set rc [MENU $tree.installtypeRightClick]
    $rc insert end command -label "Copy" \
        -compound left -image [GetImage editcopy16] \
        -command ::InstallJammer::EditCopy
    $rc insert end command -label "Paste" \
        -compound left -image [GetImage editpaste16] \
        -command ::InstallJammer::EditPaste
    $rc insert end separator
    $rc insert end cascade -label "Insert Pane  " \
        -compound left -image [GetImage displayscreen16]

    set rc [MENU $tree.paneRightClick]
    $rc insert end command -label "Copy" \
        -compound left -image [GetImage editcopy16] \
        -command ::InstallJammer::EditCopy
    $rc insert end command -label "Paste" \
        -compound left -image [GetImage editpaste16] \
        -command ::InstallJammer::EditPaste
    $rc insert end separator
    $rc insert end cascade -label "Insert Pane  " \
        -compound left -image [GetImage displayscreen16]
    $rc insert end cascade -label "Insert Action  " \
        -compound left -image [GetImage insertaction16]
    $rc insert end separator
    $rc insert end command -label "Delete Pane" \
        -compound left -image [GetImage buttoncancel16] \
        -command [list ::InstallJammer::Tree::Delete $tree]

    set rc [MENU $tree.actionRightClick]
    $rc insert end command -label "Copy" \
        -compound left -image [GetImage editcopy16] \
        -command ::InstallJammer::EditCopy
    $rc insert end command -label "Paste" \
        -compound left -image [GetImage editpaste16] \
        -command ::InstallJammer::EditPaste
    $rc insert end separator
    $rc insert end cascade -label "Insert Action  " \
        -compound left -image [GetImage insertaction16]
    $rc insert end separator
    $rc insert end command -label "Delete Action" \
        -compound left -image [GetImage buttoncancel16] \
        -command [list ::InstallJammer::Tree::Delete $tree]

    set rc [MENU $tree.actiongroupRightClick]
    $rc insert end command -label "Copy" \
        -compound left -image [GetImage editcopy16] \
        -command ::InstallJammer::EditCopy
    $rc insert end command -label "Paste" \
        -compound left -image [GetImage editpaste16] \
        -command ::InstallJammer::EditPaste
    $rc insert end separator
    $rc insert end cascade -label "Insert Action  " \
        -compound left -image [GetImage insertaction16]
    $rc insert end separator
    $rc insert end command -label "Delete Action Group" \
        -compound left -image [GetImage buttoncancel16] \
        -command [list ::InstallJammer::Tree::Delete $tree]

    set rc [MENU $tree.silentRightClick]
    $rc insert end command -label "Copy" \
        -compound left -image [GetImage editcopy16] \
        -command ::InstallJammer::EditCopy
    $rc insert end command -label "Paste" \
        -compound left -image [GetImage editpaste16] \
        -command ::InstallJammer::EditPaste
    $rc insert end separator
    $rc insert end cascade -label "Insert Action  " \
        -compound left -image [GetImage insertaction16]

    set rc [MENU $tree.actionGroupsRightClick]
    $rc insert end command -label "Copy" \
        -compound left -image [GetImage editcopy16] \
        -command ::InstallJammer::EditCopy
    $rc insert end command -label "Paste" \
        -compound left -image [GetImage editpaste16] \
        -command ::InstallJammer::EditPaste
    $rc insert end separator
    $rc insert end command -label "New Action Group" \
        -compound left -image [GetImage appwindow_list16] \
        -command [list ::InstallJammer::AddActionGroup $setup]
}

proc ::InstallJammer::Tree::Toggle { tree node } {
    variable double 1
    ::InstallJammer::SetActiveComponent $node
    after idle [list unset -nocomplain ::InstallJammer::Tree::double]
    $tree toggle $node
}

proc ::InstallJammer::Tree::SelectItem { args } {
    global conf

    variable select
    variable double

    if {[llength $args] == 2} {
        set which 1
        lassign $args tree node
    }  else {
        lassign $args tree which node
    }

    after cancel $conf(renameAfterId)

    if {$which == 3 && ![info exists select($tree)]} { set which 1 }

    if {$which == 1} {
        ## Single click.

        ::InstallJammer::SetActiveComponent $node

        if {[info exists double]} {
            unset double
            return
        }

        if {[info exists select($tree)] 
            && [string equal $select($tree) $node]} {
            set cmd [list ::InstallJammer::Tree::Rename $tree]
            set conf(renameAfterId) [after 800 $cmd]
        }

        set select($tree) $node
    } elseif {$which == 3} {
        ## Shift click

        set nodes [::InstallJammer::Tree::AllNodes $tree]

        set old  $select($tree)
        set idx1 0
        if {[string length $old]} { set idx1 [lsearch -exact $nodes $old] }
        if {$idx1 < 0} { set idx1 0 }

        set idx2 [lsearch -exact $nodes $node]

        if {$idx2 < $idx1} {
            set x $idx1
            set idx1 $idx2
            set idx2 $x
        }

        set items [list]
        foreach n [lrange $nodes $idx1 $idx2] {
            if {[$tree visible $n]} { lappend items $n }
	}

        eval $tree selection set $items
    } elseif {$which == 4} {
        ## Control click.

	if {[lsearch -exact [$tree selection get] $node] > -1} {
            $tree selection remove $node
	} else {
            $tree selection add $node
	}
    }
}

proc ::InstallJammer::Tree::Rename { tree } {
    global widg

    set item [$tree selection get]
    set id   $item

    if {$tree eq $widg(FileGroupTree)} {
        set id [$tree itemcget $item -data]
    }

    set type [$id type]

    if {$tree eq $widg(FileGroupTree)
        || $tree eq $widg(ComponentTree)
        || $tree eq $widg(SetupTypeTree)} {
        set types [list filegroup component setuptype]
        if {[lsearch -exact $types $type] < 0} { return }
        set text  [$item name]
    } else {
        set types [list pane action actiongroup]
        if {[lsearch -exact $types $type] < 0} { return }
        set text  [$item title]
    }

    $tree edit $item $text [list ::InstallJammer::Tree::DoRename $tree $item]
}

proc ::InstallJammer::Tree::DoRename { tree item newtext } {
    global widg

    set oldtext [$tree itemcget $item -text]

    if {$newtext ne $oldtext} {
        $tree itemconfigure $item -text $newtext

        if {$tree eq $widg(FileGroupTree)} {
            ::FileGroupTree::rename $item $newtext
        } elseif {$tree eq $widg(ComponentTree)} {
            ::ComponentTree::rename $item $newtext
        } elseif {$tree eq $widg(SetupTypeTree)} {
            ::SetupTypeTree::rename $item $newtext
        } else {
            set alias   [$item alias]
            set default [::InstallJammer::GetDefaultTitle $item]
            if {$newtext ne $default && ($alias eq "" || $alias eq $oldtext)
                && [::InstallJammer::CheckAlias $item $newtext 0]} {
                $item alias $newtext
                ::InstallJammer::SetActiveProperty Alias $newtext
            }

            $item title $newtext

            ::InstallJammer::RefreshComponentTitles $item
        }

        Modified
    }

    focus $tree

    return 1
}

proc ::InstallJammer::Tree::Delete { tree {prompt 1} } {
    global widg

    if {$tree eq $widg(FileGroupTree)} {
        ::FileGroupTree::delete
    } elseif {$tree eq $widg(ComponentTree)} {
        ::ComponentTree::delete
    } elseif {$tree eq $widg(SetupTypeTree)} {
        ::SetupTypeTree::delete
    } else {
        set msg "Are you sure you want to delete the selected items?"
        if {$prompt && ![::InstallJammer::AskYesNo -message $msg]} { return }

        foreach node [$tree selection get] {
            if {[IsInstallType $tree $node]} { continue }
            set setup [$node setup]
            $tree delete $node
            $node destroy
            Modified
        }

        if {[info exists setup]} {
            unset -nocomplain ::InstallJammer::ActiveComponent
            unset -nocomplain ::InstallJammer::ActiveComponents($setup)
            ::InstallJammer::SetActiveComponent
        }
    }
}

proc ::InstallJammer::Tree::Popup { setup tree X Y item } {
    global conf
    global widg

    set type [$tree itemcget $item -data]

    if {$type eq "installtype"} {
        switch -glob -- $item {
            "Common*" - "Console*" - "Silent*" - "ActionGroups*" {
                set type [string range $item 0 end-[string length $setup]]
                set type [string tolower $type 0]
            }
        }
    }

    set menu $tree.${type}RightClick
    if {![winfo exists $menu]} { return }

    if {[llength [$tree selection get]] < 2} {
        $tree selection set $item
    }

    switch -- $type {
        "installtype" {
            $menu entryconfigure "Insert Pane  " -menu $widg(${setup}PanesMenu)
        }

        "pane" {
            $menu entryconfigure "Insert Pane  " -menu $widg(${setup}PanesMenu)
            $menu entryconfigure "Insert Action  " \
                -menu $widg(${setup}ActionsMenu)
        }

        "action" - "actiongroup" - "silent" {
            $menu entryconfigure "Insert Action  " \
                -menu $widg(${setup}ActionsMenu)
        }
    }

    $menu post $X $Y

    #if {!$conf(windows)} { tkwait window $menu }
}

proc ::InstallJammer::Tree::FinishOpenProject {} {
    global widg

    ## Walk the Install tree and open every empty pane.
    ## This lets us drag-and-drop actions into nodes that
    ## have no children.  The node must be open to allow this.
    set tree [$widg(Install) gettree]
    foreach root [$tree nodes root] {
        foreach node [$tree nodes $root] {
            if {![lempty [$tree nodes $node]]} { continue }
            $tree itemconfigure $node -open 1
        }
    }

    #set tree $widg(FileGroupTree)
    #foreach platform [$tree nodes root] {
        #foreach node [$tree nodes $platform] {
            #if {![lempty [$tree nodes $node]]} { continue }
            #$tree itemconfigure $node -open 1
        #}
    #}
}

proc ::InstallJammer::Tree::IsInstallType { tree node } {
    if {[string equal $node "root"] || ![$tree exists $node]} { return 0 }
    return [string equal [$tree itemcget $node -data] "installtype"]
}

proc ::InstallJammer::Tree::IsActionParent { tree node } {
    if {$node eq "root" || ![$tree exists $node]} { return 0 }

    set data [$tree itemcget $node -data]

    if {$data eq "pane" || $data eq "actiongroup"
        || [string match "Silent*" $node] || [string match "Console*" $node]} {
        return 1
    }

    return 0
}

proc ::InstallJammer::Tree::IsPaneParent { tree node } {
    if {[string equal $node "root"] || ![$tree exists $node]} { return 0 }

    if {[string match "Common*" $node]
        || [string match "Console*" $node]
        || [string match "Silent*" $node]
        || [$tree itemcget $node -data] ne "installtype"} { return 0 }

    return 1
}

proc ::InstallJammer::Tree::GetPaneParent { tree node } {
    if {![string length $node]} { return }

    set n $node
    set p [$tree parent $n]
    while {![IsInstallType $tree $n]} {
        if {[string equal $p "root"]} { return }
        set n $p
        set p [$tree parent $n]
    }

    ## Can't add a pane to Common or a Silent install or under Action Groups.
    switch -glob -- $n {
        "Common*" - "Console*" - "Silent*" - "ActionGroups*" { return }
    }

    return $n
}

proc ::InstallJammer::Tree::GetActionParent { tree node } {
    if {[lempty $node]} { return }

    set n $node
    set p [$tree parent $n]
    set d [$tree itemcget $n -data]
    while {![string equal $d "pane"]} {
        if {[IsActionParent $tree $n]} { return $n }
        set n $p
        set p [$tree parent $n]
        if {![$tree exists $p]} { return }
        set d [$tree itemcget $n -data]
    }

    return $n
}

proc ::InstallJammer::Tree::DragInit { tree node top } {
    set p [$tree parent $node]
    if {$p eq "root" && [$tree itemcget $node -data] ne "setuptype"} { return }

    global conf
    after cancel $conf(renameAfterId)

    return [list TREE_NODE {move} $node]
}

proc ::InstallJammer::Tree::DropNode { tree source nodeData op type node } {
    global widg

    ## This proc only handles drag-and-drop commands within itself.
    ## If the widget this came from is not our widget (minus the canvas),
    ## we don't want to do anything.  They need to handle this themselves.
    if {![string equal [winfo parent $source] $tree]} { return }

    if {[llength $nodeData] != 3} { return }

    set parent [lindex $nodeData 1]
    set index  [lindex $nodeData 2]
    set data   [$tree itemcget $node -data]

    set parentNode $parent

    switch -- $data {
        "pane" {
            if {![IsPaneParent $tree $parent]} { return }
        }

        "action" {
            if {![IsActionParent $tree $parent]} { return }
        }

        "component" {
            if {$parent eq "root"} { return }
        }

        "setuptype" {
            set parent     SetupTypes
            set parentNode root
        }
    }

    if {[catch { $tree move $parentNode $node $index } error]} { return }

    $node reparent $parent
    $parent children reorder [$tree nodes $parentNode]

    if {$data eq "component"} {
        ## Reorder the components in each setup type so that
        ## they display in the correct order during installation.

        set allComponents [Components children recursive]

        foreach setuptype [SetupTypes children] {
            set components [$setuptype get Components]
            if {[llength $components] > 1} {
                set newComponents {}
                foreach component $allComponents {
                    if {[lsearch -exact $components $component] > -1} {
                        lappend newComponents $component
                    }
                }
                $setuptype set Components $newComponents
            }
        }

        ## Clear the setup type component tree and rebuild
        ## it so that all of the components are shown in
        ## the correct order.

        set tree $widg(SetupTypeComponentTree)
        $tree clear

        foreach id [Components children recursive] {
            set text   [$id name]
            set parent [$id parent]
            if {$parent eq "Components"} { set parent "root" }

            $tree insert end $parent $id \
                -type checkbutton -open 1 -text $text \
                -variable ::SetupTypeTree::ComponentIncludes($id) \
                -command [list ::SetupTypeTree::SetComponentInclude $tree $id]
        }
    }

    Modified
}

proc ::InstallJammer::Tree::OpenSelectedNode { tree {recursive 0} } {
    foreach node [$tree selection get] {
        $tree opentree $node $recursive
    }
}

proc ::InstallJammer::Tree::CloseSelectedNode { tree {recursive 0} } {
    foreach node [$tree selection get] {
        $tree closetree $node $recursive
    }
}

proc ::InstallJammer::SetupPlatformProperties { id prop } {
    set include [$id platforms]
    set cmd ::InstallJammer::FinishEditPlatformNode
    foreach n [$prop nodes platforms] {
        set varName  [$prop itemcget $n -variable]
        set platform [$prop itemcget $n -data]
        $prop itemconfigure $n -editfinishcommand \
            [list $cmd $prop $id $n $varName]
        if {[lsearch -exact $include $platform] > -1} {
            set $varName Yes
        } else {
            set $varName No
        }
    }
}

proc ::InstallJammer::RefreshComponentTitles { {items {}} } {
    global widg

    if {![llength $items]} {
        foreach installtype [InstallTypes children] {
            eval lappend idlist [$installtype children recursive]
        }
    } else {
        set types  [list pane action actiongroup]
        set idlist [list]
        foreach id $items {
            if {[eval $id is $types]} { lappend idlist $id }
        }
    }

    foreach id $idlist {
        set title [$id title]
        if {[llength [$id conditions]]} { append title "*" }
        $widg([$id setup]) itemconfigure $id -text $title
    }
}
Added lib/uninstall.tcl.




































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

if {[info exists ::InstallJammer]} { return }

proc ::InstallJammer::UpdateUninstallProgress {} {
    global conf
    global info

    incr0 conf(num)
    set pct [expr ($conf(num) * 100) / $conf(total)]
    if {$pct != $conf(lastPercent)} {
        set info(UninstallPercentComplete) $pct

        if {$info(GuiMode)} {
            ::InstallJammer::UpdateSelectedWidgets
            update
        } elseif {$info(ConsoleMode) && $conf(ShowConsoleProgress)} {
            ::InstallJammer::ConsoleProgressBar $pct
        }
        set conf(lastPercent) $pct
    }
}

proc ::InstallJammer::GetUninstallInfo {} {
    global conf
    global info
    global uninstall

    ## We check first to see if our .info files may be stored
    ## inside the uninstaller itself.  If not, we check for
    ## an InstallJammer registry that we can use.
    set dir   $::installkit::root
    set files [glob -nocomplain -dir $dir *.info]
    set conf(LogsInUninstaller) 1

    if {![llength $files]} {
        set conf(LogsInUninstaller) 0
        set dir   [::InstallJammer::GetInstallInfoDir]
        set files [glob -nocomplain -dir $dir *.info]
    }

    set installdir  $info(InstallDir)
    set uninstaller $info(Uninstaller)

    set conf(uninstall) $uninstaller

    set sort [list]
    foreach file $files {
        ## If there is a .dead file alongside this .info file,
        ## it's our way of marking a file as deleted.
        if {[file exists [file root $file].dead]} { continue }

        set id [file root [file tail $file]]
        ::InstallJammer::ReadPropertyFile $file tmp

        if {![info exists tmp(Uninstaller)]} {
            lappend sort [list $tmp(Date) $id]
            continue
        }

        if {[patheq $installdir $tmp(Dir)]
            || [patheq $uninstaller $tmp(Uninstaller)]} {
            lappend sort [list $tmp(Date) $id]
        }
    }

    set data ""
    foreach list [lsort -integer -index 0 $sort] {
        set id [lindex $list 1]

        lappend conf(UninstallIDs) $id

        set file [file join $dir $id.log]
        if {[file exists $file]} {
            append data [read_textfile $file]
        }
    }

    set uninstall(:DIR)      {}
    set uninstall(:FILE)     {}
    set uninstall(:REGISTRY) {}
    foreach line [split [string trim $data] \n] {
        if {[info exists done($line)]} { continue }
        set done($line) 1
        lappend uninstall([lindex $line 0]) [lrange $line 1 end]
    }
}

proc ::InstallJammer::CleanupInstallInfoDirs {} {
    global info
    global conf

    if {[string is true -strict $info(Testing)]} { return }

    if {![info exists conf(UninstallIDs)]} { return }
    if {[file exists $info(Uninstaller)]
        && ![file writable $info(Uninstaller)]} { return }
    if {[file exists $info(InstallInfoDir)]
        && ![file writable $info(InstallInfoDir)]} { return }

    debug "Cleaning up install registry..."

    set info(Status) "Cleaning up install registry..."
    ::InstallJammer::UpdateWidgets -update 1

    if {!$conf(UninstallRemoved)} {
        ## There was a problem deleting files, so the uninstall
        ## was not fully removed from the system.  We want to
        ## take any leftover bits from the uninstall and store
        ## them inside the uninstaller.

	debug "Uninstaller was not removed."

        if {$conf(LogsInUninstaller)} {
	    debug "Found logs in uninstaller.  Moving them  to new uninstaller."

            ## We already have logs saved in our uninstall, so
            ## we want to find the first .info file and use it
            ## for our future uninstalls.
            foreach id $conf(UninstallIDs) {
                set file [file join $::installkit::root $id.info]

                if {![info exists found]} {
                    ## Take the first .info file we find and use it.
                    set found $id
                    file copy -force $file [::InstallJammer::TmpDir]
                } else {
                    ## Mark all other info files as dead since we
                    ## have no real way of deleting them from the
                    ## uninstaller.
                    close [open [::InstallJammer::TmpDir $id.dead] w]
                }
            }

            set id $found
        } else {
	    debug "Storing install IDs in uninstaller."

            foreach id $conf(UninstallIDs) {
                set file [file join $info(InstallInfoDir) $id.info]
                if {[file exists $file]} {
                    file copy -force $file [::InstallJammer::TmpDir]
                    break
                }
            }
        }

        set log [::InstallJammer::TmpDir $id.log]
        set fp [open_text $log w -translation lf -encoding utf-8]

        foreach var [array names ::leftovers] {
            foreach list [lreverse $::leftovers($var)] {
                puts $fp [concat $var $list]
            }
        }

        close $fp

        if {!$conf(windows)} { ::InstallJammer::StoreLogsInUninstall }
    }

    foreach id $conf(UninstallIDs) {
        foreach ext {.log .ver .info} {
	    set file [file join $info(InstallInfoDir) $id$ext]
	    if {[file exists $file]} {
	    	debug "Deleting $file"
		file delete $file
	    }
        }
    }

    ## If this ApplicationID has no more installations, we can
    ## remove its directory entirely.
    if {[::InstallJammer::DirIsEmpty $info(InstallInfoDir)]} {
    	debug "Deleting empty registry directory $info(InstallInfoDir)."
        catch { file delete -force $info(InstallInfoDir) }
    } else {
    	debug "Will not delete non-empty directory $info(InstallInfoDir)."
    }
}

proc ::InstallJammer::InstallLog {args} {
    ## This is a dummy proc.  We don't actually want
    ## to log anything during an uninstall.
}

proc ::InstallJammer::CleanupTmpDir {} {
    global conf
    global info

    set tmpdir [::InstallJammer::TmpDir]
    if {$conf(windows)} {
        ## On Windows, we sometimes can't rename the uninstaller out
        ## of the way for it to complete.  This happens when the temp
        ## directory is on another drive from the installation directory.
        ## So, we attempted to rename the uninstaller, failed, and now
        ## we need to do cleanup AFTER the uninstall has exited.

        ## We create a tcl script that we're going to execute with a
        ## common installkit after the uninstall exits.  First thing
        ## we do is remove the temporary directory.
        set tmp [::InstallJammer::TmpDir ij[pid]cleanup.tcl]
        set fp [open $tmp w]
        puts $fp "catch {wm withdraw .}"
        puts $fp "set temp [list [::InstallJammer::TmpDir]]"

        if {[info exists conf(uninstall)]} {
            puts $fp "set uninstall [list $conf(uninstall)]"
        }

        if {[info exists conf(uninstall)] && !$conf(UninstallRemoved)} {
            ## The uninstaller was created but was not remvoed.  This
            ## happens when we were unable to delete some file because
            ## of permissions, so we need to store the remainder of our
            ## install info into the uninstaller.  We do that here in
            ## the cleanup because we have to wait until the uninstaller
            ## becomes writable.
            puts $fp {
                set pattern {*[.info|.log|.dead]}
                foreach file [glob -nocomplain -type f -dir $temp $pattern] {
                    lappend files $file
                    lappend names [file tail $file]
                }
                set i 0
                while {[incr i] < 600 && [file exists $uninstall] &&
                    [catch {installkit::addfiles $uninstall $files $names}]} {
                    after 100
                }
            }
        }

        ## Attempt to cleanup our temp directory for about a minute and
        ## then give up and move on.
        puts $fp {
            set i 0
            while {[file exists $temp] && [incr i] < 600} {
                catch {file delete -force -- $temp}
                after 100
            }
        }

        if {$conf(UninstallRemoved) && !$conf(UninstallRenamed)} {
            ## We attempted to rename the uninstaller out of the
            ## way, but it failed.  This usually happens with the
            ## uninstaller and the temp directory are on different
            ## filesystems.

            ## Add the uninstaller to our cleanup script.
            puts $fp {
                set i 0
                while {[file exists $uninstall] && [incr i] < 300} {
                    catch {file delete -force -- $uninstall}
                    after 100
                }
            }

            ## Check to see that the directory the uninstall is in is
            ## actually in our list of directories that failed to be
            ## deleted.  If it's in our error list, it means we tried
            ## to delete it, but we failed, so now we want to try again
            ## from our cleanup script.
            set dir [file normalize [file dirname $conf(uninstall)]]
            if {[lsearch -exact $info(ErrorDirs) $dir] > -1} {
                ## Now that we've determined this directory failed to
                ## be deleted, we want to do a check within the script
                ## itself to make sure that the directory we're about
                ## to delete is actually empty now.  It should be empty
                ## if the uninstall was deleted properly, and we already
                ## know that it failed to delete before, so we can be
                ## reasonably safe that this directory needs to go.

                set dirs [list $dir]

                if {[info exists conf(cleanupCompanyDir)]} {
                    ## The uninstaller left behind a company directory.
                    ## We need to try and clean that up as well.
                    lappend dirs $conf(cleanupCompanyDir)
                }
                puts $fp "set dirs [list $dirs]"
                puts $fp {
                    set i 0
                    while {[incr i] < 300} {
                        set done 0
                        foreach dir $dirs {
                            if {![file exists $dir]} {
                                incr done
                                continue
                            }

                            ## Check to see if the directory is empty.
                            set files [glob -nocomplain -dir $dir *]
                            eval lappend files \
                                [glob -nocomplain -dir $dir -type hidden *]
                            if {![llength $files]} { catch {file delete $dir} }
                        }

                        ## If we've deleted every directory in our list,
                        ## break out so we can exit.
                        if {$done == [llength $dirs]} { break }
                        after 100
                    }
                }
            }
        }
        puts $fp "exit"
        close $fp

        ## Create a common installkit and then launch our script with it.
        ## The script will run for a bit and check at intervals until our
        ## uninstaller here has exited and left everything available.
        set installkit [::InstallJammer::GetCommonInstallkit $conf(uninstall)]
        installkit::Windows::shellExecute -windowstate hidden default \
            $installkit "\"$tmp\""
    } else {
        ## Cleanup on UNIX is just removing the temporary directory and
        ## our cleanup script.  We add a sleep just to give time for the
        ## dust to settle.
        set tmp [file join $info(TempRoot) install[pid]cleanup.sh]
        set fp [open $tmp w]
        puts $fp "sleep 3"
        puts $fp "rm -rf $tmpdir $tmp"
        close $fp

        exec [auto_execok sh] $tmp &
    }
}

proc ::InstallJammer::exit { {prompt 0} } {
    global conf
    global info

    if {$info(WizardStarted) && !$info(WizardCancelled)} {
        ::InstallJammer::ExecuteActions "Finish Actions"
    } else {
        ::InstallJammer::ExecuteActions "Cancel Actions"
    }

    ::InstallJammer::CommonExit 0
    if {!$info(Debugging)} { ::InstallJammer::CleanupTmpDir }

    if {[string is integer -strict $conf(ExitCode)]} { ::exit $conf(ExitCode) }
    ::exit 0
}

proc ::InstallJammer::UninstallMain {} {
    global conf
    global info

    if {$conf(unix)} {
        if {$info(RequireRoot) && !$info(UserIsRoot)} {
            if {$info(GuiMode) && $info(PromptForRoot)} {
                set msg [sub "<%PromptForAdministratorText%>"]
                set cmd [concat [list [info nameofexecutable]] $::argv]
                ::InstallJammer::ExecAsRoot $cmd -message $msg
                ::exit 0
            }

            set title   [sub "<%RequireRootTitleText%>"]
            set message [sub "<%RequireRootUninstallText%>"]
            ::InstallJammer::Message -title $title -message $message
            ::exit 1
        }
    }

    if {$info(SilentMode)} {
        after 1000
        ::InstallJammer::ExecuteActions "Startup Actions"
        ::InstallJammer::ExecuteActions Silent
    } elseif {$info(ConsoleMode)} {
        ::InstallJammer::ExecuteActions "Startup Actions"
        ::InstallJammer::ExecuteActions Console
    } else {
        ::InstallJammer::ExecuteActions "Startup Actions"

        set info(WizardStarted) 1
        ::InstallJammer::CenterWindow $info(Wizard)
        ::InstallJammer::Wizard next
    }
}

proc ::InstallJammer::InitUninstall {} {
    global conf
    global info
    global argv

    catch { wm withdraw . }

    SourceCachedFile common.tcl

    ## Check and load the TWAPI extension.
    ::InstallJammer::LoadTwapi

    unset -nocomplain info(Temp)
    unset -nocomplain info(TempRoot)

    cd [::InstallJammer::TmpDir]

    set info(RunningInstaller)   0
    set info(RunningUninstaller) 1

    ::InstallJammer::CommonInit

    ::InstallJammer::ReadMessageCatalog messages

    set conf(mode)  "UninstallMode"
    set conf(stop)  [::InstallJammer::TmpDir .stop]
    set conf(pause) [::InstallJammer::TmpDir .pause]
    set conf(lastPercent) 0
    set conf(uninstall) [info nameofexecutable]
    set conf(UninstallRemoved) 0
    set conf(UninstallRenamed) 0

    set conf(modes) "Standard Silent"
    if {!$conf(windows)} { lappend conf(modes) "Console" }

    array set info {
        ErrorDirs                 ""
        ErrorFiles                ""
        ErrorsOccurred            0
        RunningUninstaller        1
        FileBeingUninstalled      ""
        GroupBeingUninstalled     ""
        UninstallPercentComplete  0
    }

    set info(Status) "Preparing to uninstall..."

    SafeArraySet info {
        FileBeingUninstalledText  "Removing <%FileBeingUninstalled%>"
        GroupBeingUninstalledText "Removing <%GroupBeingUninstalled%>"
    }

    ::InstallJammer::ParseCommandLineArguments $::argv

    if {$info(GuiMode)} {
        SourceCachedFile gui.tcl
        InitGui
    }

    ::InstallJammer::CommonPostInit

    ::InstallJammer::ConfigureBidiFonts
}

::InstallJammer::InitUninstall
Added lib/unpack.tcl.
































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

if {[info exists ::InstallJammer]} { return }

if {[threaded]} {
    proc output { line } {
        thread::send $::parentThread [list ::InstallJammer::UnpackOutput $line]
    }
} else {
    proc output {string} {
        global conf

        catch { puts $conf(runlogFp) $string }
        puts stdout $string

        catch { flush $conf(runlogFp) }
        flush stdout
    }
}

proc ::InstallJammer::InstallFiles {} {
    global conf
    global info
    global files
    global groups

    set conf(unpackTotal) 0

    ::InstallJammer::CreateDir $info(InstallDir)

    foreach group $groups {
        set name [::InstallAPI::GetDisplayText -object $group]
        output [list :GROUP $name [$group directory]]

        $group install

        ## The group may not have any actual files.
        if {![info exists files($group)]} { continue }

        foreach file $files($group) {
            output [list :FILE [$file destfile] [$file version]]
            if {![$file install]} { return }
        }
    }
}

proc ::InstallJammer::IncrProgress { bytes } {
    global conf
    global info

    if {$info(TotalSize) == 0} {
	output ":PERCENT 100"
	return
    }

    incr0 conf(unpackLeft) -$bytes
    incr0 conf(unpackTotal) $bytes
    incr0 conf(unpackSoFar) $bytes

    if {$info(TotalSize) > 0} {
	set x [expr round(($conf(unpackTotal) * wide(100.0))/$info(TotalSize))]
        if {$x != $conf(lastPercent)} {
            output ":PERCENT $x"
            set conf(lastPercent) $x
        }
    }

    #if {$info(FileSize) > 0} {
	#set x [expr round( ($conf(unpackSoFar) * 100.0) / $info(FileSize) )]
	#output ":FILEPERCENT $x"
    #}
}

proc ::InstallJammer::unpack { src dest {permissions ""} } {
    global conf
    global info

    if {![PauseCheck]} { return }

    if {$conf(rollback) && [file exists $dest]} {
        output [list :ROLLBACK $dest]
        ::InstallJammer::SaveForRollback $dest
    }

    if {$permissions eq ""} { set permissions 0666 }

    # Extract the file and copy it to its location.
    set fin [open $src r]
    if {[catch {open $dest w $permissions} fout]} {
	close $fin
	return -code error $fout
    }

    set intrans  binary
    set outtrans binary
    if {[info exists conf(eol,[file extension $dest])]} {
        set trans $conf(eol,[file extension $dest])
        if {[llength $trans] == 2} {
            set intrans  [lindex $trans 0]
            set outtrans [lindex $trans 1]
        } else {
            set outtrans [lindex $trans 0]
        }
    }

    fconfigure $fin  -translation $intrans  -buffersize $conf(chunk)
    fconfigure $fout -translation $outtrans -buffersize $conf(chunk)

    set conf(unpackLeft)  $info(FileSize)
    set conf(unpackDone)  0
    set conf(unpackSoFar) 0
    set conf(unpackFin)   $fin
    set conf(unpackFout)  $fout
    set conf(lastPercent) 0

    ::InstallJammer::unpackfile $fin $fout 0

    if {!$info(InstallStopped)} {
        vwait ::conf(unpackDone)
    }

    return $dest
}

proc ::InstallJammer::unpackfile { in out bytes {error ""} } {
    global conf

    if {![PauseCheck]} {
        set error "Install Stopped"
    }

    ::InstallJammer::IncrProgress $bytes

    if {$error ne "" || $conf(unpackLeft) <= 0 || [eof $in]} {
	close $in
	close $out
	set conf(unpackDone) $conf(unpackTotal)
    } else {
        set size $conf(chunk)
        if {$size > $conf(unpackLeft)} { set size $conf(unpackLeft) }
	::fcopy $in $out -size $size -command [lrange [info level 0] 0 2]
    }
}

proc ::InstallJammer::InstallLog { string } {
    output [list :LOG $string]
}

proc ::InstallJammer::exit {} {
    global info
    global conf

    if {![threaded]} {
        ::InstallJammer::WriteDoneFile $info(Temp)

        catch { close $conf(runlogFp) }
        catch { close $conf(unpackFin)  }
        catch { close $conf(unpackFout) }

        ::exit
    }

    output ":PERCENT 100"
    output ":DONE"
}

proc ::InstallJammer::UnpackMain {} {
    global conf
    global info

    catch { wm withdraw . }

    ::InstallJammer::CommonInit

    set conf(pwd) [file dirname [info nameofexe]]

    if {![threaded]} { set info(Temp) $conf(pwd) }

    uplevel #0 [list source -encoding utf-8 [lindex $::argv end]]

    set conf(stop)        [TmpDir .stop]
    set conf(pause)       [TmpDir .pause]
    set conf(chunk)       [expr {64 * 1024}]
    set conf(lastPercent) 0

    ::InstallJammer::InitSetup
    ::InstallJammer::InitFiles
    ::InstallJammer::UpdateFiles

    if {![threaded]} {
        set conf(vfs) /installkitunpackvfs
        ::installkit::Mount $info(installer) $conf(vfs)
        set conf(runlogFp) [open [TmpDir run.log] w]

        if {$info(InstallHasSolidArchives)} {
            foreach file [glob -nocomplain -dir [TmpDir] solid.*] {
                installkit::Mount $file $conf(vfs)
            }
        }

        ::InstallJammer::MountSetupArchives
    }

    set conf(rollback) [string match "*Rollback*" $info(CancelledInstallAction)]

    if {$conf(Wow64Disabled)} {
        installkit::Windows::disableWow64FsRedirection
    }

    if {[info exists info(InstallPassword)] && $info(InstallPassword) ne ""} {
        ::InstallAPI::SetInstallPassword -password [sub $info(InstallPassword)]
    }

    ::InstallJammer::InstallFiles

    ::InstallJammer::exit
}

::InstallJammer::UnpackMain
Added lib/utils.tcl.
















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc Window {args} {
    global conf

    set cmd     [lindex $args 0]
    set name    [lindex $args 1]
    if {$name == "" || $cmd == ""} { return }
    set res    [list]
    set exists [winfo exists $name]
    switch $cmd {
        show {
            if {$exists} {
		set res [eval Window$name [lrange $args 2 end]]
	    } else {
		if {[info procs Pre_Window$name] != ""} {
		    eval Pre_Window$name [lrange $args 2 end]
		}
		if {[info procs Window$name] != ""} {
		    set res [eval Window$name [lrange $args 2 end]]
		}
		if {[info procs Post_Window$name] != ""} {
		    eval Post_Window$name [lrange $args 2 end]
		}
	    }
        }

        hide    {
	    if $exists { wm withdraw $name }
	}

	destroy {
	    if $exists { destroy $name }
	}
    }

    return $res
}

proc WidgetName {list} {
    set w [join $list ""]
    return [string tolower [string index $w 0]][string range $w 1 end]
}

proc ShowDialog {window args} {
    global conf

    eval Window show $window $args
    tkwait window $window
}

proc ::InstallJammer::ExecuteInTerminal { file arguments } {
    set desktop [::InstallJammer::GetDesktopEnvironment]

    if {$desktop eq "Gnome"} {
        exec gnome-terminal -e "\"$file\" $arguments" >& /dev/null &
    } elseif {$desktop eq "KDE"} {
        eval exec konsole -e [list $file] $arguments >& /dev/null &
    } else {
        exec xterm -e "\"$file\" $arguments" >& /dev/null &
    }
}

proc TestInstall {} {
    global conf
    global info

    if {!$conf(projectLoaded)} {
	::InstallJammer::Message -message "No project loaded!"
	return
    }

    if {$conf(building)} {
        set    msg "There is a build in progress.  Please wait to test until "
        append msg "the build has completed."
        ::InstallJammer::Message -message $msg
        return
    }

    if {$conf(modified)} {
	set msg "This project has been modified.  "
	append msg "Do you want to save and rebuild before testing?"
	set res [::InstallJammer::MessageBox -type user -buttonwidth 16 \
            -buttons {"Save & Build" "Save & Quick Build" "Cancel"} \
            -title "Project Modified" -message "This project has been\
                modified.  Do you want to save and rebuild before testing?"]

        if {$res == 2} { return }

        update

        Save

        if {$res == 0} {
            Build [::InstallJammer::Platform]
            vwait ::conf(building)
        } else {
            ::InstallJammer::QuickBuild [::InstallJammer::Platform]
        }
    }

    set args $conf(TestCommandLineOptions)

    if {!$info(IncludeDebugging)} {
	foreach opt [list -T -D -C] {
	    if {[lsearch -exact $args $opt] < 0} { continue }
	    ::InstallJammer::MessageBox -title "Debugging Not Included" \
		-message "This install was not built with debugging options."
	    break
	}
    }

    set info(Platform) [::InstallJammer::Platform]
    set info(Ext)      [expr {$info(Platform) eq "Windows" ? ".exe" : ""}]

    set file [::InstallJammer::SubstText [$info(Platform) get Executable]]
    set dir  [InstallDir output]
    if {[$info(Platform) get BuildSeparateArchives]} {
        set dir [InstallDir output/$info(Platform)]
    }
    set file [file join $dir $file]

    if {![file exists $file]} {
	::InstallJammer::MessageBox -title "Build Install First" -message \
	    "You must build the install before you can test it."
	return
    }

    Status "Testing install..." 3000

    if {$conf(TestConsole)} {
        ::InstallJammer::ExecuteInTerminal $file $args
    } else {
        if {$conf(windows)} {
            installkit::Windows::shellExecute open $file $args
        } else {
            eval exec [list $file] $args &
        }
    }
}

proc TestUninstall {} {
    global conf
    global info

    set platform     [::InstallJammer::Platform]
    set dirname      [::InstallJammer::SubstText [$platform get InstallDir]]
    set olduninstall [file join $dirname uninstall$info(Ext)]

    set dir  [::InstallJammer::GetInstallInfoDir]
    set sort [list]

    set file [file join $dir install.log]
    if {[file exists $file]} {
        lappend sort [list [file mtime $file] $olduninstall]
    }

    if {[file exists $olduninstall]} {
        lappend sort [list [file mtime $olduninstall] $olduninstall]
    }

    foreach file [glob -nocomplain -dir $dir *.info] {
        ::InstallJammer::ReadPropertyFile $file tmp
        if {![info exists tmp(Uninstaller)]} {
            lappend sort [list $tmp(Date) $olduninstall]
        } else {
            lappend sort [list $tmp(Date) $tmp(Uninstaller)]
        }
    }

    if {![llength $sort]} {
        ::InstallJammer::Error -message \
            "No uninstaller found.  You must run the installer first."
        return
    }

    set args $conf(TestUninstallCommandLineOptions)
    set file [lindex [lindex [lsort -integer -index 0 $sort] end] 1]

    foreach list [lsort -decreasing -integer -index 0 $sort] {
        set file [lindex $list 1]
        if {[file exists $file]} { break }
    }

    if {$conf(TestUninstallConsoleMode)} {
        ::InstallJammer::ExecuteInTerminal $file $args
    } else {
        if {$conf(windows)} {
            installkit::Windows::shellExecute open $file $args
        } else {
            eval exec [list $file] $args &
        }
    }
}

proc AdjustTestInstallOptions {} {
    global conf
    upvar #0 conf(TestCommandLineOptions) opts

    set head --
    if {$conf(windows)} { set head / }

    array set options {
	SaveTempDir       debug
	TestWithoutFiles  test
	TestAllDefaults   {mode default}
        TestConsole       {mode console}
	TestSilent        {mode silent}
	TestWithConsole   debugconsole
    }

    set opts [list]
    foreach opt [array names options] {
	if {$conf($opt)} { eval lappend opts $head$options($opt) }
    }
}

proc AdjustTestUninstallOptions {} {
    global conf
    upvar #0 conf(TestUninstallCommandLineOptions) opts

    set head --
    if {$conf(windows)} { set head / }

    array set options {
        TestUninstallDebugging     debug
	TestUninstallSilentMode    {mode silent}
	TestUninstallConsoleMode   {mode console}
        TestUninstallWithConsole   debugconsole
	TestUninstallWithoutFiles  test
    }

    set opts [list]
    foreach opt [array names options] {
	if {$conf($opt)} { eval lappend opts $head$options($opt) }
    }
}

proc InstallKitBinary { {type ""} } {
    return [InstallKitStub [::InstallJammer::Platform] $type]
}

proc BuildBinary {} {
    return [InstallKitStub [::InstallJammer::Platform]]
}

proc InstallKitStub { platform {type ""} } {
    global conf
    global info

    set exe installkit
    if {$platform eq "Windows"} {
        if {[$platform get UseUncompressedBinaries]} { append exe "U" }
        if {[$platform get RequireAdministrator]} { append exe "A" }
        append exe .exe
    }

    set stub [file join $conf(pwd) Binaries $platform $exe]

    if {![file exists $stub]} {
        ::InstallJammer::Error -message \
	    "Could not find the appropriate installkit binary for $platform!"
	::exit
    }

    return $stub
}

proc InstallDir { {file ""} } {
    global conf
    global info

    if {[info exists info(ProjectDir)]} {
    	set dir $info(ProjectDir)
    } else {
	set dir [file join $conf(pwd) Installs $info(Project)]
    }

    if {$file ne ""} { set dir [file join $dir $file] }
    if {$conf(windows) && [file exists $dir]} {
	set dir [file attributes $dir -longname]
    }

    return $dir
}

proc AllPlatforms {} {
    global conf

    if {$conf(demo)} {
    	return [list Linux-x86 Windows]
    }

    if {![info exists conf(platforms)]} {
        set bindir [file join $::conf(pwd) Binaries]

        set conf(platforms) [list]
        set platformlist [glob -nocomplain -type d -dir $bindir *]
        foreach dir [lsort $platformlist] {
            set platform [file tail $dir]

            set exe installkit
            if {$platform eq "Windows"} { append exe .exe }

            if {[file exists [file join $dir $exe]]} {
                lappend conf(platforms) $platform
            }
        }
    }

    return $conf(platforms)
}

proc ActivePlatforms {} {
    global info

    set platforms [list]
    foreach platform [AllPlatforms] {
        if {[$platform active]} { lappend platforms $platform }
    }
    return $platforms
}

proc ::InstallJammer::IsRealPlatform { platform } {
    return [expr {[lsearch -exact [AllPlatforms] $platform] > -1}]
}

proc PlatformText { platform } {
    if {[::InstallJammer::IsRealPlatform $platform]} {
        return [join [split $platform -_]]
    }
    return [::InstallJammer::StringToTitle $platform]
}

proc PlatformName { platform } {
    return [string map [list . _] $platform]
}

proc SetPlatform {} {
    global preferences

    if {[info exists preferences(platform)]} { return }

    set platform [::InstallJammer::Platform]
    set platforms [AllPlatforms]
    if {[lsearch -exact $platforms $platform] > -1} { return }

    set top .__installJammer__selectPlatform

    toplevel    $top
    wm withdraw $top
    wm title    $top "Select Platform"
    wm protocol $top WM_DELETE_WINDOW "::exit"
    wm geometry $top 180x110
    ::InstallJammer::CenterWindow $top 180 110

    set msg "InstallJammer could not determine your platform.  Please choose "
    append msg "an appropriate platform from the list below."
    message $top.msg -text $msg -width 180
    pack $top.msg -anchor w -fill x

    label $top.l -text "Platform"
    pack  $top.l -anchor w

    frame $top.f
    pack  $top.f -anchor w

    COMBOBOX $top.f.cb -textvariable ::TMP -values $platforms
    pack $top.f.cb -side left

    button $top.f.b -text "Ok" -command "destroy $top"
    pack   $top.f.b -side left

    wm deiconify $top
    raise $top
    grab set $top
    tkwait window $top
    grab set .splash
    set ::preferences(platform) $::TMP
    unset ::TMP
}

proc ::InstallJammer::NodeName { obj } {
    if {[info exists ::InstallJammer::ObjMap($obj)]} {
        return $::InstallJammer::ObjMap($obj)
    }
    return $obj
}

proc ::InstallJammer::FileKey { parent name } {
    set name [file normalize $name]
    if {$::conf(windows)} { set name [string tolower $name] }
    if {![$parent is filegroup]} { set name [file tail $name] }
    return $parent,$name
}

proc ::InstallJammer::FileObj { parent name args } {
    global widg

    if {$::conf(windows)} { set name [file normalize $name] }

    set key [::InstallJammer::FileKey $parent $name]
    if {[info exists ::InstallJammer::FileMap($key)]} {
        set id $::InstallJammer::FileMap($key)
    } else {
        set id [::InstallJammer::uuid]

        if {![$parent is filegroup]} { set name [file tail $name] }
        eval [list ::File ::$id -name $name -parent $parent] $args
        set ::InstallJammer::FileMap($key)  $id
        set ::InstallJammer::NewFiles($key) 1

	if {[info exists widg(FileGroupTree)]} {
	    set pnode [::InstallJammer::NodeName $parent]
	    if {[$widg(FileGroupTree) visible $pnode]} {
		::InstallJammer::AddToFileTree $id -text [file tail $name]
	    }
	}

        Modified
        ::InstallJammer::FilesModified
    }

    return $id
}

proc ::InstallJammer::FileIsNew { parent name } {
    set key [::InstallJammer::FileKey $parent $name]
    return [info exists ::InstallJammer::NewFiles($key)]
}

## Add directories and files to the selected file group.
## All requests to add directories and files to a project pass through
## this routine, including drag-and-drop'd items.
proc AddFiles { args } {
    global info
    global conf
    global widg

    array set data {
        -isdir     0
        -files     ""
        -group     ""
    }
    array set data $args

    set tree $widg(FileGroupTree)
    set pref $widg(FileGroupPref)

    set n [::InstallJammer::NodeName $data(-group)]
    if {![string length $data(-group)]} { set n [$tree selection get] }

    if {[lempty $n]} { return }

    set group [$tree itemcget $n -data]
    set node  [::InstallJammer::NodeName $group]

    set files $data(-files)

    if {[lempty $files]} {
	if {$data(-isdir)} {
	    set files [list [mpi_chooseDirectory]]
	} else {
	    set files [mpi_getOpenFile -multiple 1]
	}
        if {![llength $files]} { return }
    }

    $tree configure -cursor watch
    Status "Adding files..."

    set dirList [list]
    foreach file $files {
        if {$file eq ""} { continue }

        if {[string match "file:*" $file]} {
            set file [string range $file 5 end]
            set file [::InstallAPI::DecodeURL -url $file]
        }

        if {[string equal $::tcl_platform(platform) "windows"]} {
            set file [file attributes $file -longname]
        }

        if {[file isdirectory $file]} {
            lappend dirList $file
        } else {
            AddToFileGroup -type file -group $group -parent $group -name $file
        }
    }

    foreach dir $dirList {
        if {[string equal $::tcl_platform(platform) "windows"]} {
            set dir [file attributes $dir -longname]
        }

        set dirid [AddToFileGroup -type dir -group $group \
                -parent $group -name $dir]

        ## Scan through the directory recursively so we
        ## can create a file object for every file.
        ::InstallJammer::RecursiveGetFiles $dirid [$group get FollowDirLinks]
    }

    ::FileGroupTree::SortNodes $node

    $tree configure -cursor {}
    ClearStatus

    ## Make sure the selected file group is visible by opening
    ## its parents up the tree.
    if {![$tree visible $node]} {
	set node [$tree parent $node]
	while {![string equal $node "root"]} {
	    $tree opentree $node 0
	    set node [$tree parent $node]
	}
    }
}

proc AddToFileGroup { args } {
    global info
    global conf
    global widg

    array set data {
        -id       ""
        -name     ""
        -text     ""
        -type     ""
        -group    ""
        -parent   ""
        -modify   1
    }
    array set data $args

    set tree   $widg(FileGroupTree)
    set pref   $widg(FileGroupPref)
    set name   $data(-name)
    set text   $data(-text)
    set type   $data(-type)
    set group  $data(-group)
    set parent $data(-parent)

    set node   [::InstallJammer::NodeName $parent]

    set id $data(-id)
    if {![string length $id]} {
        set id [::InstallJammer::FileObj $parent $name -type $type]
    } else {
        set name   [$id name]
        set type   [$id type]
        set group  [$id group]
        set node   [::InstallJammer::NodeName [$id parent]]
        set parent [$id parent]
    }

    set file [::InstallJammer::GetFileSource $id]

    set new     [::InstallJammer::FileIsNew $parent $file]
    set subnode [::InstallJammer::NodeName $id]

    if {[$tree exists $subnode]} { return $id }

    set treeopts [list -data $id -pagewindow $widg(FileGroupDetails)]

    ## Highlight newly-added items in blue.
    if {$new} { lappend treeopts -fill blue }

    ## If a file cannot be found, show it as disabled.
    if {![file exists $file]} { lappend treeopts -fill SystemDisabledText }

    switch -- $type {
        "dir"  {
            set img folder16
            lappend treeopts -drawcross allways
        }
        "file" {
            set img filedocument16
            lappend treeopts -drawcross auto
        }
    }

    if {[$id active]} { set img check$img }
    if {$text eq ""} { set text [file tail $name] }

    lappend treeopts -text $text -image [GetImage $img]

    eval [list $pref insert end $node $subnode] $treeopts

    if {$new && $data(-modify)} {
        Modified
        ::InstallJammer::FilesModified
    }

    return $id
}

proc ::InstallJammer::AddToFileTree { id args } {
    global conf
    global widg

    set tree   $widg(FileGroupTree)
    set pref   $widg(FileGroupPref)
    set node   [::InstallJammer::NodeName $id]
    set parent [$id parent]

    if {[$tree exists $node]} { return $id }

    set file [::InstallJammer::GetFileSource $id]

    set opts [list -data $id -pagewindow $widg(FileGroupDetails)]

    ## Highlight newly-added items in blue.
    if {[::InstallJammer::FileIsNew $parent $file]} {
        lappend opts -fill blue
    }

    ## If a file cannot be found, show it as disabled.
    if {![file exists $file]} {
        lappend opts -fill SystemDisabledText
    }

    switch -- [$id type] {
        "dir"  {
            set img folder16
            lappend opts -drawcross allways
        }
        "file" {
            set img filedocument16
            lappend opts -drawcross auto
        }
    }

    if {[$id active]} { set img check$img }

    lappend opts -image [GetImage $img]

    set parent [::InstallJammer::NodeName $parent]

    eval [list $pref insert end $parent $node] $opts $args

    if {[info exists conf(SortTreeNodes)]} {
        lappend conf(SortTreeNodes) $parent
    }
}

proc AddToRecentProjects { filename } {
    global preferences

    set filename [file normalize $filename]
    if {[lsearch -exact $preferences(RecentProjects) $filename] < 0} {
        lappend preferences(RecentProjects) $filename
    }

    UpdateRecentProjects
}

proc UpdateRecentProjects {} {
    global conf
    global info
    global widg
    global preferences

    variable ::InstallJammer::ProjectItemMap

    set w      $widg(Projects)
    set font   TkTextFont
    set header TkCaptionFont

    $w delete text

    set startX 20
    set startY 60

    set x   $startX
    set y   $startY
    set max 350
    foreach filename $preferences(RecentProjects) {
        if {![file exists $filename]} {
            set preferences(RecentProjects) \
                [lremove $preferences(RecentProjects) $filename]
            continue
        }
        lappend sort([file tail $filename]) $filename
    }

    set dir [GetPref ProjectDir]
    foreach dir [glob -nocomplain -type d -dir $dir *] {
	set tail [file tail $dir]
	set file [file join $dir $tail.mpi]
	if {[file exists $file]
	    && [lsearch -exact $preferences(RecentProjects) $file] < 0} {
	    lappend sort($tail.mpi) $file
	}
    }

    foreach project [lsort -dict [array names sort]] {
        foreach filename $sort($project) {
            set file [file tail $filename]
            set i [$w create text $x $y -text $file -anchor nw -font $header \
                -fill blue -tags [list text project]]
            DynamicHelp::add $w -item $i -text "Location $filename"
            set size [font measure $font $file]
            if {$size > $max} { set max $size }
            set ProjectItemMap($i) $filename
            set ProjectItemMap($filename) $i

            if {[info exists info(ProjectFile)]
                && [string equal -nocase $filename $info(ProjectFile)]} {
                set conf(SelectedProject) $i
            }

            incr y 20
        }
    }

    set x [expr {$startX + $max + 50}]
    set y $startY
    foreach project [lsort -dict [array names sort]] {
        foreach filename $sort($project) {
            set i $ProjectItemMap($filename)
            $w create text $x $y -text [LastSaved $filename] \
                -anchor nw -font $font -tags [list text $i-lastsaved]
            $w create text [expr {$x + 200}] $y -text [LastBuilt $filename] \
                -anchor nw -font $font -tags [list text $i-lastbuilt]

            incr y 20
        }
    }

    set conf(maxProjectSize) $max

    set y [expr {$startY - 30}]
    $w create text $startX $y -text "Project" \
        -anchor nw -font $header -tags [list text]
    $w create text $x $y -text "Last Saved" \
        -anchor nw -font $header -tags [list text]
    $w create text [expr {$x + 200}] $y -text "Last Built" \
        -anchor nw -font $header -tags [list text]

    if {![llength $preferences(RecentProjects)]} {
        $w create text $startX $startY -text "No Projects" -anchor nw -tags text
    }

    $w configure -scrollregion [$w bbox all]
}

proc ::InstallJammer::EnterProjectItem { w } {
    variable ProjectItemMap
    set i [$w find withtag current]

    $w itemconfigure $i -fill red
    Status $ProjectItemMap($i)
}

proc ::InstallJammer::LeaveProjectItem { w } {
    $w itemconfigure current -fill blue
    Status ""
}

proc LastSaved { filename } {
    global conf
    if {![file exists $filename]} { return 0 }
    return [clock format [file mtime $filename] -format "%D %r"]
}

proc LastBuilt { filename } {
    global conf
    set file [file join [file dirname $filename] build.log]
    if {![file exists $file]} {
	return "Never Built"
    } else {
	return [clock format [file mtime $file] -format "%D %r"]
    }
}

proc ::InstallJammer::SetLastSaved {} {
    global info
    global widg
    variable ProjectItemMap

    set filename [file normalize $info(ProjectFile)]
    set i $ProjectItemMap($filename)
    $widg(Projects) itemconfigure $i-lastsaved -text [LastSaved $filename]
}

proc ::InstallJammer::SetLastBuilt {} {
    global conf
    global info
    global widg
    variable ProjectItemMap

    if {$conf(cmdline)} { return }

    set filename [file normalize $info(ProjectFile)]
    set i $ProjectItemMap($filename)
    $widg(Projects) itemconfigure $i-lastbuilt -text [LastBuilt $filename]
}

proc ::InstallJammer::LoadProject { {force 0} } {
    global conf
    global widg
    variable ProjectItemMap

    if {$force || $conf(SelectedProject) eq ""} {
        set conf(SelectedProject) [$widg(Projects) find withtag current]
    }

    Open $ProjectItemMap($conf(SelectedProject))
}

proc ::InstallJammer::ProjectPopup { X Y } {
    global conf
    global widg

    set conf(SelectedProject) [$widg(Projects) find withtag current]

    set menu $widg(Projects).rightClick

    $menu post $X $Y
}

proc ::InstallJammer::DeleteProject {} {
    global conf
    global info
    global widg
    variable ::InstallJammer::ProjectItemMap

    set i       $conf(SelectedProject)
    set file    $ProjectItemMap($i)
    set dir     [file dirname $file]
    set project [file root [file tail $file]]

    set ans [::InstallJammer::MessageBox -parent $widg(InstallJammer) \
        -title "Delete Project" -type yesno \
	-message "The project directory '$dir' will be completely\
	    deleted.\nAre you sure you want to delete $project?"]

    if {$ans eq "no"} { return }

    if {[info exists info(Project)] && $project eq $info(Project)} {
    	if {![Close 1]} { return }
    }

    set dir [file dirname $file]

    set     files [list $file]
    lappend files [file join $dir build.log]
    lappend files [file join $dir build]
    lappend files [file join $dir output]

    eval [list file delete -force] $files

    if {[::InstallJammer::DirIsEmpty $dir]} {
    	file delete -force $dir
    } else {
    	::InstallJammer::MessageBox -title "Project Deleted" -message \
	    "Your project has been deleted, but the directory could not\
	     be removed because it is not empty."
    }

    UpdateRecentProjects
}

proc ::InstallJammer::DuplicateProject {} {
    global conf
    global info
    global widg

    variable ::InstallJammer::ProjectItemMap

    set w $widg(Projects)

    set dir [GetPref ProjectDir]

    set i $conf(SelectedProject)

    set projectFile $ProjectItemMap($i)
    set projectName [file root [file tail $projectFile]]

    set ans [::InstallJammer::MessageBox -type yesno \
    	-title "Duplicate Project" \
    	-message "Are you sure you want to duplicate $projectName?"]

    if {$ans eq "yes"} {
	if {[info exists info(Project)] && $projectName eq $info(Project)} {
	    set msg "This project must be closed before it can be\
	    	duplicated, and there are modifications.\nDo you wish to\
		save your changes before duplicating?"

	    if {![Close 0 $msg]} { return }
	}

        set new     [NextProjectName $projectName]
	set newdir  [file join $dir $new]
	set newfile [file join $newdir $new.mpi]
	set filedir [file dirname $projectFile]

	file mkdir $newdir

	foreach file [glob -nocomplain -dir $filedir *] {
	    set tail [file tail $file]

	    if {$file eq $projectFile
	    	|| $tail eq "build"
		|| $tail eq "output"
		|| $tail eq "build.log"} { continue }

	    set newfile [string map [list $filedir $newdir] $file]
	    set newdir  [file dirname $newfile]

	    file mkdir $newdir

	    file copy $file $newfile
	}

	file copy $projectFile $newfile

	AddToRecentProjects $newfile

	set conf(SelectedProject) $ProjectItemMap($newfile)

	::InstallJammer::RenameProject
    }
}

proc ::InstallJammer::RenameProject {} {
    global conf
    global info
    global widg

    variable ::InstallJammer::ProjectItemMap

    set w       $widg(Projects)
    set i       $conf(SelectedProject)
    set file    $ProjectItemMap($i)
    set project [file root [file tail $file]]

    lassign [$w bbox $i] x y

    if {[info exists info(Project)] && $project eq $info(Project)} {
	set msg "This project must be closed before it can be\
	    renamed, and there are modifications.\nDo you wish to\
	    save your changes before renaming?"

    	if {![Close 0 $msg]} { return }
    }

    ClearTmpVars

    set e $w.renameProject
    entry $w.renameProject -relief sunken -bd 1 -textvariable ::TMPARRAY(p)

    bind $e <Escape> {set ::TMP 0}
    bind $e <Return> {set ::TMP 1}

    $e insert 0 $project
    $e selection range 0 end

    set n [$w create window [list $x $y] -window $e -anchor nw \
        -width $conf(maxProjectSize)]

    after idle [list focus -force $e]

    tkwait variable ::TMP

    destroy $e
    $w delete $n

    if {$::TMP && $::TMPARRAY(p) ne $project} {
    	set new $::TMPARRAY(p)
	set dir [file dirname $file]

	set tail [file tail $dir]

	set newdir $dir
	if {$tail eq $project} {
	    set newdir [file join [file dirname $dir] $new]
	    file rename $dir $newdir
	}

	set oldfile [file join $newdir [file tail $file]]
	set newfile [file join $newdir $new.mpi]

	file rename $oldfile $newfile

	AddToRecentProjects $newfile
    }
}

proc ::InstallJammer::ExploreProject {} {
    global conf
    global widg
    variable ::InstallJammer::ProjectItemMap

    set i    $conf(SelectedProject)
    set file $ProjectItemMap($i)

    ::InstallJammer::Explore [file dirname $file]
}

proc ::InstallJammer::BackupProjectFile { args } {
    global info

    if {[llength $args] == 2} {
        lassign $args oldFile newFile
    } else {
        set newFile [lindex $args 0]
        set oldFile $info(ProjectFile)
    }

    set oldFile [::InstallJammer::SubstText $oldFile]
    set newFile [::InstallJammer::SubstText $newFile]

    if {[file pathtype $newFile] eq "relative"} {
        set newFile [file join $info(ProjectDir) $newFile]
    }

    file copy -force $oldFile $newFile
}

proc ::InstallJammer::ExploreTestInstall {} {
    global conf
    global info

    if {!$conf(projectLoaded)} {
	::InstallJammer::Message -message "Project must be loaded first."
	return
    }

    set platform [::InstallJammer::Platform]
    set dirname  [::InstallJammer::SubstText [$platform get InstallDir]]

    set dir  [::InstallJammer::GetInstallInfoDir]
    set sort [list]

    set file [file join $dir install.log]
    if {[file exists $file]} {
        lappend sort [list [file mtime $file] $dirname]
    }

    foreach file [glob -nocomplain -dir $dir *.info] {
        ::InstallJammer::ReadPropertyFile $file tmp
        lappend sort [list $tmp(Date) $tmp(Dir)]
    }

    set dirname [lindex [lindex [lsort -integer -index 0 $sort] end] 1]

    if {![file exists $dirname]} {
        ::InstallJammer::Message -message \
            "No install found.  You must run the installer first."
    } else {
        ::InstallJammer::Explore $dirname
    }
}

proc NewNode {} {
    variable ::InstallJammer::nNodes
    if {![info exists nNodes]} { set nNodes 0 }
    return [incr nNodes]
}

proc Exit {} {
    global conf

    if {$conf(exiting)} { return }

    set conf(exiting) 1
    
    if {$conf(modified) && ![Close]} {
        set conf(exiting) 0
        return
    }

    ::InstallJammer::SavePreferences

    foreach font [font names] { font delete $font }

    exit
}

proc FileList {dir} {
    global conf

    set list [glob -nocomplain [file join $conf(pwd) $dir *]]
    set return {}
    foreach dir [lsort -dict $list] {
    	lappend return [file tail $dir]
    }
    return $return
}

proc ProjectList {} {
    global conf

    set list [FileList Installs]
    set projects {}
    ## Find all the project directories.  If a directory doesn't have a
    ## install.cfg file, it's just some random directory in our Projects folder,
    ## so we skip it.
    set dir [file join $conf(pwd) Installs]
    foreach project $list {
	set file [file join $dir $project install install.cfg]
	if {![file isdirectory [file join $dir $project]]} { continue }
	if {![file exists $file]} { continue }
	lappend projects $project
    }
    return $projects
}

# -------------------------------------------------------------------
# Routines for encoding and decoding base64
# encoding from Time Janes,
# decoding from Pascual Alonso,
# namespace'ing and bugs from Parand Tony Darugar
# (tdarugar@binevolve.com)
#
# -------------------------------------------------------------------

namespace eval base64 {
  set charset "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

  # This proc by Christian Gavin
  proc encode_file {filename} {
     set inID [open $filename r]
     fconfigure $inID -translation binary
     set contents [read $inID]
     close $inID

     set encoded [::base64::encode $contents]
     set length  [string length $encoded]
     set chunk   60
     set result  ""

     for {set index 0} {$index < $length} {set index [expr $index + $chunk] } {
         set index_end [expr $index + $chunk - 1]

         if {$index_end >= $length} {
             set index_end [expr $length - 1]
             append result [string range $encoded $index $index_end]
         } else {
             append result [string range $encoded $index $index_end]
         }
     }

     return $result
  }

  # ----------------------------------------
  # encode the given text
  proc encode {text} {
    set encoded ""
    set y 0
    for {set i 0} {$i < [string length $text] } {incr i} {
      binary scan [string index $text $i] c x
      if { $x < 0 } {
        set x [expr $x + 256 ]
      }
      set y [expr ( $y << 8 ) + $x]
      if { [expr $i % 3 ] == 2}  {
        append  encoded [string index $base64::charset [expr ( $y & 0xfc0000 ) >> 18 ]]
        append  encoded [string index $base64::charset [expr ( $y & 0x03f000 ) >> 12 ]]
        append  encoded [string index $base64::charset [expr ( $y & 0x000fc0 ) >> 6 ]]
        append  encoded [string index $base64::charset [expr ( $y & 0x00003f ) ]]
        set y 0
      }
    }
    if { [expr $i % 3 ] == 1 } {
      set y [ expr $y << 4 ]
      append encoded [string index $base64::charset [ expr ( $y & 0x000fc0 ) >> 6]]
      append encoded [string index $base64::charset [ expr ( $y & 0x00003f ) ]]
      append encoded "=="
    }
    if { [expr $i % 3 ] == 2 } {
      set y [ expr $y << 2 ]
      append  encoded [string index $base64::charset [expr ( $y & 0x03f000 ) >> 12 ]]
      append  encoded [string index $base64::charset [expr ( $y & 0x000fc0 ) >> 6 ]]
      append  encoded [string index $base64::charset [expr ( $y & 0x00003f ) ]]
      append encoded "="
    }
    return $encoded
  }

  # ----------------------------------------
  # decode the given text
  # Generously contributed by Pascual Alonso
  proc decode {text} {
    set decoded ""
    set y 0
    if {[string first = $text] == -1} {
      set lenx [string length $text]
    } else {
      set lenx [string first = $text]
    }
    for {set i 0} {$i < $lenx } {incr i} {
      set x [string first [string index $text $i] $base64::charset]
      set y [expr ( $y << 6 ) + $x]
      if { [expr $i % 4 ] == 3}  {
        append decoded \
	  [binary format c [expr $y >> 16 ]]
	append decoded \
	  [binary format c [expr ( $y & 0x00ff00 ) >> 8 ]]
	append decoded \
	  [binary format c [expr ( $y & 0x0000ff ) ]]
	set y 0
      }
    }
    if { [expr $i % 4 ] == 3 } {
      set y [ expr $y >> 2 ]
	append decoded \
	  [binary format c [expr ( $y & 0x00ff00 ) >> 8 ]]
	append decoded \
	  [binary format c [expr ( $y & 0x0000ff ) ]]
    }
    if { [expr $i % 4 ] == 2 } {
      set y [ expr $y >> 4 ]
	append decoded \
	  [binary format c [expr ( $y & 0x0000ff ) ]]
    }
    return $decoded
  }
}

proc GetFile { varName args } {
    set x [eval mpi_getOpenFile $args]
    if {[lempty $x]} { return }
    upvar $varName var
    set var $x
}

proc GetDir { varName args } {
    upvar $varName var
    if {[info exists var]} { lappend args -initialdir $var }
    set x [eval mpi_chooseDirectory $args]
    if {[string length $x]} { set var $x }
}

proc GetImageFile {varName} {
    set types {
    	{"Images"		{.gif .png}}
    }

    set x [mpi_getOpenFile -filetypes $types]
    if {$x == ""} { return }
    upvar $varName var
    set var $x
}

proc GetIconFile { varName } {
    set types {
    	{"Windows Icons"        .ico}
    }

    set x [mpi_getOpenFile -filetypes $types]
    if {$x == ""} { return }
    upvar $varName var
    set var $x
}

proc GetColor { w varName {property 0} } {
    upvar #0 $varName color

    if {$property} { set w [$w edit browsepath] }

    set top [::InstallJammer::TopName .__getColor]

    if {$color eq "" || $color eq "system"} { set color #FFFFFF }

    set newcolor [SelectColor::menu $top [list right $w] -color $color]

    if {![lempty $newcolor]} { set color $newcolor }
}

proc Children {win} {
    set children [winfo children $win]

    set list {}
    foreach w $children {
	lappend list $w
	eval lappend list [Children $w]
    }
    return $list
}

proc ::InstallJammer::EditPaneProc { id } {
    set obj  [$id object]
    set pane [$id component]

    uplevel #0 [list source [::InstallJammer::GetPaneSourceFile $id]]

    ClearTmpVars

    set proc  [::InstallJammer::GetPaneProc $id CreateWindow]
    set old   [string trim [info body $proc] \n]
    set ::TMP $old
    ::editor::new -font "Courier 10" -title "Editing $pane pane for $id" \
        -variable ::TMP
    set body [string trim $::TMP \n]

    if {$body ne $old} {
        proc ::CreateWindow.$id [info args $proc] \n$body\n

        set file [InstallDir Theme/[$id setup]/$id.tcl]
        file mkdir [file dirname $file]

        set fp [open $file w]
        puts  $fp [ProcDefinition ::CreateWindow.$id]
        close $fp

        Modified
    }
}

proc ::InstallJammer::RestorePaneProc { id } {
    set ans [::InstallJammer::MessageBox -icon question -type yesno \
        -message "Are you sure you want to restore the original code\
                        for this pane?"]
    if {$ans eq "yes"} {
        set file [InstallDir Theme/[$id setup]/$id.tcl]
        file delete $file

        if {[::InstallJammer::CommandExists ::CreateWindow.$id]} {
            rename ::CreateWindow.$id ""
        }
    }
}

proc EditTextField { id field title varName {multilang 1} args } {
    global conf
    upvar #0 $varName var

    variable ::InstallJammer::languages

    if {![::InstallJammer::ObjExists $id]} {
        set id [::InstallJammer::GetActiveComponent]
    }

    if {[GetPref Editor] ne ""} {
        set cmd [list ::InstallJammer::FinishExternalEditTextField $id $field]
        ::InstallJammer::LaunchExternalEditor $var $cmd
        return
    }

    set conf(editOldText)   $var
    set conf(editTextField) [list $id $field]

    set args [linsert $args 0 -title $title -variable $varName]

    if {$multilang} {
        set args [linsert $args 0 -languages 1 \
            -languagecommand ::InstallJammer::EditorLanguageChanged]
    }

    set res [eval ::editor::new $args]

    if {$multilang} {
        if {$res} {
            if {[string index $var end] eq "\n"} {
                set var [string range $var 0 end-1]
            }

            if {$var ne $conf(editOldText)} {
                set lang [list [::editor::language]]
                ::InstallJammer::SetVirtualText $lang $id $field $var
            }
        }

        set var [::InstallJammer::GetText $id $field -subst 0]
    }

    if {$var ne $conf(editOldText)} { Modified }
}

proc ::InstallJammer::EditorLanguageChanged {} {
    global conf

    variable languages

    lassign $conf(editTextField) id field

    if {[::editor::modified]} {
        set ans [::InstallJammer::Message \
            -type yesnocancel -title "Text Modified" \
            -message "Text has been modified.  Do you want to save changes?"]

        if {$ans eq "cancel"} { return }
        if {$ans eq "yes"} {
            set lang [list [::editor::lastlanguage]]
            set text [::editor::gettext]
            if {[string index $text end] eq "\n"} {
                set text [string range $text 0 end-1]
            }
            ::InstallJammer::SetVirtualText $lang $id $field $text
            Modified
        }
    }

    set lang [list [::editor::language]]
    set text [::InstallJammer::GetText $id $field -language $lang -subst 0]

    ::editor::settext $text

    set conf(editOldText) $text
}

proc BindMouseWheel { w {cmd WheelScroll} } {
    set top [winfo toplevel $w]
    switch -- $::tcl_platform(platform) {
	"windows" {
	    bind $top <MouseWheel> "$cmd $w 5 units %D"
	    bind $top <Control-MouseWheel> "$cmd $w 1 units %D"
	    bind $top <Shift-MouseWheel> "$cmd $w 1 pages %D"
	}

	"unix" {
	    bind $top <4> "$cmd $w -5 units"
	    bind $top <5> "$cmd $w  5 units"
	    bind $top <Control-4> "$cmd $w -1 units"
	    bind $top <Control-5> "$cmd $w  1 units"
	    bind $top <Shift-4> "$cmd $w -1 pages"
	    bind $top <Shift-5> "$cmd $w  1 pages"
	}
    }
}

proc WheelScroll {w num type {delta 0}} {
    if {$delta > 0} { set num -$num }
    $w yview scroll $num $type
}

proc Modified { {status 1} } {
    if {$status != $::conf(modified)} {
        set ::conf(modified) $status
        ::InstallJammer::SetMainWindowTitle
    }
}

proc ::InstallJammer::FilesModified { {status 1} } {
    set ::conf(filesModified) $status
}

proc ClearTmpVars {} {
    unset -nocomplain ::TMP
    unset -nocomplain ::TMPARRAY
    unset -nocomplain ::platforms
}

proc InstallDirList { platform {group ""} } {
    global conf
    global info
    global widg

    set list [list <%InstallDir%> <%ProgramFolder%> <%Temp%> <%Home%>]

    if {[string equal $platform "Windows"]} {
	foreach dir [lsort $conf(WindowsSpecialDirs)] { lappend list <%$dir%> }
    } else {
	#lappend list <%CommonStartMenu%>
	#lappend list <%KDEDesktop%> <%KDEStartMenu%> <%KDECommonStartMenu%>
	#lappend list <%GnomeDesktop%> <%GnomeStartMenu%>
        #lappend list <%GnomeCommonStartMenu%>
	lappend list <%KDEDesktop%> <%GnomeDesktop%>
	lappend list /usr/bin /usr/local/bin /opt
    }

    foreach filegroup [FileGroups children] {
        lappend list "<%FileGroup [$filegroup name]%>"
    }

    return $list
}

proc ::InstallJammer::CheckForInstallDirLoop { id destination } {
    ## If it's not another file group, we're not gonna' loop.
    if {![regexp {<%FileGroup (.*)%>} $destination -> folder]} { return 1 }

    set list   [list [::InstallJammer::GetFileSource $id]]
    set groups [FileGroups children]
    while {1} {
        set obj [::InstallJammer::FindObjByName $folder $groups]
        if {![string length $obj]} { return 1 }

        lappend list $folder

	## Check the destination dir.  If it's not a file group, we're done.
        set dir [$obj get Destination]
	if {![regexp {<%FileGroup (.*)%>} $dir -> folder]} { return 1 }

        if {[lsearch -exact $list $folder] > -1} { return 0 }
    }

    return 1
}

proc AddComponent { setup args } {
    array set _args {
        -id      ""
        -parent  "root"
    }
    array set _args $args

    set id     $_args(-id)
    set parent $_args(-parent)

    switch -- [$id type] {
        "pane" - "window" {
            set command ::InstallJammer::AddPane
            set result [eval [list $command $setup [$id component]] $args]
        }

        "action" {
            set command ::InstallJammer::AddAction
            set result [eval [list $command $setup [$id component]] $args]
        }

        "actiongroup" {
            set command ::InstallJammer::AddActionGroup
            set result [eval [list $command $setup] $args -edit 0]
        }
    }

    return $result
}

proc ::InstallJammer::AddPane { setup pane args } {
    global widg

    variable ::InstallJammer::panes

    set obj    $panes($pane)
    set pref   $widg($setup)
    set sel    [lindex [$pref selection get] 0]
    set parent [::InstallJammer::Tree::GetPaneParent $pref $sel]

    set title [$obj title]
    if {![string length $title]} { $obj get Title value title }

    set data(-id)     ""
    set data(-index)  end
    set data(-title)  $title
    set data(-parent) $parent
    set data(-addnew) 1
    array set data $args

    set id     $data(-id)
    set index  $data(-index)
    set parent $data(-parent)

    if {[lempty $parent]} {
        ::InstallJammer::Error -message "You cannot add a pane here."
        return
    }

    set image [GetImage appdisplay16]

    set new 0
    if {![string length $id]} {
        set new  1

        if {[string length $sel]} {
            if {![$sel is installtype]} { set index [$pref index $sel] }
        }

        set id   [::InstallJammer::uuid]
        set type pane
        if {[$obj get Toplevel value toplevel] && $toplevel} { set type window }
        InstallComponent ::$id -parent $parent -setup $setup -index $index \
            -component $pane -type $type -title $data(-title)

        if {[lsearch -exact [$panes($pane) installtypes] "Common"] < 0} {
            $id set Active Yes
        }
    }

    $obj initialize $id

    foreach field [$obj textfields] {
        $obj get $field subst subst
        $id set -safe $field \
            [::InstallJammer::GetText $id $field -label 1 -subst 0]
        $id set -safe $field,subst $subst
    }

    $pref insert $index $parent $id -text $data(-title) -image $image \
        -data pane -createcommand [list CreatePaneFrame $id] \
        -fill [expr {$new ? "#0000FF" : "#000000"}]

    if {$new && $data(-addnew)} {
        variable ::InstallJammer::actions

        ## Add all the conditions for this pane.
        foreach list [$obj conditions pane] {
            lassign $list condition args
            set cid  [::InstallJammer::AddCondition $condition -parent $id]
            set cobj [$cid object]

            unset -nocomplain tmp
            array set tmp $args

            if {[info exists tmp(<Title>)]} {
                $cid title $tmp(<Title>)
                unset tmp(<Title>)
            }

            set props [$cobj properties]
            set texts [$cobj textfields]

            foreach [list arg val] [array get tmp] {
                if {[lsearch -exact $props $arg] > -1} {
                    $cid set $arg $val
                } elseif {[lsearch -exact $texts $arg] > -1} {
                    ::InstallJammer::SetVirtualText en $cid [list $arg $val]
                }
            }
        }

        ## Add all the actions for this pane.
        set actionlist [$obj actions]
        if {[lempty $actionlist]} { $pref itemconfigure $id -open 1 }

        foreach list $actionlist {
            incr0 i

            lassign $list action args

            set aobj $actions($action)

            unset -nocomplain tmp
            array set tmp $args

            ## Make a special case for an argument called <InstallMode>
            ## that specifies that this action should only be added
            ## if we're adding to that install mode.
            if {[info exists tmp(<InstallMode>)]} {
                if {$parent ne "$tmp(<InstallMode>)Install"} { continue }
                unset tmp(<InstallMode>)
            }

            ## Make a special case for an argument called <Title>
            ## that specifies the title of the object.
            set title [$aobj title]
            if {[info exists tmp(<Title>)]} {
                set title $tmp(<Title>)
                unset tmp(<Title>)
            }

            set act [::InstallJammer::AddAction $setup $action \
                -parent $id -title $title]

            set props [$aobj properties]
            set texts [$aobj textfields]

            ## Walk through the arguments for this action and setup
            ## any text fields and properties that were passed.
            foreach [list arg val] [array get tmp] {
                if {[lsearch -exact $props $arg] > -1} {
                    $act set $arg $val
                } elseif {[lsearch -exact $texts $arg] > -1} {
                    ::InstallJammer::SetVirtualText en $act [list $arg $val]
                }
            }

            ## Add any conditions for this action.
            foreach list [$obj conditions action$i] {
                lassign $list condition args
                set cid  [::InstallJammer::AddCondition $condition -parent $act]
                set cobj [$cid object]

                unset -nocomplain tmp
                array set tmp $args

                if {[info exists tmp(<Title>)]} {
                    $cid title $tmp(<Title>)
                    unset tmp(<Title>)
                }

                set props [$cobj properties]
                set texts [$cobj textfields]

                foreach [list arg val] $args {
                    if {[lsearch -exact $props $arg] > -1} {
                        $cid set $arg $val
                    } elseif {[lsearch -exact $texts $arg] > -1} {
                        ::InstallJammer::SetVirtualText en $cid [list $arg $val]
                    }
                }
            }
        }
    }

    Modified

    ::InstallJammer::RefreshComponentTitles $id

    return $id
}

proc CreatePaneFrame { id } {
    global widg

    variable ::InstallJammer::panes
    
    set pane  [$id component]
    set setup [$id setup]

    set obj  $panes($pane)
    set pref $widg($setup)

    set frame [$pref getframe $id]

    if {[winfo exists $frame.sw]} { return }

    ScrolledWindow $frame.sw -scrollbar vertical

    set prop [PROPERTIES $frame.sw.p]
    pack $frame.sw -expand 1 -fill both
    $frame.sw setwidget $frame.sw.p

    set f [frame $frame.buttons]
    pack $f -side bottom -anchor se -pady 2

    BUTTON $f.design  -text "Edit Pane Code" -width 18 \
        -command [list ::InstallJammer::EditPaneProc $id]
    pack   $f.design -side left -padx 5

    BUTTON $f.restore  -text "Restore Original Pane" -width 18 \
        -command [list ::InstallJammer::RestorePaneProc $id]
    pack   $f.restore -side left -padx [list 0 20]

    BUTTON $f.preview -text "Preview Pane" -width 18 \
        -command [list ::InstallJammer::PreviewWindow $id]
    pack   $f.preview -side left

    $prop insert end root standard -text "Standard Properties" -open 1
    if {[llength [$obj properties 0]]} {
        $prop insert end root advanced -text "Advanced Properties" -open 0
    }
    $obj addproperties $prop $id

    $prop insert end root text -text "Text Properties"
    $obj addtextfields $prop text $id
}

proc AddProperty { prop index parent id name varName args } {
    upvar #0 $varName var

    array set data {
        -node    "#auto"
        -type    ""
        -data    ""
        -help    ""
        -pretty  ""
        -choices ""
    }
    array set data $args

    set type $data(-type)
    if {[string equal $type "hidden"]} { return }

    set scmd ::InstallJammer::StartEditPropertyNode
    set fcmd ::InstallJammer::FinishEditPropertyNode
    set opts [list -text $data(-pretty) -variable $varName]
    lappend opts -data $data(-data) -helptext $data(-help)
    lappend opts -browseargs [list -style Toolbutton]
    lappend opts -editstartcommand  [list $scmd $prop $id $name $type $varName]
    lappend opts -editfinishcommand [list $fcmd $prop $id $name $type $varName]

    switch -- $data(-type) {
        "text" {
            set title "Edit [::InstallJammer::StringToTitle $name]"
            lappend opts -browsebutton 1
            lappend opts -browsecommand
            lappend opts [list EditTextField $id $name $title $varName 0]
        }

        "code" {
            set title "Edit [::InstallJammer::StringToTitle $name]"
            lappend opts -browsebutton 1
            lappend opts -browsecommand
            lappend opts [list EditTextField $id $name $title $varName 0 \
                                -font "Courier 10"]
        }

        "file" {
            lappend opts -browsebutton 1
            lappend opts -browsecommand [list GetFile $varName]
        }

        "image" {
            lappend opts -browsebutton 1
            lappend opts -browsecommand [list GetImageFile $varName]
        }

        "boolean" - "yesno" {
            if {[info exists var]} {
                if {[string is true $var]} {
                    set var Yes
                } else {
                    set var No
                }
            }
            lappend opts -values [list Yes No] -editable 0
        }

        "nullboolean" {
            lappend opts -values [list "" Yes No] -editable 0
        }

        "editboolean" {
            lappend opts -values [list "" Yes No] -editable 1
        }

        "color" {
            lappend opts -browsebutton 1
            lappend opts -browsecommand [list GetColor %W $varName 1]
        }

        "installedfile" {
            lappend opts -valuescommand [list InstallDirList Windows]
        }

        "windowsicon" {
            lappend opts -browsebutton  1
            lappend opts -browsecommand [list GetIconFile $varName]
            lappend opts -valuescommand [list GetIconList]
        }

        "choice" - "editchoice" {
            lappend opts -values $data(-choices)
            lappend opts -editable [expr {$data(-type) eq "editchoice"}]
        }

        "anchor" {
            set list [list center n ne e se s sw w nw]
            lappend opts -values $list -editable 0
        }

        "buttons" {
            variable ::InstallJammer::theme
            lappend opts -values $theme(Buttons) -editable 0
        }

        "readonly" {
            lappend opts -state disabled
        }

        "action" {
            lappend opts -valuescommand ::InstallJammer::ActionList
        }

        "conditions" {
            lappend opts -editable     0
            lappend opts -browsebutton 1
            lappend opts -browsecommand
            lappend opts [list ::InstallJammer::ConditionsWizard active]
        }

        "pane" - "window" {
            lappend opts -valuescommand
	    lappend opts ::InstallJammer::GetPaneListForActiveComponent
        }

        "filemethod" {
            lappend opts -editable 0
            lappend opts -values $::InstallJammer::PropertyMap(FileUpdateMethod)
        }

        "custom" {
            set command Edit.[$id component].$name

            lappend opts -browsebutton  1
            lappend opts -browsecommand [list $command $id]
        }

        "widget" {
            lappend opts -valuescommand
            lappend opts [list ::InstallJammer::FindWidgetsForID $id]
        }

        "language" {
            lappend opts -editable 0
            lappend opts -valuescommand "::InstallJammer::GetLanguages 1"
        }

        "location" {
            lappend opts -editable 0
            lappend opts -browsebutton  1
            lappend opts -browsecommand [list ::InstallJammer::EditLocation $id]
        }

        "stringmap" {
            set title "Edit [::InstallJammer::StringToTitle $name]"
            lappend opts -browsebutton 1
            lappend opts -browsecommand
            lappend opts [list EditTextField $id $name $title $varName 0]
        }

        "addwidgettype" {
            lappend opts -values $data(-choices)
            lappend opts -editable [expr {$data(-type) eq "editchoice"}]
            lappend opts -modifycommand
            lappend opts [list ::InstallJammer::ConfigureAddWidgetFrame $id]
        }

        "platform" {
            lappend opts -valuescommand "AllPlatforms"
        }
    }

    eval $prop insert $index $parent $data(-node) $opts
}

proc ::InstallJammer::CheckAlias { id alias {showError 1} } {
    variable aliases

    if {$alias eq "all"} {
        if {$showError} {
            ::InstallJammer::Error -message \
                "The word '$alias' is reserved and cannot be used as an alias"
        }
        return 0
    }

    if {[info exists aliases($alias)] && $aliases($alias) ne $id} {
        if {$showError} {
            ::InstallJammer::Error -message \
                "The alias '$alias' is being used by another object"
        }
        return 0
    }

    return 1
}

proc ::InstallJammer::SetActivePropertyNode { path } {
    global conf

    set conf(editprop) $path
    set conf(editnode) [$path edit current]
}

proc ::InstallJammer::FinishEditingActiveNode { w } {
    global conf

    if {![info exists conf(editprop)]} { return }
    if {![winfo exists $conf(editprop)]} { return }
    if {[$conf(editprop) edit active] eq ""} { return }

    if {[string match "$w*" $conf(editprop)]} { return }
    if {[string match "$conf(editprop)*" $w]} { return }

    set window [$conf(editprop) edit editwindow]
    if {$window ne "" && [string match "$window*" $w]} { return }

    $conf(editprop) edit finish
    unset -nocomplain conf(editprop) conf(editnode)
}

proc ::InstallJammer::StartEditPropertyNode { path id property type varName } {

}

proc ::InstallJammer::FinishEditPropertyNode { path id property type varName } {
    global widg

    upvar #0 $varName var

    set updatefiles 0
    if {$id eq "file" || $id eq "multiplefiles"} {
        set updatefiles 1
        set ids [::FileGroupTree::GetSelectedItems]
    } elseif {$id eq "condition"} {
        set id [::InstallJammer::GetActiveCondition]
        if {![::InstallJammer::ObjExists $id]} { return 1 }
        set ids [list $id]
    } else {
        set id [::InstallJammer::GetActiveComponent]
        if {![::InstallJammer::ObjExists $id]} { return 1 }
        set ids [list $id]
    }

    foreach id $ids {
        switch -- $property {
            "Name" {
                if {[$id is filegroup component setuptype]} {
                    ::InstallJammer::RenameComponent $id $var
                }
            }

            "Alias" {
                if {![::InstallJammer::CheckAlias $id $var]} { return 0 }

                if {[$id is pane action actiongroup]} {
                    set alias   [$id alias]
                    set default [::InstallJammer::GetDefaultTitle $id]
                    if {$var eq "" && ($alias eq "" || $alias eq [$id title])} {
                        $id title $default
                    } elseif {[$id title] eq $default} {
                        $id title $var
                    }
                    set tree $widg([$id setup]Tree)
                    $tree itemconfigure $id -text [$id title]
                }
            }

            "Destination" {
                if {[$id is filegroup]
                    && ![::InstallJammer::CheckForInstallDirLoop $id $var]} {
                    ::InstallJammer::MessageBox -message \
                        "Destination creates an infinite loop."
                    after idle [list focus [$path edit entrypath]]
                    return 0
                }
            }
        }
    }

    switch -- $type {
        "installedfile" {
            set var [string trim $var]
        }

        "stringmap" {
            set var [string trim $var]

            if {[catch { llength $var } len] || [expr {$len % 2}]} {
                ::InstallJammer::MessageBox -icon error -message \
                    "Invalid string map.  Must be an even number of values."
                after idle [list focus [$path edit entrypath]]
                return 0
            }
        }

        "version" {
            set ver [::InstallJammer::SubstText $var]
            if {[string length $ver]
                && [scan $ver "%d.%d.%d.%d" major minor patch build] != 4} {
                ::InstallJammer::MessageBox -icon error -message \
                    "Invalid version.  Must be in the format X.X.X.X"
                after idle [list focus [$path edit entrypath]]
                return 0
            }
        }
    }

    if {$updatefiles} {
        if {$var != [$path edit value]} {
            ::FileGroupTree::UpdateSelectedItems $property $var
        }
    } else {
        if {$var != [$path edit value]} { Modified }
        $id set $property $var
    }

    return 1
}

proc ::InstallJammer::EditVersionNode { name } {
    variable ::InstallJammer::active

    lassign [split $active($name) .] \
        active(MajorVersion) active(MinorVersion) \
        active(PatchVersion) active(BuildVersion)

    foreach x [list Major Minor Patch Build] {
        if {![string length $active(${x}Version)]} {
            set active(${x}Version) 0
        }
    }

    return 1
}

proc ::InstallJammer::EditTextFieldNode { path id field varName substVarName } {
    global conf

    set conf(editTextField) [list $id $field]

    set frame [$path edit editpath]
    set entry [$path edit entrypath]
    set check $path.editTextFieldSubst

    $check configure -variable $substVarName
    pack  $check -in $frame -side left -before $entry
    raise $check

    return 1
}

proc ::InstallJammer::FinishEditTextFieldNode { path id field varName
                                                substVarName } {
    upvar #0 $varName var $substVarName subst
    set newtext $var

    if {[catch { $id title }]} {
        set id $::InstallJammer::ActiveComponent
    }

    if {$subst && ![::InstallJammer::CheckVirtualText $newtext]} { return 0 }

    if {$newtext ne [::InstallJammer::GetText $id $field -subst 0]} {
        ::InstallJammer::SetVirtualText en $id [list $field $newtext]
        Modified
    }
    return 1
}
proc ::InstallJammer::FinishExternalEditTextField { id field old new } {
    ::InstallJammer::SetVirtualText en $id $field $new
    ::InstallJammer::UpdateActiveComponent
    Modified
}

proc ::InstallJammer::FinishEditPlatformNode { path id property varName } {
    upvar #0 $varName var

    if {$var != [$path edit value]} { Modified }

    set platform  [$path itemcget $property -data]
    set original  [$id platforms]
    set platforms $original

    if {$var} {
        lappend platforms $platform
    } else {
        set platforms [lremove $platforms $platform]
    }
    set platforms [lsort -unique $platforms]

    if {[llength $platforms] != [llength $original]} {
        $id platforms $platforms
        Modified
    }

    return 1
}

proc ::InstallJammer::FinishEditPlatformPropertyNode { path parent node } {
    set value [$path itemcget $node -value]

    if {![::InstallJammer::CheckVirtualText $value]} { return 0 }

    if {$value != [$path edit value]} { Modified }

    set platform [$path itemcget $parent -data]
    set property [$path itemcget $node -data]

    $platform set $property $value

    return 1
}

proc GetComponentList { {setup ""} {activeOnly 0} } {
    global conf

    set list [list]

    foreach id [::itcl::find objects -isa InstallComponent] {
        if {$setup ne "" && [$id setup] ne $setup} { continue }
        if {$activeOnly && ![$id active]} { continue }
        lappend list $id
    }

    return $list
}

proc GetPaneComponentList { {setup Install} {activeOnly 0} } {
    set list [list]
    foreach id [GetComponentList $setup $activeOnly] {
        if {[$id ispane]} { lappend list $id }
    }

    return $list
}

proc GetPaneList { {setup Install} {activeOnly 0} } {
    set panes [list]
    foreach id [GetPaneComponentList $setup $activeOnly] {
        lappend panes [$id component]
    }
    return [lsort -unique $panes]
}

proc ::InstallJammer::GetPaneListForActiveComponent {} {
    set id [::InstallJammer::GetActiveComponent]
    return [GetPaneComponentList [$id setup]]
}

proc GetImageList { setup {activeOnly 0} } {
    variable ::InstallJammer::ComponentObjectMap

    set images [list]
    foreach id [GetComponentList $setup $activeOnly] {
        if {![info exists ComponentObjectMap($id)]} { continue }
	foreach img [$ComponentObjectMap($id) images] {
	    lappend images $id $img
	}
    }
    return $images
}

proc GetImageData { setups {activeOnly 0} } {
    global conf
    global info

    foreach setup $setups {
        foreach [list id image] [GetImageList $setup $activeOnly] {
            set img  [$id get $image]
            set name [::InstallJammer::SubstText $img]
            set file $name
            if {$file eq ""} { continue }

            if {[file pathtype $file] eq "relative"
                && ![::InstallJammer::HasVirtualText $file]} {
                ## The image file's path is relative.  Look for it
                ## first in our project directory and then in the
                ## InstallJammer Images/ directory.
                if {[file exists [file join $info(ProjectDir) $file]]} {
                    set file [file join $info(ProjectDir) $file]
                } elseif {[file exists [file join $conf(pwd) Images $file]]} {
                    set file [file join $conf(pwd) Images $file]
                }
            }

            set imageArray($id,$image) $img
            if {[file exists $file]} {
                set name [::InstallJammer::Normalize $name unix]
                set files($name) [file normalize $file]
            }
        }
    }

    set data "array set ::images [list [array get imageArray]]\n"
    foreach {name file} [array get files] {
        if {![file exists $file]} { continue }
        set x [list [::base64::encode_file $file]]
	append data "set \"::images($name)\" \[image create photo -data $x]\n"
    }

    return $data
}

proc ShrinkCode { string } {
    set output ""
    foreach line [split [string trim $string] \n] {
	set line [string trim $line]
	## Drop comments.
	if {[string index $line 0] == "#"} { continue }

	## Merge split lines back
	if {[string index $line end] == "\\"} {
	    append output [string replace $line end end " "]
	} else {
	    append output $line\n
	}
    }

    return $output
}

proc ShrinkFile {file} {
    if {[file exists $file]} {
        return [ShrinkCode [read_file $file]]
    }
}

proc ::InstallJammer::Explore { {initdir ""} } {
    global conf
    global preferences

    set explorer ""

    if {$initdir ne "" && ![file exists $initdir]} {
        ::InstallJammer::Error -message \
	    "Directory '$initdir' does not exist"
        return
    }

    if {[info exists preferences(FileExplorer)] 
	&& $preferences(FileExplorer) ne ""} {
	set explorer [list exec $preferences(FileExplorer)]
    } else {
        if {$conf(windows)} {
	    set explorer [list exec [auto_execok explorer.exe]]
            if {$initdir ne ""} {
                set initdir  [file nativename $initdir]
                set explorer [list ::installkit::Windows::shellExecute explore]
	    }
        } elseif {$conf(osx)} {
            set explorer [list exec open]
	} else {
            set explorer [list exec xdg-open]
            if {$initdir eq ""} { set initdir [file normalize ~] }
	}
    }

    if {$explorer eq ""} {
        ::InstallJammer::Error -message \
	    "Could not find a suitable file explorer."
	return
    }

    Status "Launching File Explorer..." 3000

    if {$initdir eq ""} {
	set res [catch { eval $explorer & } error]
    } else {
	set res [catch { eval $explorer [list $initdir] & } error]
    }

    if {$res} {
        ::InstallJammer::MessageBox -message $error
    }
}

proc NextProjectName { project {start 2} } {
    global preferences

    set dirs [list]
    foreach filename $preferences(RecentProjects) {
        lappend dirs [file dirname $filename]
        lappend dirs [file dirname [file dirname $filename]]
    }

    set n [lindex $project end]
    if {![string is integer $n]} {
        set n $start
        set new "$project $n"
    } else {
        set project [lrange $project 0 end-1]
        set new "$project [incr n]"
    }

    while {1} {
        set found 0
        foreach dir [lsort -unique $dirs] {
            if {[file exists [file join $dir $new]]} { set found 1; break }
        }
        if {!$found} { return $new }
        set new "$project [incr n]"
    }
}

proc GetImage { image } {
    return [InstallJammerIcons image $image]
}

proc GetIconList {} {
    return [glob -nocomplain -tails -directory $::conf(winico) *.ico]
}

proc SetIconTheme {} {
    global conf
    global widg

    IconLibrary InstallJammerIcons

    set prefs prefs
    if {[IsWindowsXP]} { set prefs xpprefs }

    set dir  [file join $conf(lib) Icons]
    set file [file join $dir InstallJammer.tkico]

    ## Load the common InstallJammer icons.
    InstallJammerIcons load -file $file -groups [list common crystal $prefs]

    ## Load the Crystal theme icons for InstallJammer.
    set file [file join $dir InstallJammer.crystal.png.tkico]
    InstallJammerIcons load -file $file

    set file [file join $dir InstallJammer.crystal.dialog.png.tkico]
    InstallJammerIcons load -file $file

    set file [file join $dir InstallJammer.crystal.toolbar.png.tkico]
    InstallJammerIcons load -file $file

    ## Create the checked file and folder icons.
    foreach icon [list folder16 filedocument16] {
        InstallJammerIcons add check$icon -create 1
        set image [GetImage check$icon]
        $image copy [GetImage $icon]
        $image copy [GetImage check]
    }
}

proc GetPref {pref} {
    global info
    global preferences

    if {[info exists preferences($pref)]} { return $preferences($pref) }
    if {[info exists info($pref)]} { return $info($pref) }
    return 0
}

proc ValidateSpinBox {w oldString newString} {
    if {![string is integer $newString]} { return 0 }
    return 1
}

proc IsWindows {} {
    if {$::tcl_platform(platform) ne "windows"} { return 0 }
    if {$::tcl_platform(osVersion) > 5.0} { return 0 }
    return 1
}

proc IsWindowsXP {} {
    if {$::tcl_platform(platform) ne "windows"} { return 0 }
    if {$::tcl_platform(osVersion) < 5.1} { return 0 }
    return 1
}

proc ::InstallJammer::SetMenuState {menu state} {
    for {set i 0} {$i < [$menu index end]} {incr i} {
	if {[$menu type $i] == "separator"} { continue }
	$menu entryconfigure $i -state $state
    }
}

proc ::InstallJammer::TopName { name } {
    global widg
    if {![string equal [string index $name 0] "."]} { set name .$name }
    return $widg(InstallJammer)$name
}

proc ::InstallJammer::PaneWindowBody { id prefix } {
    set pane [$id component]

    set proc ::InstallJammer::preview::$prefix.$id
    if {![::InstallJammer::CommandExists $proc]} {
    	set proc ::InstallJammer::preview::$prefix.$pane
    }
    if {![::InstallJammer::CommandExists $proc]} { return }
    return [info body $proc]
}

proc ::InstallJammer::Error { args } {
    global widg
    set args [linsert $args 0 -title "InstallJammer Error" -icon error]
    eval ::InstallJammer::MessageBox $args
}

proc ::InstallJammer::CopyPropertiesValue {} {
    global conf
    set data [$conf(prop) itemcget $conf(node) -value]
    if {$data eq ""} { return }
    clipboard clear
    clipboard append $data
}

proc ::InstallJammer::PastePropertiesValue {} {
    global conf

    set data [clipboard get]

    ## Edit the property
    $conf(prop) edit start $conf(node)

    set values   [$conf(prop) edit values]
    set editable [$conf(prop) edit editable]

    if {[llength $values] && !$editable && [lsearch -exact $values $data] < 0} {
        ## This property has a strict list of values, and our new value
        ## doesn't match anything in the list.
        $conf(prop) edit cancel
    } else {
        ## Get the variable for the node we're editing.
        upvar #0 [$conf(prop) variable $conf(node)] value

        ## Set the new value to the contents of the clipboard.
        set value $data

        ## Finish editing the property.
        $conf(prop) edit finish
    }
}

proc ::InstallJammer::GetSetupTypeNames { platform } {
    set names [list]
    foreach id [SetupTypes children] {
        if {[lsearch -exact [$id platforms] $platform] > -1} {
            lappend names [$id name]
        }
    }
    return $names
}

proc ::InstallJammer::SetMainWindowTitle {} {
    global info
    global conf
    global widg

    if {$conf(cmdline) || $conf(loading)} { return }

    set percent [expr {$conf(building) ? "$conf(buildProgress)% " : ""}]

    set mod [expr {$conf(modified) ? "*" : ""}]

    set title "${percent}InstallJammer - "
    if {![info exists info(Project)] || ![string length $info(Project)]} {
        append title "Multiplatform Installer"
    } else {
        append title "$info(Project) ${mod}($info(ProjectFile))"
    }

    if {$title ne [wm title $widg(InstallJammer)]} {
        wm title $widg(InstallJammer) $title
    }
}

proc ::InstallJammer::FlashMainWindow {} {
    global conf
    global widg

    if {![info exists conf(hwin)]} { return }
    if {[wm state $widg(InstallJammer)] ne "iconic"} { return }

    twapi::flash_window_caption $conf(hwin) -toggle

    after 1000 ::InstallJammer::FlashMainWindow
}

proc ::InstallJammer::BooleanValue { value } {
    return [expr {$value ? "Yes" : "No"}]
}

proc ::InstallJammer::AskYesNo { args } {
    set ans [eval [list ::InstallJammer::MessageBox -type yesno] $args]
    return [string equal $ans "yes"]
}

proc ::InstallJammer::Dialog { args } {
    variable count
    if {![info exists count]} { set count 0 }

    if {![llength $args] || [string index [lindex $args 0] 0] eq "-"} {
        set path .__dialog[incr count]
    } else {
        set path [lindex $args 0]
        set args [lrange $args 1 end]
    }
    set path [::InstallJammer::TopName $path]
    eval [list StandardDialog $path] $args
}

proc ::InstallJammer::StringToTitle { string } {
    if {[regexp {[_-]} $string]} {
        set words [split $string _-]
    } else {
        regsub -all {[A-Z]} $string { \0} words
    }

    foreach word $words {
        lappend list [string toupper $word 0]
    }

    return [join $list " "]
}

proc ::InstallJammer::SaveActiveComponent {} {
    variable ::InstallJammer::active
    variable ::InstallJammer::Properties

    if {[info exists ::InstallJammer::ActiveComponent]} {
        ## Store the previous active component's values
        ## into the Properties array.
        set old $::InstallJammer::ActiveComponent
        if {![catch { $old object } obj]} {
            foreach prop [$obj properties] {
                if {$prop eq "ID" || $prop eq "Component"} { continue }
                set Properties($old,$prop) $active($prop)
            }

            foreach prop [$obj textfields] {
                set Properties($old,$prop,subst) $active($prop,subst)
            }
        }
    }
}

proc ::InstallJammer::UpdateActiveComponent {} {
    variable ::InstallJammer::active
    variable ::InstallJammer::Properties

    set id [::InstallJammer::GetActiveComponent]
    if {[catch { $id object } obj]} { return }

    foreach var [array names active] {
        set active($var) ""
    }

    foreach prop [$obj properties] {
        set active($prop) $Properties($id,$prop)
    }

    foreach prop [$obj textfields] {
        set active($prop) [::InstallJammer::GetText $id $prop -subst 0 -label 1]
        set active($prop,subst) $Properties($id,$prop,subst)
    }

    set active(ID)        $id
    set active(Component) [[$id object] title]

    ::InstallJammer::SetActiveComponentConditions
}

proc ::InstallJammer::SetActiveComponent { {id ""} } {
    variable ::InstallJammer::active

    ::InstallJammer::SaveActiveComponent

    if {$id eq ""} {
        set active(ID)        ""
        set active(Component) ""
        unset -nocomplain ::InstallJammer::ActiveComponent
        return
    }

    if {![::InstallJammer::ObjExists $id]} { return }

    set ::InstallJammer::ActiveComponent $id
    
    ::InstallJammer::UpdateActiveComponent

    switch -- [$id type] {
        "filegroup" {
            ::InstallJammer::SetHelp GroupsAndFiles
            set ::InstallJammer::ActiveComponents(filegroup) $id
        }

        "file" - "dir" {
            ::InstallJammer::SetHelp FilesAndDirectories
            set ::InstallJammer::ActiveComponents(filegroup) $id
        }

        "component" - "setuptype" {
            set ::InstallJammer::ActiveComponents([$id type]) $id
        }

        "action" {
            ::InstallJammer::SetHelp [$id component]
            set ::InstallJammer::ActiveComponents([$id setup]) $id
        }

        "actiongroup" {
            ::InstallJammer::SetHelp WhatAreActionGroups
            set ::InstallJammer::ActiveComponents([$id setup]) $id
        }

        "pane" {
            ::InstallJammer::SetHelp WhatArePanes
            set ::InstallJammer::ActiveComponents([$id setup]) $id
        }

        default {
            ::InstallJammer::SetHelp TheUserInterfaceTree
            set ::InstallJammer::ActiveComponents([$id setup]) $id
        }
    }
}

proc ::InstallJammer::GetActiveComponent {} {
    if {[info exists ::InstallJammer::ActiveComponent]} {
        return $::InstallJammer::ActiveComponent
    }
}

proc ::InstallJammer::SetActiveProperty {prop value} {
    set ::InstallJammer::active($prop) $value
}

proc ::InstallJammer::RenameComponent { id name } {
    global widg

    set node $id

    switch -- [$id type] {
        "filegroup" {
            set node [::InstallJammer::NodeName $id]
            ::InstallJammer::Tree::DoRename $widg(FileGroupTree) $node $name
        }

        "component" {
            ::InstallJammer::Tree::DoRename $widg(ComponentTree) $node $name
        }

        "setuptype" {
            ::InstallJammer::Tree::DoRename $widg(SetupTypeTree) $node $name
        }

        default {
            $id title $name
        }
    }
}

proc ::InstallJammer::FontConfigure { font args } {
    set command configure
    if {[lsearch -exact [font names] $font] < 0} { set command create }
    eval [list font $command $font] $args
}

proc ::InstallJammer::IsVirtualTextValid { str } {
    return [expr {[regsub -all {<%} $str {} x] == [regsub -all {%>} $str {} x]}]
}

proc ::InstallJammer::CheckVirtualText { string } {
    if {![::InstallJammer::IsVirtualTextValid $string]} {
        ::InstallJammer::Error -message "Virtual text is invalid."
        return 0
    }
    return 1
}

proc ::InstallJammer::FindWidgetsForID { id } {
    set widgets [list]
    switch -- [$id type] {
        "pane" {
            set widgets [::InstallJammer::GetPaneWidgets $id]
        }

        "action" {
            set parent [$id parent]
            if {![$parent is actiongroup]} {
                set widgets [::InstallJammer::GetPaneWidgets $parent]
            }
        }
    }

    set return [list]
    foreach widget $widgets {
        if {[::InstallJammer::ObjExists $widget]} {
            lappend return $widget
        } else {
            lappend return [::InstallJammer::StringToTitle $widget]
        }
    }

    return [lsort $return]
}

proc ::InstallJammer::GetPaneWidgets { id } {
    variable ::InstallJammer::theme
    variable ::InstallJammer::panes

    if {[catch { $id object } obj]} { return }

    set widgets [list]

    foreach line $theme(Buttons) {
        foreach button [split $line /] {
            lappend widgets ${button}Button
        }
    }

    set files [list [$obj tclfile]]

    foreach include [$obj includes] {
        if {[info exists panes($include)]} {
            lappend files [$panes($include) tclfile]
        }
    }

    foreach file $files {
        set x [read_file $file]
        foreach {x widget} [regexp -all -inline -- { widget set ([^ ]+)} $x] {
            lappend widgets $widget
        }
    }

    foreach child [$id children recursive] {
        if {[$child is action] && [$child component] eq "AddWidget"} {
            lappend widgets $child
        }
    }

    return [lsort -unique $widgets]
}

proc ::InstallJammer::Platform {} {
    global tcl_platform

    if {[string equal $tcl_platform(platform) "windows"]} { return Windows }

    set os      $tcl_platform(os)
    set machine $tcl_platform(machine)
    set version $tcl_platform(osVersion)

    switch -glob -- $machine {
	"intel" - "*86" {
            set machine "x86"
        }

	"Power*" {
            set machine "ppc"
        }

	"sun*" {
            set machine "sparc"
        }
    }

    switch -- $os {
	"AIX" {
	    return $os-ppc
	}

        "Darwin" {
            return MacOS-X
        }

        "IRIX" - "IRIX64" {
            return IRIX-mips
        }

        "SunOS" {
	    return Solaris-$machine
	}

	"HP-UX" {
	    return HPUX-hppa
	}

        "FreeBSD" {
    	    set ver [lindex [split $version -] 0]
	    if {[lempty $ver]} { set ver $version }
	    set major [lindex [split $ver .] 0]
	    return $os-$major-$machine
	}

        default {
            return $os-$machine
        }
    }
}

proc ::InstallJammer::FadeWindowIn { window } {
    global conf

    if {$conf(unix)} {
        wm deiconify $window
        return
    }

    wm attributes $window -alpha 0.1
    wm deiconify $window

    for {set i 0} {$i < 1.0} {iincr i 0.03} {
        wm attributes $window -alpha $i
        after 10
        update idletasks
    }

    wm attributes $window -alpha 0.99999
}

proc ::InstallJammer::FadeWindowOut { window {destroy 0} } {
    global conf

    if {$conf(unix)} {
        if {$destroy} {
            destroy $window
        } else {
            wm withdraw $window
        }
        return
    }

    for {set i [wm attrib $window -alpha]} {$i >= .01} {iincr i -0.03} {
        wm attribute $window -alpha $i
        after 10
        update idletasks
    }

    if {$destroy} {
        destroy $window
    } else {
        wm withdraw   $window
        wm attributes $window -alpha 0.99999
    }
}

proc ::InstallJammer::LoadMessages { args } {
    global conf

    array set _args {
        -dir   ""
        -clear 0
    }
    array set _args $args

    if {![string length $_args(-dir)]} {
        set _args(-dir)   [file join $conf(lib) msgs]
        set _args(-clear) 1
    }
    
    set list [list]
    foreach id [itcl::find object -isa ::InstallJammer::ComponentDetails] {
        lappend list [$id name]
    }
    set list [lsort -unique $list]

    foreach file [recursive_glob $_args(-dir) *.msg] {
        set lang [file root [file tail $file]]

        upvar #0 ::InstallJammer::Msgs_$lang messages

        if {$_args(-clear)} {
            ::msgcat::mcclear $lang
            unset -nocomplain messages
        }

        set data [read_textfile $file]

        unset -nocomplain first
        foreach line [split $data \n] {
            set line [string trim $line]
            if {$line eq ""} { continue }
            if {![info exists first]} { set first $line; continue }
            set second $line
            break
        }

        if {![string match {"*"} $second] && ![string match "*\{" $first]} {
            continue
        }
        if {[catch {array set msg $data}]} { continue }
        foreach text [array names msg] {
            if {[lsearch -exact $list $text] > -1} {
                ## This is an action or something, so it has
                ## multiple text definitions.
                foreach {name value} $msg($text) {
                    set messages($text,$name) $value
                    ::msgcat::mcset $lang $text,$name $value
                }
            } else {
                set messages($text) $msg($text)
                ::msgcat::mcset $lang $text $msg($text)
            }
        }

        unset msg
    }
}

proc ::InstallJammer::ArchiveExists { archive } {
    global conf
    return [expr [lsearch -exact $conf(Archives) $archive] > -1]
}

proc ::InstallJammer::GetActiveLanguages {} {
    global info

    variable ::InstallJammer::languages
    variable ::InstallJammer::languagecodes

    set langs [list]

    foreach code [::InstallJammer::GetLanguageCodes] {
        if {$info(Language,$code)} {
            lappend langs $code $languagecodes($code)
        }
    }

    if {[lsearch -exact $langs "English"] < 0} {
    	lappend langs en English
    }

    return $langs
}

proc ::InstallJammer::DumpObject { obj } {
    variable ::InstallJammer::Properties

    ## List = type properties options textproperties children
    set list {}

    lappend list [$obj type]

    $obj properties props
    lappend list [array get props]

    array set opts [$obj serialize]
    foreach opt {-setup -parent -command -conditions} {
        unset -nocomplain opts($opt)
    }

    lappend list [array get opts]

    set textprops {}
    foreach prop [[$obj object] textfields] {
        foreach lang [::InstallJammer::GetLanguageCodes] {
            lappend textprops $prop
            lappend textprops $lang
            lappend textprops [::InstallJammer::GetText $obj $prop -subst 0 \
                -language $lang -forcelang 1]
            lappend textprops [$obj get $prop,subst]
        }
    }

    lappend list $textprops

    set childlist {}
    if {![catch { $obj conditions } conditions]} {
        foreach condition $conditions {
            lappend childlist [::InstallJammer::DumpObject $condition]
        }
    }

    if {![catch { $obj children } children]} {
        foreach child $children {
            lappend childlist [::InstallJammer::DumpObject $child]
        }
    }

    lappend list $childlist

    return $list
}

proc ::InstallJammer::CreateComponentFromDump { setup list {parent ""} } {
    lassign $list type props opts textprops children

    array set _opts $opts

    set component $_opts(-component)

    set args [list]

    if {$parent ne ""} {
        lappend args -parent $parent
    }

    if {[info exists _opts(-title)]} {
        lappend args -title $_opts(-title)
    }

    switch -- $type {
        "pane" - "window" {
            set id [::InstallJammer::AddPane $setup $_opts(-component) \
                -addnew 0 -title $_opts(-title)]
        }

        "action" {
            set id [eval ::InstallJammer::AddAction $setup $component $args]
        }

        "actiongroup" {
            set id [eval ::InstallJammer::AddActionGroup $setup $args -edit 0]
        }

        "condition" {
            set id [eval ::InstallJammer::AddCondition $component $args]
        }
    }

    if {$id ne ""} {
        eval $id configure $opts

        $id set $props

        foreach {prop lang text subst} $textprops {
            ::InstallJammer::SetVirtualText $lang $id $prop $text
            $id set $prop,subst $subst
        }

        foreach childlist $children {
            ::InstallJammer::CreateComponentFromDump $setup $childlist $id
        }
    }
}

proc ::InstallJammer::OutputDir { {file ""} } {
    global conf

    if {[info exists conf(OutputDir)]} {
        set output $conf(OutputDir)
    } else {
    	set output [InstallDir output]
    }

    if {$file ne ""} { set output [file join $output $file] }
    return $output
}

proc ::InstallJammer::BuildDir { {file ""} } {
    global conf

    if {[info exists conf(BuildDir)]} {
        set build $conf(BuildDir)
    } else {
    	set build [InstallDir build]
    }

    if {$file ne ""} { set build [file join $build $file] }
    return $build
}

proc ::InstallJammer::LibDir { {file ""} } {
    global conf
    set return $conf(lib)
    if {$file ne ""} { set return [file join $return $file] }
    return $return
}

proc ::InstallJammer::GetBuildLogFile {} {
    global conf
    if {![info exists conf(buildLogFile)]} {
        set conf(buildLogFile) [InstallDir build.log]
    }
    return $conf(buildLogFile)
}

proc ::InstallJammer::GetDefaultTitle { id } {
    return [[$id object] title]
}

proc ::InstallJammer::OpenTempFile { {varName ""} {mode "w"} } {
    if {$varName ne ""} { upvar 1 $varName file }
    set file [::InstallJammer::TmpDir [pid][clock clicks].tmp]
    return [open $file $mode]
}

proc ::InstallJammer::WatchExternalFile { pid file command n } {
    if {$::conf(watch,$file) ne [file mtime $file]} {
        set ::conf(watch,$file) [file mtime $file]
        set data [read_file $file]
        if {[string index $data end] eq "\n"} {
            set data [string range $data 0 end-1]
        }
        uplevel #0 $command [list $::conf(watch,$file,text) $data]
        set n 10
    }

    ## Every 3 seconds, check to see if the editor process is still
    ## active.  If it's not, do cleanup and stop.
    if {[incr n] >= 10} {
        if {[::InstallAPI::FindProcesses -pid $pid] eq ""} {
            unset -nocomplain ::conf(watch,$file) ::conf(watch,$file,text)
            file delete -force $file
            return
        }
        set n 0
    }
    after 300 [lreplace [info level 0] end end $n]
}

proc ::InstallJammer::LaunchExternalEditor { value command } {
    global conf

    set fp [::InstallJammer::OpenTempFile file]
    puts $fp $value
    close $fp

    set editor [GetPref Editor]
    if {[string match "*%filename%*" $editor]} {
        set editor [string map [list "%filename%" $file] $editor]
    } else {
        lappend editor $file
    }
    set pid [eval exec $editor &]
    set conf(watch,$file) [file mtime $file]
    set conf(watch,$file,text) $value
    ::InstallJammer::WatchExternalFile $pid $file $command 0
}

proc ::InstallJammer::FindFile {file args} {
    if {$file eq ""} { return }
    if {[file pathtype $file] eq "absolute"} { return $file }

    set dirs [linsert $args 0 [InstallDir]]
    foreach dir $dirs {
        set path [file join $dir $file]
        if {[file exists $path]} { return $path }
    }

    return $file
}

proc ::InstallJammer::GetWindowGeometry {window default} {
    global preferences
    variable WindowGeometry

    set geometry $default
    if {[info exists preferences(Geometry,$window)]} {
        set geometry $preferences(Geometry,$window)
        lassign [split $geometry x+] w h x y
        lassign [wm maxsize .] maxW maxH

        ## If this is the first time to display this window, and it's
        ## outside of the viewing area, readjust to use the default geometry.
        if {![info exists WindowGeometry($window)]
            && ($x < 0 || ($x + $w) > $maxW || $y < 0 || ($y + $h) > $maxH)} {
            set geometry $default
        }
    }

    set WindowGeometry($window) $geometry
    return $geometry
}

proc ::InstallJammer::SendReadySignal {} {
    global conf

    if {![info exists conf(commandSocks)]} { return }

    update
    foreach sock $conf(commandSocks) {
        puts  $sock "OK"
        flush $sock
    }
}

proc ::InstallJammer::AcceptCommandConnection {sock ip port} {
    global conf

    lappend conf(commandSocks) $sock
    fconfigure $sock -blocking 0 -buffering line -buffersize 1000000
    fileevent  $sock readable [list ::InstallJammer::ReadCommandPort $sock]
}

proc ::InstallJammer::ReadCommandPort {sock} {
    global conf

    set data [read $sock]

    if {$data eq ""} {
        catch {close $sock}
        set conf(commandSocks) [lremove $conf(commandSocks) $sock]
    } else {
        catch {uplevel #0 $data} result
        puts  $sock $result
        puts  $sock "OK"
        flush $sock
    }
}
Added lib/virtualtext.tcl.


























































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
## $Id$
##
## BEGIN LICENSE BLOCK
##
## Copyright (C) 2002  Damon Courtney
## 
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## version 2 as published by the Free Software Foundation.
## 
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License version 2 for more details.
## 
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the
##     Free Software Foundation, Inc.
##     51 Franklin Street, Fifth Floor
##     Boston, MA  02110-1301, USA.
##
## END LICENSE BLOCK

proc ::InstallJammer::LoadReservedVirtualText {} {
    global conf
    global info
    global widg

    variable InstallJammerVirtualText

    set virtualtext {
        {AutoFileGroups           1}
        {AutoRefreshFiles         1}
        {BuildFailureAction       1}
        {CommandLineFailureAction 1}
        {CompressionLevel         1}
        {CurrentPane              1}
        {Date                     1}
        {DateFormat               1}
        {DefaultDirectoryLocation 1}
        {DefaultLanguage          1}
        {DefaultMode              1}
        {DefaultToSystemLanguage  1}
        {ErrorsOccurred           1}
        {Ext                      1}
        {FileBeingInstalled       1}
        {FileBeingInstalledText   1}
        {FileBeingUninstalled     1}
        {FileBeingUninstalledText 1}
        {FileSize                 1}
        {GroupBeingInstalled      1}
        {GroupBeingInstalledText  1}
        {GUID                     1}
        {Home                     1}
        {Icon                     1}
        {IgnoreDirectories        1}
        {IgnoreFiles              1}
        {Image                    1}
        {InstallFinished          1}
        {InstallID                1}
        {InstallPercentComplete   1}
        {InstallSource            1}
        {InstallStarted           1}
        {InstallStopped           1}
        {Installer                1}
        {InstallerID              1}
        {Installing               1}
        {InstallPassword          1}
        {Language                 1}
        {LastGUID                 1}
        {LastIgnoreDirectories    1}
        {LastIgnoreFiles          1}
        {LastUUID                 1}
        {LicenseAccepted          1}
        {OriginalInstallDir       1}
        {Platform                 1}
        {PreserveFileAttributes   1}
        {PreserveFilePermissions  1}
        {Project                  1}
        {ProjectDir               1}
        {ProjectFile              1}
        {ProjectID                1}
        {ProjectVersion           1}
        {ScriptExt                1}
        {SelectedComponents       1}
        {SelectedFileGroups       1}
        {SilentMode               1}
        {SkipUnusedFileGroups     1}
        {SaveOnlyToplevelDirs     1}
        {SpaceAvailableText       1}
        {SpaceRequired            1}
        {SpaceRequiredText        1}
        {Status                   1}
        {SystemLanguage           1}
        {Temp                     1}
        {TempRoot                 1}
        {Theme                    1}
        {ThemeDir                 1}
        {ThemeVersion             1}
        {UninstallModes           1}
        {UninstallPercentComplete 1}
        {UserMovedBack            1}
        {UserMovedNext            1}
        {Username                 1}
        {WindowsPlatform          1}
        {WizardHeight             1}
        {WizardWidth              1}
        {WizardFirstStep          1}
        {WizardLastStep           1}
    }

    foreach var [concat $conf(InstallVars) $conf(PlatformVars)] {
        lappend virtualtext [list $var 1]
    }

    foreach code [::InstallJammer::GetLanguageCodes] {
        lappend virtualtext [list Language,$code 1]
    }

    foreach list $virtualtext {
        lassign $list var reserved type
        set InstallJammerVirtualText($var) $reserved
    }
}

proc ::InstallJammer::NewVirtualText { listbox } {
    set desc "User-Defined Virtual Text"
    set item [$listbox insert end root #auto -values [list {} {} $desc]]

    $listbox see  item  $item
    $listbox edit start $item 0
}

proc ::InstallJammer::DeleteVirtualText { listbox } {
    global conf

    variable languages

    set lang $languages($conf(VirtualTextLanguage))

    set items [list]
    foreach item [$listbox selection get] name [$listbox get -selected col 0] {
	if {![IsReservedVirtualText $name]} {
            lappend items $item
            ::msgcat::mcunset $lang $name
        }
    }

    set edit [$listbox edit editing]
    if {$edit ne ""} {
        set name [$listbox get $edit col 0]
        ::msgcar::mcunset $lang $name
        lappend items $edit
    }

    if {[llength $items]} {
        eval [list $listbox delete] $items
        Modified
    }
}

proc ::InstallJammer::LongEditVirtualText { w item } {
    global conf

    set name  [lindex [$w get item $item] 0]
    set value [$w edit editvalue]

    if {[GetPref Editor] ne ""} {
        variable languages
        set lang $languages($conf(VirtualTextLanguage))
        set cmd [list ::InstallJammer::FinishExternalEditVirtualText \
            $w $item $name $lang]
        ::InstallJammer::LaunchExternalEditor $value $cmd
        return
    }

    ClearTmpVars

    set ::TMP $value
    ::editor::new -title "Editing $name" -variable ::TMP
    if {[string index $::TMP end] eq "\n"} {
        set ::TMP [string range $::TMP 0 end-1]
    }
    $w edit editvalue $::TMP
    ClearTmpVars
    $w edit finish
}

proc ::InstallJammer::EditStartVirtualText { w item col } {
    set name [$w get value $item 0]
    if {[IsReservedVirtualText $name]} { return 0 }
    return 1
}

proc ::InstallJammer::EditFinishVirtualText { w item col } {
    global conf
    global info

    variable languages

    set lang   $languages($conf(VirtualTextLanguage))
    set name   [lindex [$w get item $item] 0]
    set oldval [$w edit value]
    set newval [$w edit editvalue]

    if {$newval ne $oldval} {
        if {$col == 0} {
            set names [$w get col 0]
            if {[lsearch -exact $names $newval] > -1
                || [::InstallJammer::IsReservedVirtualText $newval]} {
                ::InstallJammer::Error -message \
                    "A virtual text variable with that name already exists."
                $w edit cancel
                return 1
            }

            set val ""
            if {[::msgcat::mcexists $oldval $lang]} {
                set val [::msgcat::mcget $lang $oldval]
            }

            ::msgcat::mcset   $lang $newval $val
            ::msgcat::mcunset $lang $oldval
        } else {
            ::msgcat::mcset $lang $name $newval
        }

        Modified
    }

    if {[info exists conf(locations)]
        && [lsearch -glob $conf(locations) "*<%$name%>*"] > -1} {
        ::InstallJammer::RedrawFileTreeNodes
    }

    return 1
}

proc ::InstallJammer::FinishExternalEditVirtualText {w item name lang old new} {
    if {[$w edit current] eq $item} {
        $w edit editvalue $new
        set entry [$w edit entrypath]
        $entry selection range 0 end
        after idle [list focus $entry]
    } else {
        ::msgcat::mcset $lang $name $new
        if {[$w exists $item]} {
            $w itemconfigure $item -values [list $name $new]
        }
    }

    Modified
}

proc ::InstallJammer::LoadVirtualText {} {
    global conf
    global info
    global widg

    variable languages

    if {![info exists widg(VirtualTextTable)]} { return }

    set table $widg(VirtualTextTable)

    ::InstallJammer::ClearVirtualText

    ::InstallJammer::LoadReservedVirtualText

    if {$conf(VirtualTextLanguage) eq "None"} {
        foreach var [lsort [array names info]] {
            if {![::InstallJammer::IsReservedVirtualText $var]} {
                $table insert end root #auto -values [list $var $info($var)]
            }
        }
    } else {
        set lang $languages($conf(VirtualTextLanguage))
        array set msg [::msgcat::mcgetall $lang]
        foreach var [lsort [array names msg]] {
            if {[string first , $var] < 0} {
                $table insert end root #auto -values [list $var $msg($var)]
            }
        }
    }
}

proc ::InstallJammer::ClearVirtualText {} {
    global widg

    if {[info exists widg(VirtualTextTable)]} {
        $widg(VirtualTextTable) clear
    }
}

proc ::InstallJammer::UpdateReservedVirtualText {} {
    global info
    global widg

    set table $widg(VirtualTextTable)

    set row 0
    foreach item [$table items root] {
        set name [$table get value $item 0]
	if {![IsReservedVirtualText $name]} { continue }
	if {![info exists info($name)]} { continue }
        $table set $row,1 $info($name)
        incr row
    }
}

proc ::InstallJammer::IsReservedVirtualText {name} {
    variable InstallJammerVirtualText
    if {[info exists InstallJammerVirtualText($name)]} {
        return $InstallJammerVirtualText($name)
    }
    return 0
}
Added tests/test.tcl.






>
>
>
1
2
3
source utils.tcl
runAllTests
exit
Added tests/test1.mpi.


























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
array set info {
AllowLanguageSelection
{No}

AppName
{Your Application Name}

ApplicationID
{8E2BFF26-D98E-476D-BA36-2F26D6269749}

ApplicationURL
{}

AutoRefreshFiles
{Yes}

BuildFailureAction
{Fail (recommended)}

CancelledInstallAction
{Rollback and Stop}

CleanupCancelledInstall
{Yes}

CommandLineFailureAction
{Fail (recommended)}

Company
{Your Company Name}

CompressionLevel
{6}

CompressionMethod
{zlib}

Copyright
{}

CreateDesktopShortcut
{Yes}

CreateQuickLaunchShortcut
{Yes}

DefaultDirectoryLocation
{}

DefaultLanguage
{English}

DefaultToSystemLanguage
{Yes}

EnableResponseFiles
{Yes}

Ext
{.exe}

ExtractSolidArchivesOnStartup
{No}

Icon
{Modern/Small/SetupModernSmall01.gif}

IgnoreDirectories
{}

IgnoreFiles
{}

Image
{Modern/SetupModern01.gif}

IncludeDebugging
{Yes}

InstallPassword
{}

InstallVersion
{1.0.0.0}

Language,ca
{Yes}

Language,cs
{Yes}

Language,de
{Yes}

Language,en
{Yes}

Language,es
{Yes}

Language,fr
{Yes}

Language,hu
{Yes}

Language,it
{Yes}

Language,lt
{Yes}

Language,nl
{Yes}

Language,pl
{Yes}

Language,pt_br
{Yes}

Language,ru
{Yes}

LastIgnoreDirectories
{}

LastIgnoreFiles
{}

LaunchApplication
{Yes}

PackageDescription
{}

PackageLicense
{}

PackageMaintainer
{}

PackageName
{<%ShortAppName%>}

PackagePackager
{}

PackageRelease
{<%PatchVersion%>}

PackageSummary
{}

PackageVersion
{<%MajorVersion%>.<%MinorVersion%>}

PreserveFileAttributes
{Yes}

PreserveFilePermissions
{Yes}

ProjectID
{7D02994C-8612-4FDA-BB3B-275B501DFF8A}

ProjectVersion
{1.2.14.1}

SaveOnlyToplevelDirs
{No}

ScriptExt
{.bat}

ShortAppName
{yourapp}

SkipUnusedFileGroups
{Yes}

Theme
{Modern_Wizard}

ThemeDir
{Modern_Wizard}

ThemeVersion
{1}

UpgradeApplicationID
{}

Version
{1.0}

ViewReadme
{Yes}

WizardHeight
{365}

WizardWidth
{500}

}

array set ::InstallJammer::InstallCommandLineOptions {
debug
{Debugging Switch Yes No {} {run installer in debug mode}}

debugconsole
{ShowConsole Switch Yes No {} {run installer with a debug console open}}

mode
{InstallMode Choice No No {Console Default Silent Standard} {set the mode to run the installer in}}

prefix
{InstallDir String No No {} {set the installation directory}}

test
{Testing Switch Yes No {} {run installer without installing any files}}

test-script
{TestScript String Yes Yes {} {}}

}
array set ::InstallJammer::UninstallCommandLineOptions {
debug
{Debugging Switch Yes No {} {run uninstaller in debug mode}}

debugconsole
{ShowConsole Switch Yes No {} {run uninstaller with a debug console open}}

mode
{UninstallMode Choice No No {Console Silent Standard} {set the mode to run the uninstaller in}}

test
{Testing Switch Yes No {} {run uninstaller without uninstalling any files}}

test-script
{TestScript String Yes Yes {} {}}

}
FileGroup ::70818653-0707-4293-8F5F-8DCA8A0E97C4 -setup Install -active Yes -platforms {Windows TarArchive ZipArchive} -name {Program Files} -parent FileGroups
Component ::2EBFF24C-F2E7-4AC5-9A4B-E1D8D57146CC -setup Install -active Yes -platforms Windows -name {Default Component} -parent Components
SetupType ::22DAD4C7-23EA-4B36-8957-CE5FFE3F95B2 -setup Install -active Yes -platforms Windows -name Typical -parent SetupTypes
SetupType ::DC5F8F72-5665-4EA7-AC40-DD103BA19818 -setup Install -active Yes -platforms Windows -name Custom -parent SetupTypes

InstallComponent 7F12D2E6-6228-4549-B567-77B60756335E -setup Install -type pane -title {Welcome Screen} -component Welcome -active Yes -parent StandardInstall
InstallComponent 57BFF0F0-BA4B-4235-A8BC-295E9FA03854 -setup Install -type pane -conditions {03D1631D-9742-4932-B02C-1D25B790C5E1 981418EB-51B3-42A0-930B-BD513D82228D} -title {Select Destination} -component SelectDestination -active Yes -parent StandardInstall
Condition 03D1631D-9742-4932-B02C-1D25B790C5E1 -active Yes -parent 57BFF0F0-BA4B-4235-A8BC-295E9FA03854 -title {Script Condition} -component ScriptCondition -TreeObject::id 03D1631D-9742-4932-B02C-1D25B790C5E1
Condition 981418EB-51B3-42A0-930B-BD513D82228D -active Yes -parent 57BFF0F0-BA4B-4235-A8BC-295E9FA03854 -title {File Permission Condition} -component FilePermissionCondition -TreeObject::id 981418EB-51B3-42A0-930B-BD513D82228D
InstallComponent FC987119-4BF9-406E-B31D-49EFBB1793E8 -setup Install -type pane -conditions {9EF3A047-ACCA-4263-9B80-94D3A88E5DEA C642D7DE-A2EE-4E46-906D-5BB734E06C56} -title {Setup Type} -component SetupType -active Yes -parent StandardInstall
Condition 9EF3A047-ACCA-4263-9B80-94D3A88E5DEA -active Yes -parent FC987119-4BF9-406E-B31D-49EFBB1793E8 -title {Script Condition} -component ScriptCondition -TreeObject::id 9EF3A047-ACCA-4263-9B80-94D3A88E5DEA
Condition C642D7DE-A2EE-4E46-906D-5BB734E06C56 -active Yes -parent FC987119-4BF9-406E-B31D-49EFBB1793E8 -title {String Is Condition} -component StringIsCondition -TreeObject::id C642D7DE-A2EE-4E46-906D-5BB734E06C56
InstallComponent 0F27BEBF-46CB-4834-9478-7E8E50D097FA -setup Install -type action -title {Populate Setup Types} -component PopulateSetupTypes -active Yes -parent FC987119-4BF9-406E-B31D-49EFBB1793E8
InstallComponent 028390FA-2333-4C47-843E-E0D0ED2B5D33 -setup Install -type pane -conditions 931B2116-756F-48CE-ABDE-2E28B29DAB12 -title {Choose Components} -component ChooseComponents -active Yes -parent StandardInstall
Condition 931B2116-756F-48CE-ABDE-2E28B29DAB12 -active Yes -parent 028390FA-2333-4C47-843E-E0D0ED2B5D33 -title {String Equal Condition} -component StringEqualCondition -TreeObject::id 931B2116-756F-48CE-ABDE-2E28B29DAB12
InstallComponent 44AB3F02-67C0-4EE4-A576-ABDBBB645BFB -setup Install -type action -title {Populate Components} -component PopulateComponents -active Yes -parent 028390FA-2333-4C47-843E-E0D0ED2B5D33
InstallComponent 45C7FCC1-EE4F-43DB-A4ED-BC9A82D62D24 -setup Install -type pane -title {Start Copying Files} -component StartCopyingFiles -active Yes -parent StandardInstall
InstallComponent 88B5489F-86AA-468A-A8AC-62FF9D6DC610 -setup Install -type pane -title {Copying Files} -component CopyFiles -active Yes -parent StandardInstall
InstallComponent 9321E964-C631-4011-BF00-6334F7B4581A -setup Install -type action -title {Disable Buttons} -component ModifyWidget -active Yes -parent 88B5489F-86AA-468A-A8AC-62FF9D6DC610
InstallComponent 86D33DD4-5B24-4B32-A05E-B109573C00B4 -setup Install -type action -title {Install Everything} -component ExecuteAction -active Yes -parent 88B5489F-86AA-468A-A8AC-62FF9D6DC610
InstallComponent 20B817F2-0F1D-47D3-B9DD-3C62CE5B855A -setup Install -type action -title {Move Forward} -component MoveForward -active Yes -parent 88B5489F-86AA-468A-A8AC-62FF9D6DC610
InstallComponent 59A04F4F-C22B-42D7-A09F-D5A42C5119A4 -setup Install -type pane -title {Setup Complete} -component SetupComplete -active Yes -parent StandardInstall
InstallComponent E230B57B-6C55-46B8-974C-CCAD003267D2 -setup Install -type action -conditions {1A75A73E-ADE7-4198-B2CE-16EBE0EEC4F3 4C62C271-752B-4F3D-AD44-16C9FB036B92} -title {View Readme Checkbutton} -component AddWidget -active Yes -parent 59A04F4F-C22B-42D7-A09F-D5A42C5119A4
Condition 1A75A73E-ADE7-4198-B2CE-16EBE0EEC4F3 -active Yes -parent E230B57B-6C55-46B8-974C-CCAD003267D2 -title {File Exists Condition} -component FileExistsCondition -TreeObject::id 1A75A73E-ADE7-4198-B2CE-16EBE0EEC4F3
Condition 4C62C271-752B-4F3D-AD44-16C9FB036B92 -active Yes -parent E230B57B-6C55-46B8-974C-CCAD003267D2 -title {String Is Condition} -component StringIsCondition -TreeObject::id 4C62C271-752B-4F3D-AD44-16C9FB036B92
InstallComponent 7C9F30F2-E42C-4AFC-BF88-BC0F80010078 -setup Install -type action -conditions {D7B22071-C6D5-439E-ABBC-454A317BEBD7 921ADE61-D25D-4841-AC79-A3F5DA939BC6} -title {Launch Application Checkbutton} -component AddWidget -active Yes -parent 59A04F4F-C22B-42D7-A09F-D5A42C5119A4
Condition D7B22071-C6D5-439E-ABBC-454A317BEBD7 -active Yes -parent 7C9F30F2-E42C-4AFC-BF88-BC0F80010078 -title {File Exists Condition} -component FileExistsCondition -TreeObject::id D7B22071-C6D5-439E-ABBC-454A317BEBD7
Condition 921ADE61-D25D-4841-AC79-A3F5DA939BC6 -active Yes -parent 7C9F30F2-E42C-4AFC-BF88-BC0F80010078 -title {String Is Condition} -component StringIsCondition -TreeObject::id 921ADE61-D25D-4841-AC79-A3F5DA939BC6
InstallComponent C72FB649-796D-40E1-AF3E-618BD4880127 -setup Install -type action -conditions {7760979D-C999-41FE-9CF2-0F6E0E83CCC2 92B694D9-2E0D-4B69-AB9D-8BDD02D2AA73} -title {Desktop Shortcut Checkbutton} -component AddWidget -active Yes -parent 59A04F4F-C22B-42D7-A09F-D5A42C5119A4
Condition 7760979D-C999-41FE-9CF2-0F6E0E83CCC2 -active Yes -parent C72FB649-796D-40E1-AF3E-618BD4880127 -title {File Exists Condition} -component FileExistsCondition -TreeObject::id 7760979D-C999-41FE-9CF2-0F6E0E83CCC2
Condition 92B694D9-2E0D-4B69-AB9D-8BDD02D2AA73 -active Yes -parent C72FB649-796D-40E1-AF3E-618BD4880127 -title {String Is Condition} -component StringIsCondition -TreeObject::id 92B694D9-2E0D-4B69-AB9D-8BDD02D2AA73
InstallComponent 018814A4-A7CB-4498-86A5-2CA7DA217D8F -setup Install -type action -conditions {44F39CB3-EECF-4F5E-BB87-AC68E465F86A D98FCD0E-BA23-44E1-B688-78CE3AB7F8BC 696922E0-95C8-4E7A-83CB-BBDAEC62D5C3} -title {Quick Launch Shortcut Checkbutton} -component AddWidget -active Yes -parent 59A04F4F-C22B-42D7-A09F-D5A42C5119A4
Condition 44F39CB3-EECF-4F5E-BB87-AC68E465F86A -active Yes -parent 018814A4-A7CB-4498-86A5-2CA7DA217D8F -title {Platform Condition} -component PlatformCondition -TreeObject::id 44F39CB3-EECF-4F5E-BB87-AC68E465F86A
Condition D98FCD0E-BA23-44E1-B688-78CE3AB7F8BC -active Yes -parent 018814A4-A7CB-4498-86A5-2CA7DA217D8F -title {File Exists Condition} -component FileExistsCondition -TreeObject::id D98FCD0E-BA23-44E1-B688-78CE3AB7F8BC
Condition 696922E0-95C8-4E7A-83CB-BBDAEC62D5C3 -active Yes -parent 018814A4-A7CB-4498-86A5-2CA7DA217D8F -title {String Is Condition} -component StringIsCondition -TreeObject::id 696922E0-95C8-4E7A-83CB-BBDAEC62D5C3
InstallComponent D5FCE600-561B-46E6-ACAE-67185E3A3D2C -setup Install -type pane -title {Copying Files} -component CopyFiles -active Yes -parent DefaultInstall
InstallComponent D5044EB4-D57C-4744-B46D-05FB8BDA9979 -setup Install -type action -title {Disable Buttons} -component ModifyWidget -active Yes -parent D5FCE600-561B-46E6-ACAE-67185E3A3D2C
InstallComponent 4140D9DD-BA31-4311-9AC6-BE9D7EF220E4 -setup Install -type action -title {Install Everything} -component ExecuteAction -active Yes -parent D5FCE600-561B-46E6-ACAE-67185E3A3D2C
InstallComponent 3B88EC33-CE05-41B4-916F-E4684A9C62AB -setup Install -type action -title {Move Forward} -component MoveForward -active Yes -parent D5FCE600-561B-46E6-ACAE-67185E3A3D2C
InstallComponent 68BEF2C8-FB6D-46BC-9CBA-6069FC465EA3 -setup Install -type pane -title {Setup Complete} -component SetupComplete -active Yes -parent DefaultInstall
InstallComponent B03167BC-367B-4DDC-ACD4-E908C2938F7F -setup Install -type action -conditions {1AF57F48-2F60-44FE-AAD1-C2F1B1E59416 E6B908CC-AA78-4001-A303-064F73FB61FD} -title {View Readme Checkbutton} -component AddWidget -active Yes -parent 68BEF2C8-FB6D-46BC-9CBA-6069FC465EA3
Condition 1AF57F48-2F60-44FE-AAD1-C2F1B1E59416 -active Yes -parent B03167BC-367B-4DDC-ACD4-E908C2938F7F -title {File Exists Condition} -component FileExistsCondition -TreeObject::id 1AF57F48-2F60-44FE-AAD1-C2F1B1E59416
Condition E6B908CC-AA78-4001-A303-064F73FB61FD -active Yes -parent B03167BC-367B-4DDC-ACD4-E908C2938F7F -title {String Is Condition} -component StringIsCondition -TreeObject::id E6B908CC-AA78-4001-A303-064F73FB61FD
InstallComponent 31A5F48D-8D72-4143-BCD1-92669852DB59 -setup Install -type action -conditions {76F49002-DD56-42C0-8507-7240A570191F 8007933F-5291-49A8-9EED-5EFD237F0384} -title {Launch Application Checkbutton} -component AddWidget -active Yes -parent 68BEF2C8-FB6D-46BC-9CBA-6069FC465EA3
Condition 76F49002-DD56-42C0-8507-7240A570191F -active Yes -parent 31A5F48D-8D72-4143-BCD1-92669852DB59 -title {File Exists Condition} -component FileExistsCondition -TreeObject::id 76F49002-DD56-42C0-8507-7240A570191F
Condition 8007933F-5291-49A8-9EED-5EFD237F0384 -active Yes -parent 31A5F48D-8D72-4143-BCD1-92669852DB59 -title {String Is Condition} -component StringIsCondition -TreeObject::id 8007933F-5291-49A8-9EED-5EFD237F0384
InstallComponent 52FFBEDC-FDB4-4B97-B9F8-11514FE1079E -setup Install -type action -conditions {73075CC5-E757-4070-AE91-6DC5169E7252 23AF60FF-037B-4714-B3DB-599057CBC6F6} -title {Desktop Shortcut Checkbutton} -component AddWidget -active Yes -parent 68BEF2C8-FB6D-46BC-9CBA-6069FC465EA3
Condition 73075CC5-E757-4070-AE91-6DC5169E7252 -active Yes -parent 52FFBEDC-FDB4-4B97-B9F8-11514FE1079E -title {File Exists Condition} -component FileExistsCondition -TreeObject::id 73075CC5-E757-4070-AE91-6DC5169E7252
Condition 23AF60FF-037B-4714-B3DB-599057CBC6F6 -active Yes -parent 52FFBEDC-FDB4-4B97-B9F8-11514FE1079E -title {String Is Condition} -component StringIsCondition -TreeObject::id 23AF60FF-037B-4714-B3DB-599057CBC6F6
InstallComponent FEA2C975-1D24-4801-8396-ADD267808D3E -setup Install -type action -conditions {F4A0FD07-2ED7-45B4-A58D-88925E06CA01 1A3CCE80-6C5A-43C1-B334-8B9B7646D795 99F6610C-8C0F-4475-A071-C06333A77675} -title {Quick Launch Shortcut Checkbutton} -component AddWidget -active Yes -parent 68BEF2C8-FB6D-46BC-9CBA-6069FC465EA3
Condition F4A0FD07-2ED7-45B4-A58D-88925E06CA01 -active Yes -parent FEA2C975-1D24-4801-8396-ADD267808D3E -title {Platform Condition} -component PlatformCondition -TreeObject::id F4A0FD07-2ED7-45B4-A58D-88925E06CA01
Condition 1A3CCE80-6C5A-43C1-B334-8B9B7646D795 -active Yes -parent FEA2C975-1D24-4801-8396-ADD267808D3E -title {File Exists Condition} -component FileExistsCondition -TreeObject::id 1A3CCE80-6C5A-43C1-B334-8B9B7646D795
Condition 99F6610C-8C0F-4475-A071-C06333A77675 -active Yes -parent FEA2C975-1D24-4801-8396-ADD267808D3E -title {String Is Condition} -component StringIsCondition -TreeObject::id 99F6610C-8C0F-4475-A071-C06333A77675
InstallComponent 1611994D-6806-4F6D-8BB4-23AC524DD93D -setup Install -type action -title {Prompt to continue installation} -component ConsoleAskYesOrNo -active Yes -parent ConsoleInstall
InstallComponent B98596C4-0AA7-4208-9774-0ADB2D766B56 -setup Install -type action -conditions 0E0A568C-F679-4489-B061-931C15075A33 -title {Exit if they said no} -component Exit -active Yes -parent ConsoleInstall
Condition 0E0A568C-F679-4489-B061-931C15075A33 -active Yes -parent B98596C4-0AA7-4208-9774-0ADB2D766B56 -title {String Is Condition} -component StringIsCondition -TreeObject::id 0E0A568C-F679-4489-B061-931C15075A33
InstallComponent 804E20E3-FD50-4B8F-BA82-B8E0955A1394 -setup Install -type action -conditions EC8FA828-EB62-49DD-8CEB-371945D6727B -title {Prompt for install destination} -component ConsoleGetUserInput -active Yes -parent ConsoleInstall
Condition EC8FA828-EB62-49DD-8CEB-371945D6727B -active Yes -parent 804E20E3-FD50-4B8F-BA82-B8E0955A1394 -title {File Permission Condition} -component FilePermissionCondition -TreeObject::id EC8FA828-EB62-49DD-8CEB-371945D6727B
InstallComponent CE1358E6-09F7-4984-B40A-1BDF4A9358A0 -setup Install -type action -title {Output Installing Message} -component ConsoleMessage -active Yes -parent ConsoleInstall
InstallComponent 939D4E35-19C0-4DA4-95D9-C017EA124455 -setup Install -type action -title {Install Everything} -component ExecuteAction -active Yes -parent ConsoleInstall
InstallComponent 29218D4F-A773-4377-ACC7-8D7ECEB5F281 -setup Install -type action -title {Output Install Complete Message} -component ConsoleMessage -active Yes -parent ConsoleInstall
InstallComponent 0AD6B2F1-9DD6-4155-BAB2-C2E5A9C1C449 -setup Install -type action -title Exit -component Exit -active Yes -parent ConsoleInstall
InstallComponent CED955F7-7B89-4D7B-B62E-FF39D97FE39B -setup Install -type action -title {Install Everything} -component ExecuteAction -active Yes -parent SilentInstall
InstallComponent 614C6F65-6F31-4E32-A600-5831551BB045 -setup Install -type action -title Exit -component Exit -active Yes -parent SilentInstall
InstallComponent 1B721050-E754-4D7F-A7E6-3669979BD4BF -setup Install -type actiongroup -title {Setup Actions} -alias {Setup Actions} -active Yes -parent ActionGroupsInstall
InstallComponent 9E1AAF5C-749C-4840-9AAD-1082D55AE2E5 -setup Install -type action -title {Test Script} -component ExecuteScript -alias {Test Script} -active Yes -parent 1B721050-E754-4D7F-A7E6-3669979BD4BF
InstallComponent FDE4744C-A20D-4A5A-99EB-37983CEEEC8B -setup Install -type actiongroup -title {Startup Actions} -alias {Startup Actions} -active Yes -parent ActionGroupsInstall
InstallComponent FAB5A83A-DC94-43CC-961A-74954B83D5CD -setup Install -type action -title {Create Install Panes} -component CreateInstallPanes -active Yes -parent FDE4744C-A20D-4A5A-99EB-37983CEEEC8B
InstallComponent 9641A6D0-7BB3-4746-91A2-45D0FBC9E5AE -setup Install -type actiongroup -title {Install Actions} -alias {Install Actions} -active Yes -parent ActionGroupsInstall
InstallComponent 66E194D0-90B3-4999-8C1D-78AEAADB2FA7 -setup Install -type action -title {Install Selected Files} -component InstallSelectedFiles -active Yes -parent 9641A6D0-7BB3-4746-91A2-45D0FBC9E5AE
InstallComponent B1D6DA80-A470-42F0-BF81-BDDA11CCF903 -setup Install -type action -conditions 74265BA6-3A1F-467B-8D14-E271AAF37FC2 -title {Install Uninstaller} -component InstallUninstaller -active Yes -parent 9641A6D0-7BB3-4746-91A2-45D0FBC9E5AE
Condition 74265BA6-3A1F-467B-8D14-E271AAF37FC2 -active Yes -parent B1D6DA80-A470-42F0-BF81-BDDA11CCF903 -title {String Is Condition} -component StringIsCondition -TreeObject::id 74265BA6-3A1F-467B-8D14-E271AAF37FC2
InstallComponent BEEF4D69-7ED3-41C8-BDC9-E86D5333D4A7 -setup Install -type action -conditions 464B2689-001B-4B53-8EDB-2F3FE169DCD4 -title {Windows Uninstall Registry} -component AddWindowsUninstallEntry -active Yes -parent 9641A6D0-7BB3-4746-91A2-45D0FBC9E5AE
Condition 464B2689-001B-4B53-8EDB-2F3FE169DCD4 -active Yes -parent BEEF4D69-7ED3-41C8-BDC9-E86D5333D4A7 -title {String Is Condition} -component StringIsCondition -TreeObject::id 464B2689-001B-4B53-8EDB-2F3FE169DCD4
InstallComponent B28303E8-004A-43A3-AC76-414D134F94F9 -setup Install -type action -conditions 200C6071-BD12-479F-9ADD-D48FB782F7D5 -title {Program Shortcut} -component InstallProgramFolderShortcut -active Yes -parent 9641A6D0-7BB3-4746-91A2-45D0FBC9E5AE
Condition 200C6071-BD12-479F-9ADD-D48FB782F7D5 -active Yes -parent B28303E8-004A-43A3-AC76-414D134F94F9 -title {String Is Condition} -component StringIsCondition -TreeObject::id 200C6071-BD12-479F-9ADD-D48FB782F7D5
InstallComponent 266C6C0F-C069-46DD-9838-8DB5DD6351F4 -setup Install -type action -conditions E727D6FE-2D34-464D-AC50-5B6FDA45F94B -title {Uninstall Shortcut} -component InstallProgramFolderShortcut -active Yes -parent 9641A6D0-7BB3-4746-91A2-45D0FBC9E5AE
Condition E727D6FE-2D34-464D-AC50-5B6FDA45F94B -active Yes -parent 266C6C0F-C069-46DD-9838-8DB5DD6351F4 -title {String Is Condition} -component StringIsCondition -TreeObject::id E727D6FE-2D34-464D-AC50-5B6FDA45F94B
InstallComponent C3EAFC25-F412-466E-95E7-C43F7045E895 -setup Install -type actiongroup -title {Finish Actions} -alias {Finish Actions} -active Yes -parent ActionGroupsInstall
InstallComponent CC91317C-EDE0-429E-879D-810CF3ECDD0A -setup Install -type action -conditions {4E360EAF-AFA9-43E3-8CD0-4ED7755E0B10 C9EA4191-53BC-413B-90CC-63B584DE60B2} -title {Install Desktop Shortcut} -component InstallDesktopShortcut -active Yes -parent C3EAFC25-F412-466E-95E7-C43F7045E895
Condition 4E360EAF-AFA9-43E3-8CD0-4ED7755E0B10 -active Yes -parent CC91317C-EDE0-429E-879D-810CF3ECDD0A -title {String Is Condition} -component StringIsCondition -TreeObject::id 4E360EAF-AFA9-43E3-8CD0-4ED7755E0B10
Condition C9EA4191-53BC-413B-90CC-63B584DE60B2 -active Yes -parent CC91317C-EDE0-429E-879D-810CF3ECDD0A -title {File Exists Condition} -component FileExistsCondition -TreeObject::id C9EA4191-53BC-413B-90CC-63B584DE60B2
InstallComponent 7334F8BA-C35D-4F63-A926-901355FF1B37 -setup Install -type action -conditions {E71E10BF-8B60-41DE-89CB-A770DDA50763 23CD85B7-BE23-4D02-8AB9-C1C1D4A961CA} -title {Install Quick Launch Shortcut} -component InstallWindowsShortcut -active Yes -parent C3EAFC25-F412-466E-95E7-C43F7045E895
Condition E71E10BF-8B60-41DE-89CB-A770DDA50763 -active Yes -parent 7334F8BA-C35D-4F63-A926-901355FF1B37 -title {String Is Condition} -component StringIsCondition -TreeObject::id E71E10BF-8B60-41DE-89CB-A770DDA50763
Condition 23CD85B7-BE23-4D02-8AB9-C1C1D4A961CA -active Yes -parent 7334F8BA-C35D-4F63-A926-901355FF1B37 -title {File Exists Condition} -component FileExistsCondition -TreeObject::id 23CD85B7-BE23-4D02-8AB9-C1C1D4A961CA
InstallComponent 8B731604-25BD-4974-B646-74349BEA776A -setup Install -type action -conditions {DB1D9C02-507C-4706-B6E2-538C9BBF83EE FA00CE55-9437-4796-AC47-642DFBB72991 90C7003F-FAFB-40B2-86A4-25317C78399E} -title {View Readme Window} -component TextWindow -active Yes -parent C3EAFC25-F412-466E-95E7-C43F7045E895
Condition DB1D9C02-507C-4706-B6E2-538C9BBF83EE -active Yes -parent 8B731604-25BD-4974-B646-74349BEA776A -title {String Is Condition} -component StringIsCondition -TreeObject::id DB1D9C02-507C-4706-B6E2-538C9BBF83EE
Condition FA00CE55-9437-4796-AC47-642DFBB72991 -active Yes -parent 8B731604-25BD-4974-B646-74349BEA776A -title {String Is Condition} -component StringIsCondition -TreeObject::id FA00CE55-9437-4796-AC47-642DFBB72991
Condition 90C7003F-FAFB-40B2-86A4-25317C78399E -active Yes -parent 8B731604-25BD-4974-B646-74349BEA776A -title {File Exists Condition} -component FileExistsCondition -TreeObject::id 90C7003F-FAFB-40B2-86A4-25317C78399E
InstallComponent 94D26118-7214-4D77-8701-81F50D758296 -setup Install -type action -conditions {9ED2E111-A27B-4020-8F67-313619FCE5A3 3AF50345-7EA0-4E9A-B627-EC1737B67497 380E192B-915B-4066-A1D7-087B7F6F4BB5} -title {Launch Application} -component ExecuteExternalProgram -active Yes -parent C3EAFC25-F412-466E-95E7-C43F7045E895
Condition 9ED2E111-A27B-4020-8F67-313619FCE5A3 -active Yes -parent 94D26118-7214-4D77-8701-81F50D758296 -title {String Is Condition} -component StringIsCondition -TreeObject::id 9ED2E111-A27B-4020-8F67-313619FCE5A3
Condition 3AF50345-7EA0-4E9A-B627-EC1737B67497 -active Yes -parent 94D26118-7214-4D77-8701-81F50D758296 -title {String Is Condition} -component StringIsCondition -TreeObject::id 3AF50345-7EA0-4E9A-B627-EC1737B67497
Condition 380E192B-915B-4066-A1D7-087B7F6F4BB5 -active Yes -parent 94D26118-7214-4D77-8701-81F50D758296 -title {File Exists Condition} -component FileExistsCondition -TreeObject::id 380E192B-915B-4066-A1D7-087B7F6F4BB5
InstallComponent C11E1E67-57A7-4353-9FA0-36137288F0C6 -setup Install -type actiongroup -title {Cancel Actions} -alias {Cancel Actions} -active Yes -parent ActionGroupsInstall
InstallComponent CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5 -setup Uninstall -type pane -title Uninstall -component Uninstall -active Yes -parent StandardUninstall
InstallComponent 314C280D-877D-491E-BB79-D98AE5ACCE33 -setup Uninstall -type action -title {Modify Widget} -component ModifyWidget -active Yes -parent CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5
InstallComponent 86A81E43-CD88-4376-A0EC-1B648E239681 -setup Uninstall -type action -title {Execute Action} -component ExecuteAction -active Yes -parent CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5
InstallComponent 195583C5-E5BF-46A9-803B-5B56E4C3740E -setup Uninstall -type action -title {Move Forward} -component MoveForward -active Yes -parent CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5
InstallComponent 370E1073-A18F-4970-BA92-404F995305C6 -setup Uninstall -type pane -conditions 0C3AC926-5F46-4FDA-98DD-54EF99E08A4C -title {Uninstall Details} -component UninstallDetails -active Yes -parent StandardUninstall
Condition 0C3AC926-5F46-4FDA-98DD-54EF99E08A4C -active Yes -parent 370E1073-A18F-4970-BA92-404F995305C6 -title {String Is Condition} -component StringIsCondition -TreeObject::id 0C3AC926-5F46-4FDA-98DD-54EF99E08A4C
InstallComponent 643FB86F-275B-4FD2-81EA-389F39C844E7 -setup Uninstall -type pane -title {Uninstall Complete} -component UninstallComplete -active Yes -parent StandardUninstall
InstallComponent E6D1058D-A0C6-4404-B29B-34324F32282F -setup Uninstall -type action -title {Console Ask Yes Or No} -component ConsoleAskYesOrNo -active Yes -parent ConsoleUninstall
InstallComponent 036C13B1-0E96-4A97-9143-85F5AEC6AFC4 -setup Uninstall -type action -conditions 982C2E0B-6F81-46A0-BED8-E2D253F0E428 -title Exit -component Exit -active Yes -parent ConsoleUninstall
Condition 982C2E0B-6F81-46A0-BED8-E2D253F0E428 -active Yes -parent 036C13B1-0E96-4A97-9143-85F5AEC6AFC4 -title {String Is Condition} -component StringIsCondition -TreeObject::id 982C2E0B-6F81-46A0-BED8-E2D253F0E428
InstallComponent 98F10689-CF62-408F-8CFF-90B481AB8919 -setup Uninstall -type action -title {Console Message} -component ConsoleMessage -active Yes -parent ConsoleUninstall
InstallComponent B7E5A7C5-D456-4730-A506-6633873D2735 -setup Uninstall -type action -title {Execute Action} -component ExecuteAction -active Yes -parent ConsoleUninstall
InstallComponent 25F80124-CD10-4EA8-AAD0-18985025B310 -setup Uninstall -type action -title {Console Message} -component ConsoleMessage -active Yes -parent ConsoleUninstall
InstallComponent 965E5383-521A-421A-8EEA-A90DC53F1338 -setup Uninstall -type action -title Exit -component Exit -active Yes -parent ConsoleUninstall
InstallComponent 2DCAD6A8-71AF-4662-BF1D-726781389EBE -setup Uninstall -type action -title {Uninstall Everything} -component ExecuteAction -active Yes -parent SilentUninstall
InstallComponent 83BE8BB8-2F9B-4C43-BFBD-22D604F506AF -setup Uninstall -type action -title Exit -component Exit -active Yes -parent SilentUninstall
InstallComponent B426A47D-01D9-42AC-95A7-D17A5409DC03 -setup Uninstall -type actiongroup -title {Setup Actions} -alias {Setup Actions} -active Yes -parent ActionGroupsUninstall
InstallComponent 40A63CB6-3BAE-4FDB-B2ED-D6E14CB3EC46 -setup Uninstall -type action -title {Test Script} -component ExecuteScript -alias {Test Script} -active Yes -parent B426A47D-01D9-42AC-95A7-D17A5409DC03
InstallComponent 8DD6E5B5-BCD3-475B-9F50-EC650FF94706 -setup Uninstall -type actiongroup -title {Startup Actions} -alias {Startup Actions} -active Yes -parent ActionGroupsUninstall
InstallComponent EABAF583-B4B6-46E0-BC8C-2BFCEFEA3161 -setup Uninstall -type action -conditions {40FCC4D0-83EF-4CEA-ACCB-E1DFBC9052CD CE85FAF5-6C87-48A4-A8CC-236F5670A605} -title Exit -component Exit -active Yes -parent 8DD6E5B5-BCD3-475B-9F50-EC650FF94706
Condition 40FCC4D0-83EF-4CEA-ACCB-E1DFBC9052CD -active Yes -parent EABAF583-B4B6-46E0-BC8C-2BFCEFEA3161 -title {String Is Condition} -component StringIsCondition -TreeObject::id 40FCC4D0-83EF-4CEA-ACCB-E1DFBC9052CD
Condition CE85FAF5-6C87-48A4-A8CC-236F5670A605 -active Yes -parent EABAF583-B4B6-46E0-BC8C-2BFCEFEA3161 -title {Ask Yes or No} -component AskYesOrNo -TreeObject::id CE85FAF5-6C87-48A4-A8CC-236F5670A605
InstallComponent 463A3DA5-8F2F-4E3F-9989-F2A71ED430F3 -setup Uninstall -type actiongroup -title {Uninstall Actions} -alias {Uninstall Actions} -active Yes -parent ActionGroupsUninstall
InstallComponent 3EA49215-B054-42E5-B03B-4EC4D002BCD8 -setup Uninstall -type action -title {Uninstall Selected Files} -component UninstallSelectedFiles -active Yes -parent 463A3DA5-8F2F-4E3F-9989-F2A71ED430F3
InstallComponent E8D5F0F3-3A25-4E39-B0D1-D01D58A1AFB3 -setup Uninstall -type actiongroup -title {Finish Actions} -alias {Finish Actions} -active Yes -parent ActionGroupsUninstall
InstallComponent 974E41DB-EB24-4E2C-99C5-AF76EDC51BC2 -setup Uninstall -type actiongroup -title {Cancel Actions} -alias {Cancel Actions} -active Yes -parent ActionGroupsUninstall

array set Properties {
018814A4-A7CB-4498-86A5-2CA7DA217D8F,Background
{white}

018814A4-A7CB-4498-86A5-2CA7DA217D8F,Text,subst
{1}

018814A4-A7CB-4498-86A5-2CA7DA217D8F,Type
{checkbutton}

018814A4-A7CB-4498-86A5-2CA7DA217D8F,VirtualText
{CreateQuickLaunchShortcut}

018814A4-A7CB-4498-86A5-2CA7DA217D8F,X
{185}

018814A4-A7CB-4498-86A5-2CA7DA217D8F,Y
{200}

028390FA-2333-4C47-843E-E0D0ED2B5D33,Active
{Yes}

028390FA-2333-4C47-843E-E0D0ED2B5D33,BackButton,subst
{1}

028390FA-2333-4C47-843E-E0D0ED2B5D33,CancelButton,subst
{1}

028390FA-2333-4C47-843E-E0D0ED2B5D33,Caption,subst
{1}

028390FA-2333-4C47-843E-E0D0ED2B5D33,DescriptionLabel,subst
{0}

028390FA-2333-4C47-843E-E0D0ED2B5D33,Message,subst
{1}

028390FA-2333-4C47-843E-E0D0ED2B5D33,NextButton,subst
{1}

028390FA-2333-4C47-843E-E0D0ED2B5D33,Subtitle,subst
{1}

028390FA-2333-4C47-843E-E0D0ED2B5D33,Title,subst
{1}

03D1631D-9742-4932-B02C-1D25B790C5E1,Comment
{Do not display this pane if this is an upgrade install unless there is more than one installation present}

03D1631D-9742-4932-B02C-1D25B790C5E1,Script
{!<%UpgradeInstall%> || <%PreviousInstallCount%> != 1}

0AD6B2F1-9DD6-4155-BAB2-C2E5A9C1C449,ExitType
{Finish}

0C3AC926-5F46-4FDA-98DD-54EF99E08A4C,String
{<%ErrorsOccurred%>}

0E0A568C-F679-4489-B061-931C15075A33,CheckCondition
{Before Action is Executed}

0E0A568C-F679-4489-B061-931C15075A33,Operator
{false}

0E0A568C-F679-4489-B061-931C15075A33,String
{<%Answer%>}

0F27BEBF-46CB-4834-9478-7E8E50D097FA,ExecuteAction
{Before Pane is Displayed}

1611994D-6806-4F6D-8BB4-23AC524DD93D,Default
{Yes}

1611994D-6806-4F6D-8BB4-23AC524DD93D,Prompt
{<%InstallStartupText%>}

1A3CCE80-6C5A-43C1-B334-8B9B7646D795,CheckCondition
{Before Action is Executed}

1A3CCE80-6C5A-43C1-B334-8B9B7646D795,Filename
{<%ProgramExecutable%>}

1A75A73E-ADE7-4198-B2CE-16EBE0EEC4F3,CheckCondition
{Before Action is Executed}

1A75A73E-ADE7-4198-B2CE-16EBE0EEC4F3,Filename
{<%ProgramReadme%>}

1AF57F48-2F60-44FE-AAD1-C2F1B1E59416,CheckCondition
{Before Action is Executed}

1AF57F48-2F60-44FE-AAD1-C2F1B1E59416,Filename
{<%ProgramReadme%>}

1B721050-E754-4D7F-A7E6-3669979BD4BF,Alias
{Setup Actions}

200C6071-BD12-479F-9ADD-D48FB782F7D5,CheckCondition
{Before Action is Executed}

200C6071-BD12-479F-9ADD-D48FB782F7D5,Operator
{false}

200C6071-BD12-479F-9ADD-D48FB782F7D5,String
{<%UpgradeInstall%>}

22DAD4C7-23EA-4B36-8957-CE5FFE3F95B2,Components
{2EBFF24C-F2E7-4AC5-9A4B-E1D8D57146CC}

22DAD4C7-23EA-4B36-8957-CE5FFE3F95B2,Description,subst
{1}

22DAD4C7-23EA-4B36-8957-CE5FFE3F95B2,DisplayName,subst
{1}

22DAD4C7-23EA-4B36-8957-CE5FFE3F95B2,Name
{Typical}

23AF60FF-037B-4714-B3DB-599057CBC6F6,CheckCondition
{Before Action is Executed}

23AF60FF-037B-4714-B3DB-599057CBC6F6,Operator
{false}

23AF60FF-037B-4714-B3DB-599057CBC6F6,String
{<%InstallStopped%>}

23CD85B7-BE23-4D02-8AB9-C1C1D4A961CA,CheckCondition
{Before Action is Executed}

23CD85B7-BE23-4D02-8AB9-C1C1D4A961CA,Filename
{<%ProgramExecutable%>}

25F80124-CD10-4EA8-AAD0-18985025B310,Message,subst
{1}

266C6C0F-C069-46DD-9838-8DB5DD6351F4,FileName
{<%ShortAppName%>-uninstall}

266C6C0F-C069-46DD-9838-8DB5DD6351F4,ShortcutName
{Uninstall <%AppName%>}

266C6C0F-C069-46DD-9838-8DB5DD6351F4,TargetFileName
{<%Uninstaller%>}

266C6C0F-C069-46DD-9838-8DB5DD6351F4,WorkingDirectory
{<%InstallDir%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message,subst
{1}

2DCAD6A8-71AF-4662-BF1D-726781389EBE,Action
{Uninstall Actions}

2EBFF24C-F2E7-4AC5-9A4B-E1D8D57146CC,Description,subst
{1}

2EBFF24C-F2E7-4AC5-9A4B-E1D8D57146CC,DisplayName,subst
{1}

2EBFF24C-F2E7-4AC5-9A4B-E1D8D57146CC,FileGroups
{70818653-0707-4293-8F5F-8DCA8A0E97C4}

2EBFF24C-F2E7-4AC5-9A4B-E1D8D57146CC,Name
{Default Component}

2EBFF24C-F2E7-4AC5-9A4B-E1D8D57146CC,RequiredComponent
{Yes}

314C280D-877D-491E-BB79-D98AE5ACCE33,ExecuteAction
{Before Pane is Displayed}

314C280D-877D-491E-BB79-D98AE5ACCE33,State
{disabled}

314C280D-877D-491E-BB79-D98AE5ACCE33,Widget
{NextButton; CancelButton}

31A5F48D-8D72-4143-BCD1-92669852DB59,Background
{white}

31A5F48D-8D72-4143-BCD1-92669852DB59,Text,subst
{1}

31A5F48D-8D72-4143-BCD1-92669852DB59,Type
{checkbutton}

31A5F48D-8D72-4143-BCD1-92669852DB59,VirtualText
{LaunchApplication}

31A5F48D-8D72-4143-BCD1-92669852DB59,X
{185}

31A5F48D-8D72-4143-BCD1-92669852DB59,Y
{160}

370E1073-A18F-4970-BA92-404F995305C6,BackButton,subst
{1}

370E1073-A18F-4970-BA92-404F995305C6,CancelButton,subst
{1}

370E1073-A18F-4970-BA92-404F995305C6,Caption,subst
{1}

370E1073-A18F-4970-BA92-404F995305C6,Message,subst
{1}

370E1073-A18F-4970-BA92-404F995305C6,NextButton,subst
{1}

370E1073-A18F-4970-BA92-404F995305C6,Subtitle,subst
{1}

370E1073-A18F-4970-BA92-404F995305C6,Text,subst
{1}

370E1073-A18F-4970-BA92-404F995305C6,Title,subst
{1}

380E192B-915B-4066-A1D7-087B7F6F4BB5,CheckCondition
{Before Action is Executed}

380E192B-915B-4066-A1D7-087B7F6F4BB5,Filename
{<%ProgramExecutable%>}

3AF50345-7EA0-4E9A-B627-EC1737B67497,CheckCondition
{Before Action is Executed}

3AF50345-7EA0-4E9A-B627-EC1737B67497,String
{<%LaunchApplication%>}

40A63CB6-3BAE-4FDB-B2ED-D6E14CB3EC46,Alias
{Test Script}

40A63CB6-3BAE-4FDB-B2ED-D6E14CB3EC46,Conditions
{0 conditions}

40FCC4D0-83EF-4CEA-ACCB-E1DFBC9052CD,CheckCondition
{Before Action is Executed}

40FCC4D0-83EF-4CEA-ACCB-E1DFBC9052CD,String
{<%GuiMode%>}

4140D9DD-BA31-4311-9AC6-BE9D7EF220E4,Action
{Install Actions}

44AB3F02-67C0-4EE4-A576-ABDBBB645BFB,ExecuteAction
{Before Pane is Displayed}

44F39CB3-EECF-4F5E-BB87-AC68E465F86A,CheckCondition
{Before Action is Executed}

44F39CB3-EECF-4F5E-BB87-AC68E465F86A,Platform
{Windows}

45C7FCC1-EE4F-43DB-A4ED-BC9A82D62D24,BackButton,subst
{1}

45C7FCC1-EE4F-43DB-A4ED-BC9A82D62D24,CancelButton,subst
{1}

45C7FCC1-EE4F-43DB-A4ED-BC9A82D62D24,Caption,subst
{1}

45C7FCC1-EE4F-43DB-A4ED-BC9A82D62D24,Message,subst
{1}

45C7FCC1-EE4F-43DB-A4ED-BC9A82D62D24,NextButton,subst
{1}

45C7FCC1-EE4F-43DB-A4ED-BC9A82D62D24,Subtitle,subst
{1}

45C7FCC1-EE4F-43DB-A4ED-BC9A82D62D24,Text,subst
{1}

45C7FCC1-EE4F-43DB-A4ED-BC9A82D62D24,Title,subst
{1}

463A3DA5-8F2F-4E3F-9989-F2A71ED430F3,Alias
{Uninstall Actions}

464B2689-001B-4B53-8EDB-2F3FE169DCD4,CheckCondition
{Before Action is Executed}

464B2689-001B-4B53-8EDB-2F3FE169DCD4,Operator
{false}

464B2689-001B-4B53-8EDB-2F3FE169DCD4,String
{<%UpgradeInstall%>}

4C62C271-752B-4F3D-AD44-16C9FB036B92,CheckCondition
{Before Action is Executed}

4C62C271-752B-4F3D-AD44-16C9FB036B92,Operator
{false}

4C62C271-752B-4F3D-AD44-16C9FB036B92,String
{<%InstallStopped%>}

4E360EAF-AFA9-43E3-8CD0-4ED7755E0B10,CheckCondition
{Before Action is Executed}

4E360EAF-AFA9-43E3-8CD0-4ED7755E0B10,String
{<%CreateDesktopShortcut%>}

52FFBEDC-FDB4-4B97-B9F8-11514FE1079E,Background
{white}

52FFBEDC-FDB4-4B97-B9F8-11514FE1079E,Text,subst
{1}

52FFBEDC-FDB4-4B97-B9F8-11514FE1079E,Type
{checkbutton}

52FFBEDC-FDB4-4B97-B9F8-11514FE1079E,VirtualText
{CreateDesktopShortcut}

52FFBEDC-FDB4-4B97-B9F8-11514FE1079E,X
{185}

52FFBEDC-FDB4-4B97-B9F8-11514FE1079E,Y
{180}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,BackButton,subst
{1}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,BrowseButton,subst
{1}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,BrowseText,subst
{1}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,CancelButton,subst
{1}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,Caption,subst
{1}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,Destination,subst
{1}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,DestinationLabel,subst
{0}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,Message,subst
{1}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,NextButton,subst
{1}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,Subtitle,subst
{1}

57BFF0F0-BA4B-4235-A8BC-295E9FA03854,Title,subst
{1}

59A04F4F-C22B-42D7-A09F-D5A42C5119A4,BackButton,subst
{1}

59A04F4F-C22B-42D7-A09F-D5A42C5119A4,CancelButton,subst
{1}

59A04F4F-C22B-42D7-A09F-D5A42C5119A4,Caption,subst
{1}

59A04F4F-C22B-42D7-A09F-D5A42C5119A4,Message,subst
{1}

59A04F4F-C22B-42D7-A09F-D5A42C5119A4,NextButton,subst
{1}

614C6F65-6F31-4E32-A600-5831551BB045,ExitType
{Finish}

643FB86F-275B-4FD2-81EA-389F39C844E7,BackButton,subst
{1}

643FB86F-275B-4FD2-81EA-389F39C844E7,CancelButton,subst
{1}

643FB86F-275B-4FD2-81EA-389F39C844E7,Caption,subst
{1}

643FB86F-275B-4FD2-81EA-389F39C844E7,Message,subst
{1}

643FB86F-275B-4FD2-81EA-389F39C844E7,NextButton,subst
{1}

68BEF2C8-FB6D-46BC-9CBA-6069FC465EA3,BackButton,subst
{1}

68BEF2C8-FB6D-46BC-9CBA-6069FC465EA3,CancelButton,subst
{1}

68BEF2C8-FB6D-46BC-9CBA-6069FC465EA3,Caption,subst
{1}

68BEF2C8-FB6D-46BC-9CBA-6069FC465EA3,Message,subst
{1}

68BEF2C8-FB6D-46BC-9CBA-6069FC465EA3,NextButton,subst
{1}

696922E0-95C8-4E7A-83CB-BBDAEC62D5C3,CheckCondition
{Before Action is Executed}

696922E0-95C8-4E7A-83CB-BBDAEC62D5C3,Operator
{false}

696922E0-95C8-4E7A-83CB-BBDAEC62D5C3,String
{<%InstallStopped%>}

70818653-0707-4293-8F5F-8DCA8A0E97C4,Destination
{<%InstallDir%>}

70818653-0707-4293-8F5F-8DCA8A0E97C4,Name
{Program Files}

73075CC5-E757-4070-AE91-6DC5169E7252,CheckCondition
{Before Action is Executed}

73075CC5-E757-4070-AE91-6DC5169E7252,Filename
{<%ProgramExecutable%>}

7334F8BA-C35D-4F63-A926-901355FF1B37,ShortcutDirectory
{<%QUICK_LAUNCH%>}

7334F8BA-C35D-4F63-A926-901355FF1B37,ShortcutName
{<%AppName%>}

7334F8BA-C35D-4F63-A926-901355FF1B37,TargetFileName
{<%ProgramExecutable%>}

7334F8BA-C35D-4F63-A926-901355FF1B37,WorkingDirectory
{<%InstallDir%>}

74265BA6-3A1F-467B-8D14-E271AAF37FC2,CheckCondition
{Before Action is Executed}

74265BA6-3A1F-467B-8D14-E271AAF37FC2,Operator
{false}

74265BA6-3A1F-467B-8D14-E271AAF37FC2,String
{<%UpgradeInstall%>}

76F49002-DD56-42C0-8507-7240A570191F,CheckCondition
{Before Action is Executed}

76F49002-DD56-42C0-8507-7240A570191F,Filename
{<%ProgramExecutable%>}

7760979D-C999-41FE-9CF2-0F6E0E83CCC2,CheckCondition
{Before Action is Executed}

7760979D-C999-41FE-9CF2-0F6E0E83CCC2,Filename
{<%ProgramExecutable%>}

7C9F30F2-E42C-4AFC-BF88-BC0F80010078,Background
{white}

7C9F30F2-E42C-4AFC-BF88-BC0F80010078,Text,subst
{1}

7C9F30F2-E42C-4AFC-BF88-BC0F80010078,Type
{checkbutton}

7C9F30F2-E42C-4AFC-BF88-BC0F80010078,VirtualText
{LaunchApplication}

7C9F30F2-E42C-4AFC-BF88-BC0F80010078,X
{185}

7C9F30F2-E42C-4AFC-BF88-BC0F80010078,Y
{160}

7F12D2E6-6228-4549-B567-77B60756335E,BackButton,subst
{1}

7F12D2E6-6228-4549-B567-77B60756335E,CancelButton,subst
{1}

7F12D2E6-6228-4549-B567-77B60756335E,Caption,subst
{1}

7F12D2E6-6228-4549-B567-77B60756335E,Message,subst
{1}

7F12D2E6-6228-4549-B567-77B60756335E,NextButton,subst
{1}

8007933F-5291-49A8-9EED-5EFD237F0384,CheckCondition
{Before Action is Executed}

8007933F-5291-49A8-9EED-5EFD237F0384,Operator
{false}

8007933F-5291-49A8-9EED-5EFD237F0384,String
{<%InstallStopped%>}

804E20E3-FD50-4B8F-BA82-B8E0955A1394,Prompt
{<%ConsoleSelectDestinationText%>}

804E20E3-FD50-4B8F-BA82-B8E0955A1394,VirtualText
{InstallDir}

83BE8BB8-2F9B-4C43-BFBD-22D604F506AF,ExitType
{Finish}

86A81E43-CD88-4376-A0EC-1B648E239681,Action
{Uninstall Actions}

86D33DD4-5B24-4B32-A05E-B109573C00B4,Action
{Install Actions}

88B5489F-86AA-468A-A8AC-62FF9D6DC610,BackButton,subst
{1}

88B5489F-86AA-468A-A8AC-62FF9D6DC610,CancelButton,subst
{1}

88B5489F-86AA-468A-A8AC-62FF9D6DC610,Caption,subst
{1}

88B5489F-86AA-468A-A8AC-62FF9D6DC610,FileLabel,subst
{1}

88B5489F-86AA-468A-A8AC-62FF9D6DC610,Message,subst
{1}

88B5489F-86AA-468A-A8AC-62FF9D6DC610,NextButton,subst
{1}

88B5489F-86AA-468A-A8AC-62FF9D6DC610,ProgressValue,subst
{1}

88B5489F-86AA-468A-A8AC-62FF9D6DC610,Subtitle,subst
{1}

88B5489F-86AA-468A-A8AC-62FF9D6DC610,Title,subst
{1}

8B731604-25BD-4974-B646-74349BEA776A,Caption,subst
{1}

8B731604-25BD-4974-B646-74349BEA776A,CloseButton,subst
{1}

8B731604-25BD-4974-B646-74349BEA776A,Message,subst
{1}

8B731604-25BD-4974-B646-74349BEA776A,TextFile
{<%ProgramReadme%>}

8B731604-25BD-4974-B646-74349BEA776A,Title,subst
{1}

8DD6E5B5-BCD3-475B-9F50-EC650FF94706,Alias
{Startup Actions}

90C7003F-FAFB-40B2-86A4-25317C78399E,CheckCondition
{Before Action is Executed}

90C7003F-FAFB-40B2-86A4-25317C78399E,Filename
{<%ProgramReadme%>}

921ADE61-D25D-4841-AC79-A3F5DA939BC6,CheckCondition
{Before Action is Executed}

921ADE61-D25D-4841-AC79-A3F5DA939BC6,Operator
{false}

921ADE61-D25D-4841-AC79-A3F5DA939BC6,String
{<%InstallStopped%>}

92B694D9-2E0D-4B69-AB9D-8BDD02D2AA73,CheckCondition
{Before Action is Executed}

92B694D9-2E0D-4B69-AB9D-8BDD02D2AA73,Operator
{false}

92B694D9-2E0D-4B69-AB9D-8BDD02D2AA73,String
{<%InstallStopped%>}

931B2116-756F-48CE-ABDE-2E28B29DAB12,String1
{<%InstallType%>}

931B2116-756F-48CE-ABDE-2E28B29DAB12,String2
{Custom}

9321E964-C631-4011-BF00-6334F7B4581A,ExecuteAction
{Before Pane is Displayed}

9321E964-C631-4011-BF00-6334F7B4581A,State
{disabled}

9321E964-C631-4011-BF00-6334F7B4581A,Widget
{Back Button;Next Button}

939D4E35-19C0-4DA4-95D9-C017EA124455,Action
{Install Actions}

94D26118-7214-4D77-8701-81F50D758296,ProgramCommandLine
{<%ProgramExecutable%>}

94D26118-7214-4D77-8701-81F50D758296,WaitForProgram
{No}

94D26118-7214-4D77-8701-81F50D758296,WorkingDirectory
{<%InstallDir%>}

9641A6D0-7BB3-4746-91A2-45D0FBC9E5AE,Alias
{Install Actions}

965E5383-521A-421A-8EEA-A90DC53F1338,ExitType
{Finish}

974E41DB-EB24-4E2C-99C5-AF76EDC51BC2,Alias
{Cancel Actions}

981418EB-51B3-42A0-930B-BD513D82228D,CheckCondition
{Before Next Pane is Displayed}

981418EB-51B3-42A0-930B-BD513D82228D,FailureMessage
{<%DirectoryPermissionText%>}

981418EB-51B3-42A0-930B-BD513D82228D,Filename
{<%InstallDir%>}

981418EB-51B3-42A0-930B-BD513D82228D,Permission
{can create}

982C2E0B-6F81-46A0-BED8-E2D253F0E428,CheckCondition
{Before Action is Executed}

982C2E0B-6F81-46A0-BED8-E2D253F0E428,Operator
{false}

982C2E0B-6F81-46A0-BED8-E2D253F0E428,String
{<%Answer%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message,subst
{1}

99F6610C-8C0F-4475-A071-C06333A77675,CheckCondition
{Before Action is Executed}

99F6610C-8C0F-4475-A071-C06333A77675,Operator
{false}

99F6610C-8C0F-4475-A071-C06333A77675,String
{<%InstallStopped%>}

9E1AAF5C-749C-4840-9AAD-1082D55AE2E5,Alias
{Test Script}

9E1AAF5C-749C-4840-9AAD-1082D55AE2E5,Conditions
{0 conditions}

9E1AAF5C-749C-4840-9AAD-1082D55AE2E5,TclScript
{if {[info exists ::info(TestScript)]} {
    uplevel #0 [list source $::info(TestScript)]
}}

9ED2E111-A27B-4020-8F67-313619FCE5A3,CheckCondition
{Before Action is Executed}

9ED2E111-A27B-4020-8F67-313619FCE5A3,String
{<%GuiMode%>}

9EF3A047-ACCA-4263-9B80-94D3A88E5DEA,Comment
{Only display this pane if we have more than one Setup Type}

9EF3A047-ACCA-4263-9B80-94D3A88E5DEA,Script
{[llength [SetupTypes children]] > 1}

B03167BC-367B-4DDC-ACD4-E908C2938F7F,Background
{white}

B03167BC-367B-4DDC-ACD4-E908C2938F7F,Text,subst
{1}

B03167BC-367B-4DDC-ACD4-E908C2938F7F,Type
{checkbutton}

B03167BC-367B-4DDC-ACD4-E908C2938F7F,VirtualText
{ViewReadme}

B03167BC-367B-4DDC-ACD4-E908C2938F7F,X
{185}

B03167BC-367B-4DDC-ACD4-E908C2938F7F,Y
{140}

B28303E8-004A-43A3-AC76-414D134F94F9,ShortcutName
{<%AppName%>}

B28303E8-004A-43A3-AC76-414D134F94F9,TargetFileName
{<%ProgramExecutable%>}

B28303E8-004A-43A3-AC76-414D134F94F9,WorkingDirectory
{<%InstallDir%>}

B426A47D-01D9-42AC-95A7-D17A5409DC03,Alias
{Setup Actions}

B426A47D-01D9-42AC-95A7-D17A5409DC03,Conditions
{0 conditions}

B7E5A7C5-D456-4730-A506-6633873D2735,Action
{Uninstall Actions}

C11E1E67-57A7-4353-9FA0-36137288F0C6,Alias
{Cancel Actions}

C3EAFC25-F412-466E-95E7-C43F7045E895,Alias
{Finish Actions}

C642D7DE-A2EE-4E46-906D-5BB734E06C56,Comment
{Don't display this pane in an upgrade install}

C642D7DE-A2EE-4E46-906D-5BB734E06C56,Operator
{false}

C642D7DE-A2EE-4E46-906D-5BB734E06C56,String
{<%UpgradeInstall%>}

C72FB649-796D-40E1-AF3E-618BD4880127,Background
{white}

C72FB649-796D-40E1-AF3E-618BD4880127,Text,subst
{1}

C72FB649-796D-40E1-AF3E-618BD4880127,Type
{checkbutton}

C72FB649-796D-40E1-AF3E-618BD4880127,VirtualText
{CreateDesktopShortcut}

C72FB649-796D-40E1-AF3E-618BD4880127,X
{185}

C72FB649-796D-40E1-AF3E-618BD4880127,Y
{180}

C9EA4191-53BC-413B-90CC-63B584DE60B2,CheckCondition
{Before Action is Executed}

C9EA4191-53BC-413B-90CC-63B584DE60B2,Filename
{<%ProgramExecutable%>}

CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5,BackButton,subst
{1}

CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5,CancelButton,subst
{1}

CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5,Caption,subst
{1}

CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5,FileValue,subst
{1}

CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5,Message,subst
{1}

CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5,NextButton,subst
{1}

CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5,ProgressValue,subst
{1}

CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5,Subtitle,subst
{1}

CBD29A25-CDB5-45BE-AC62-8926E9B6CEB5,Title,subst
{1}

CC91317C-EDE0-429E-879D-810CF3ECDD0A,ShortcutName
{<%AppName%>}

CC91317C-EDE0-429E-879D-810CF3ECDD0A,TargetFileName
{<%ProgramExecutable%>}

CC91317C-EDE0-429E-879D-810CF3ECDD0A,WorkingDirectory
{<%InstallDir%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message,subst
{1}

CE85FAF5-6C87-48A4-A8CC-236F5670A605,CheckCondition
{Before Action is Executed}

CE85FAF5-6C87-48A4-A8CC-236F5670A605,Message,subst
{1}

CE85FAF5-6C87-48A4-A8CC-236F5670A605,Title,subst
{1}

CE85FAF5-6C87-48A4-A8CC-236F5670A605,TrueValue
{No}

CED955F7-7B89-4D7B-B62E-FF39D97FE39B,Action
{Install Actions}

D5044EB4-D57C-4744-B46D-05FB8BDA9979,ExecuteAction
{Before Pane is Displayed}

D5044EB4-D57C-4744-B46D-05FB8BDA9979,State
{disabled}

D5044EB4-D57C-4744-B46D-05FB8BDA9979,Widget
{Back Button;Next Button}

D5FCE600-561B-46E6-ACAE-67185E3A3D2C,BackButton,subst
{1}

D5FCE600-561B-46E6-ACAE-67185E3A3D2C,CancelButton,subst
{1}

D5FCE600-561B-46E6-ACAE-67185E3A3D2C,Caption,subst
{1}

D5FCE600-561B-46E6-ACAE-67185E3A3D2C,FileLabel,subst
{1}

D5FCE600-561B-46E6-ACAE-67185E3A3D2C,Message,subst
{1}

D5FCE600-561B-46E6-ACAE-67185E3A3D2C,NextButton,subst
{1}

D5FCE600-561B-46E6-ACAE-67185E3A3D2C,ProgressValue,subst
{1}

D5FCE600-561B-46E6-ACAE-67185E3A3D2C,Subtitle,subst
{1}

D5FCE600-561B-46E6-ACAE-67185E3A3D2C,Title,subst
{1}

D7B22071-C6D5-439E-ABBC-454A317BEBD7,CheckCondition
{Before Action is Executed}

D7B22071-C6D5-439E-ABBC-454A317BEBD7,Filename
{<%ProgramExecutable%>}

D98FCD0E-BA23-44E1-B688-78CE3AB7F8BC,CheckCondition
{Before Action is Executed}

D98FCD0E-BA23-44E1-B688-78CE3AB7F8BC,Filename
{<%ProgramExecutable%>}

DB1D9C02-507C-4706-B6E2-538C9BBF83EE,CheckCondition
{Before Action is Executed}

DB1D9C02-507C-4706-B6E2-538C9BBF83EE,String
{<%GuiMode%>}

DC5F8F72-5665-4EA7-AC40-DD103BA19818,Components
{2EBFF24C-F2E7-4AC5-9A4B-E1D8D57146CC}

DC5F8F72-5665-4EA7-AC40-DD103BA19818,Description,subst
{1}

DC5F8F72-5665-4EA7-AC40-DD103BA19818,DisplayName,subst
{1}

DC5F8F72-5665-4EA7-AC40-DD103BA19818,Name
{Custom}

E230B57B-6C55-46B8-974C-CCAD003267D2,Background
{white}

E230B57B-6C55-46B8-974C-CCAD003267D2,Text,subst
{1}

E230B57B-6C55-46B8-974C-CCAD003267D2,Type
{checkbutton}

E230B57B-6C55-46B8-974C-CCAD003267D2,VirtualText
{ViewReadme}

E230B57B-6C55-46B8-974C-CCAD003267D2,X
{185}

E230B57B-6C55-46B8-974C-CCAD003267D2,Y
{140}

E6B908CC-AA78-4001-A303-064F73FB61FD,CheckCondition
{Before Action is Executed}

E6B908CC-AA78-4001-A303-064F73FB61FD,Operator
{false}

E6B908CC-AA78-4001-A303-064F73FB61FD,String
{<%InstallStopped%>}

E6D1058D-A0C6-4404-B29B-34324F32282F,Default
{Yes}

E6D1058D-A0C6-4404-B29B-34324F32282F,Prompt
{<%UninstallStartupText%>}

E71E10BF-8B60-41DE-89CB-A770DDA50763,CheckCondition
{Before Action is Executed}

E71E10BF-8B60-41DE-89CB-A770DDA50763,String
{<%CreateQuickLaunchShortcut%>}

E727D6FE-2D34-464D-AC50-5B6FDA45F94B,CheckCondition
{Before Action is Executed}

E727D6FE-2D34-464D-AC50-5B6FDA45F94B,Operator
{false}

E727D6FE-2D34-464D-AC50-5B6FDA45F94B,String
{<%UpgradeInstall%>}

E8D5F0F3-3A25-4E39-B0D1-D01D58A1AFB3,Alias
{Finish Actions}

EABAF583-B4B6-46E0-BC8C-2BFCEFEA3161,Comment
{Ask the user if they want to proceed with the uninstall.}

EABAF583-B4B6-46E0-BC8C-2BFCEFEA3161,Conditions
{2 conditions}

EC8FA828-EB62-49DD-8CEB-371945D6727B,CheckCondition
{Before Next Action is Executed}

EC8FA828-EB62-49DD-8CEB-371945D6727B,FailureMessage
{<%DirectoryPermissionText%>}

EC8FA828-EB62-49DD-8CEB-371945D6727B,Filename
{<%InstallDir%>}

EC8FA828-EB62-49DD-8CEB-371945D6727B,Permission
{can create}

F4A0FD07-2ED7-45B4-A58D-88925E06CA01,CheckCondition
{Before Action is Executed}

F4A0FD07-2ED7-45B4-A58D-88925E06CA01,Platform
{Windows}

FA00CE55-9437-4796-AC47-642DFBB72991,CheckCondition
{Before Action is Executed}

FA00CE55-9437-4796-AC47-642DFBB72991,String
{<%ViewReadme%>}

FC987119-4BF9-406E-B31D-49EFBB1793E8,Active
{Yes}

FC987119-4BF9-406E-B31D-49EFBB1793E8,BackButton,subst
{1}

FC987119-4BF9-406E-B31D-49EFBB1793E8,CancelButton,subst
{1}

FC987119-4BF9-406E-B31D-49EFBB1793E8,Caption,subst
{1}

FC987119-4BF9-406E-B31D-49EFBB1793E8,DescriptionLabel,subst
{0}

FC987119-4BF9-406E-B31D-49EFBB1793E8,Message,subst
{1}

FC987119-4BF9-406E-B31D-49EFBB1793E8,NextButton,subst
{1}

FC987119-4BF9-406E-B31D-49EFBB1793E8,Subtitle,subst
{1}

FC987119-4BF9-406E-B31D-49EFBB1793E8,Title,subst
{1}

FDE4744C-A20D-4A5A-99EB-37983CEEEC8B,Alias
{Startup Actions}

FDE4744C-A20D-4A5A-99EB-37983CEEEC8B,Conditions
{0 conditions}

FEA2C975-1D24-4801-8396-ADD267808D3E,Background
{white}

FEA2C975-1D24-4801-8396-ADD267808D3E,Text,subst
{1}

FEA2C975-1D24-4801-8396-ADD267808D3E,Type
{checkbutton}

FEA2C975-1D24-4801-8396-ADD267808D3E,VirtualText
{CreateQuickLaunchShortcut}

FEA2C975-1D24-4801-8396-ADD267808D3E,X
{185}

FEA2C975-1D24-4801-8396-ADD267808D3E,Y
{200}

TarArchive,Active
{No}

TarArchive,BuildSeparateArchives
{No}

TarArchive,CompressionLevel
{6}

TarArchive,DefaultDirectoryPermission
{0755}

TarArchive,DefaultFilePermission
{0755}

TarArchive,Executable
{<%AppName%>-<%Version%>-<%Platform%>-Install<%Ext%>}

TarArchive,FallBackToConsole
{Yes}

TarArchive,InstallDir
{<%Home%>/<%ShortAppName%>}

TarArchive,InstallMode
{Standard}

TarArchive,InstallType
{Typical}

TarArchive,OutputFileName
{<%ShortAppName%>-<%Version%>.tar.gz}

TarArchive,ProgramExecutable
{}

TarArchive,ProgramFolderAllUsers
{No}

TarArchive,ProgramFolderName
{<%AppName%>}

TarArchive,ProgramLicense
{<%InstallDir%>/LICENSE.txt}

TarArchive,ProgramName
{}

TarArchive,ProgramReadme
{<%InstallDir%>/README.txt}

TarArchive,PromptForRoot
{Yes}

TarArchive,RequireRoot
{No}

TarArchive,RootInstallDir
{/usr/local/<%ShortAppName%>}

TarArchive,VirtualTextMap
{<%InstallDir%> <%ShortAppName%>}

Windows,Active
{Yes}

Windows,BuildSeparateArchives
{No}

Windows,Executable
{<%AppName%>-<%Version%>-Setup<%Ext%>}

Windows,FileDescription
{<%AppName%> <%Version%> Setup}

Windows,IncludeTWAPI
{No}

Windows,InstallDir
{<%PROGRAM_FILES%>/<%AppName%>}

Windows,InstallMode
{Standard}

Windows,InstallType
{Typical}

Windows,LastRequireAdministrator
{Yes}

Windows,ProgramExecutable
{}

Windows,ProgramFolderAllUsers
{No}

Windows,ProgramFolderName
{<%AppName%>}

Windows,ProgramLicense
{<%InstallDir%>/LICENSE.txt}

Windows,ProgramName
{}

Windows,ProgramReadme
{<%InstallDir%>/README.txt}

Windows,RequireAdministrator
{Yes}

Windows,UseUncompressedBinaries
{No}

Windows,WindowsIcon
{Setup Blue Screen.ico}

ZipArchive,Active
{No}

ZipArchive,BuildSeparateArchives
{No}

ZipArchive,CompressionLevel
{6}

ZipArchive,DefaultDirectoryPermission
{0755}

ZipArchive,DefaultFilePermission
{0755}

ZipArchive,Executable
{<%AppName%>-<%Version%>-<%Platform%>-Install<%Ext%>}

ZipArchive,FallBackToConsole
{Yes}

ZipArchive,InstallDir
{<%Home%>/<%ShortAppName%>}

ZipArchive,InstallMode
{Standard}

ZipArchive,InstallType
{Typical}

ZipArchive,OutputFileName
{<%ShortAppName%>-<%Version%>.zip}

ZipArchive,ProgramExecutable
{}

ZipArchive,ProgramFolderAllUsers
{No}

ZipArchive,ProgramFolderName
{<%AppName%>}

ZipArchive,ProgramLicense
{<%InstallDir%>/LICENSE.txt}

ZipArchive,ProgramName
{}

ZipArchive,ProgramReadme
{<%InstallDir%>/README.txt}

ZipArchive,PromptForRoot
{Yes}

ZipArchive,RequireRoot
{No}

ZipArchive,RootInstallDir
{/usr/local/<%ShortAppName%>}

ZipArchive,VirtualTextMap
{<%InstallDir%> <%ShortAppName%>}

}

::msgcat::mcmset ca {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset cs {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset de {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset en {
018814A4-A7CB-4498-86A5-2CA7DA217D8F,Text
{<%CreateQuickLaunchShortcutText%>}

22DAD4C7-23EA-4B36-8957-CE5FFE3F95B2,Description
{<%TypicalInstallDescription%>}

25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

2EBFF24C-F2E7-4AC5-9A4B-E1D8D57146CC,Description
{<%ProgramFilesDescription%>}

31A5F48D-8D72-4143-BCD1-92669852DB59,Text
{<%LaunchApplicationText%>}

50D39F94-72B5-48C1-9C52-EBC283908B6F,Message
{<%InstallStartupText%>}

50D39F94-72B5-48C1-9C52-EBC283908B6F,Title
{<%InstallApplicationText%>}

52FFBEDC-FDB4-4B97-B9F8-11514FE1079E,Text
{<%CreateDesktopShortcutText%>}

7C9F30F2-E42C-4AFC-BF88-BC0F80010078,Text
{<%LaunchApplicationText%>}

8B731604-25BD-4974-B646-74349BEA776A,Caption
{<%ApplicationReadmeText%>}

8B731604-25BD-4974-B646-74349BEA776A,Message
{}

8B731604-25BD-4974-B646-74349BEA776A,Title
{<%ApplicationReadmeText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

B03167BC-367B-4DDC-ACD4-E908C2938F7F,Text
{<%ViewReadmeText%>}

C72FB649-796D-40E1-AF3E-618BD4880127,Text
{<%CreateDesktopShortcutText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

CE85FAF5-6C87-48A4-A8CC-236F5670A605,Message
{<%UninstallStartupText%>}

CE85FAF5-6C87-48A4-A8CC-236F5670A605,Title
{<%UninstallApplicationText%>}

DC5F8F72-5665-4EA7-AC40-DD103BA19818,Description
{<%CustomInstallDescription%>}

E230B57B-6C55-46B8-974C-CCAD003267D2,Text
{<%ViewReadmeText%>}

FEA2C975-1D24-4801-8396-ADD267808D3E,Text
{<%CreateQuickLaunchShortcutText%>}

}
::msgcat::mcmset es {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset fr {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset hu {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset it {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset lt {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset nl {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset pl {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset pt_br {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}
::msgcat::mcmset ru {
25F80124-CD10-4EA8-AAD0-18985025B310,Message
{<%UninstallCompleteText%>}

29218D4F-A773-4377-ACC7-8D7ECEB5F281,Message
{<%InstallationCompleteText%>}

98F10689-CF62-408F-8CFF-90B481AB8919,Message
{<%UninstallingApplicationText%>}

CE1358E6-09F7-4984-B40A-1BDF4A9358A0,Message
{<%InstallingApplicationText%>}

}

Added tests/test1.test.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
test test-1.0 {Build a basic installer} -body {
    buildInstaller
    file exists $::env(IJTEST_INSTALLER)
} -result {1}

test test-1.1 {Test a basic installer} -body {
    runInstallerTest {
        inject after Welcome {
            test_pressButton "Next >"
        }

        inject after SelectDestination {
            test_pressButton "Next >"
        }

        inject after SetupType {
            test_pressButton "Next >"
        }

        inject after StartCopyingFiles {
            test_pressButton "Next >"
        }

        inject after SetupComplete {
            test_pressButton "Finish"
        }
    }

    if {![file exists $info(InstallInfoDir)]} {
        return -code error "Registry directory not created"
    }

    cd $info(InstallInfoDir)
    if {![file exists $info(ApplicationID).info]} {
        return -code error ".info file not created"
    }

    if {![file exists $info(ApplicationID).log]} {
        return -code error ".log file not created"
    }
}
Added tests/utils.tcl.










































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
catch {wm withdraw .}
set ::env(IJTEST_DIR) [file normalize [file dirname [info script]]]
set ::env(IJTEST_TMP) [file join $::env(IJTEST_DIR) tmp]
set ::env(IJTEST_BIN) \
    [file normalize [file join $::env(IJTEST_DIR) .. installjammer]]

proc test {name desc args} {
    array set _args $args

    echo "$desc"
    set code [catch {uplevel #0 $_args(-body)} result]

    if {$code == 1} {
        return -code error $result
    }

    cd $::env(IJTEST_DIR)
}

proc echo {string} {
    puts  stdout $string
    flush stdout
}

proc readFile {file} {
    set fp [open $file]
    set x  [read $fp]
    close $fp
    return $x
}

proc makeDirectory {dir} {
    variable test
    if {![file exists $dir]} { file mkdir $dir }
    lappend test(dirs) $dir
}

proc project {project} {
    global info

    unset -nocomplain ::env(IJTEST_PROJECT)

    set mpi $project
    if {[file isdir $project]} { set mpi [file join $project $project.mpi] }
    if {![file exists $mpi]} { return }
    set ::env(IJTEST_PROJECT) $project

    uplevel #0 [list catch [list source $mpi]]
}

proc buildInstaller {args} {
    if {[info exists ::env(IJTEST_INSTALLER)]} {
        return $::env(IJTEST_INSTALLER)
    }
    eval rebuildInstaller $args
}

proc rebuildInstaller {args} {
    makeDirectory build
    makeDirectory output

    set project $::env(IJTEST_PROJECT)

    set opts [list]
    lappend opts --build-dir [file join $::env(IJTEST_DIR) build]
    lappend opts --output-dir [file join $::env(IJTEST_DIR) output]
    lappend opts --build-log-file [file join $::env(IJTEST_DIR) build build.log]
    eval lappend opts $args
    lappend opts --build [file join $::env(IJTEST_DIR) $project]
    set result [eval exec [list $::env(IJTEST_BIN)] $opts]

    if {[regexp {Installer: ([^\n]+)} $result -> installer]} {
        set ::env(IJTEST_INSTALLER) $installer
        return $installer
    }
}

proc runInstallerTest {script args} {
    if {![info exists ::env(IJTEST_INSTALLER)]} {
        if {![info exists ::env(IJTEST_PROJECT)]} {
            return -code error "could not find test installer"
        }
        buildInstaller $::env(IJTEST_PROJECT)
    }

    makeDirectory $::env(IJTEST_TMP)

    set tmp [file join $::env(IJTEST_TMP) script]
    set fp [open $tmp w]
    puts $fp $script
    puts $fp {
        ## Add an exit event to dump the info array for testing.
        inject enter exit {
            puts "array set info [list [array get info]]"
        }
    }
    close $fp

    set installer $::env(IJTEST_INSTALLER)
    catch {eval exec [list $installer --test-script $tmp] $args} res
    if {[string match "array set info*" $res]} { uplevel #0 $res }
}

proc runBuilderTest {script} {
    variable test

    if {![info exists test(builderSock)]} {
        set port 60006
        exec $::env(IJTEST_BIN) --command-port $port -- &
        set test(builderSock) [socket localhost $port]
        gets $test(builderSock) line
    }

    puts  $test(builderSock) $script
    flush $test(builderSock)
    set response {}
    while {[gets $test(builderSock) line] != -1} {
        if {$line eq "OK"} { break }
        lappend response $line
    }
    return [join $response \n]
}

proc runAllTests {} {
    foreach file [glob -nocomplain *.test] {
        echo "===== $file ====="
        project [file root $file].mpi
        uplevel #0 [list source $file]
        unset -nocomplain ::env(IJTEST_INSTALLER)
    }

    cleanupTests
    exit
}

proc cleanupTests {} {
    variable test

    if {[info exists test(builderSock)]} {
        puts  $test(builderSock) exit
        flush $test(builderSock)
    }

    if {[info exists test(dirs)]} {
        foreach dir $test(dirs) {
            file delete -force $dir
        }
    }
}